The Four Pillars of a Good Software Developer
I've recently been working on another enterprise web application from the ground up, which gave me a chance to apply some of "my" habits to a blank canvas. They're not really "my" habits, rather an aggregation of the countless books, blogs and videos I've consumed regarding the developer craft, best practices, design patterns and so on.
I formulated these habits into what I believe to be the four pillars that make up good software development:
- Code Quality
- Code Correctness
- Code Performance
- Code Productivity
These four pillars are not mutually exclusive. My experience to date has always suggested a little more emphasis on productivity. We've all heard the line "oh, just get it done for now, we can always come back later and refactor": this of course, never happens. This shift towards getting things done I can understand as developer hours cost money and deadlines are looming, however nine times out of ten this always comes at a cost of the three other pillars: quality, correctness and performance. Skip ahead five years on this project and you end up with a brittle code base, performance problems, lots of bugs and a terrible time trying to keep the software current. Now where is the productivity?
Shift back five years on this same project and do things "properly" by unit testing everything - including property getters and setters (don't forget constructors), applying every GoF and/or Fowler pattern that you can fit, endlessly obsessing if "for each" is slower than "for (i.." with a sprinkling of IDE plug-ins such as StyleCop, CheckStyle or JSLint and things should be looking pretty good. The only issue is there might not be a next year as your web application may not ship on time and you may end up seeking employment elsewhere. Excessive rules, tools and processes have spelt near disaster for productivity on every project I have been involved.
So what's the happy medium?
My vision of optimal is in the centre spot of the Venn diagram below. It's difficult to stay in the middle spot all the time, but try we must:
Venn Diagram of the Four Pillars
If I can stay in the centre spot I'm usually a happy developer. The projects I found frustrating to work on have generally been lacking in one or more of these pillars: E.g. lacking in proper testing either with unit tests or automation tests, non existent code quality or having to manually build and deploy solutions.
Each section that follows details some useful ideas and links to further information for each pillar:
Code that is easy to comprehend and be modified by a developer who didn't write it.
Code quality is a very subjective area. For me, code quality means consistency. Consistently bad is not ideal, but consistency is key. There are so many elements that comprise code quality such as class, variable, property and method names, use of tabs vs. spacing, use of braces, brackets, correct usage of design patterns and so on. The biggest reason for code quality is maintainability. If you only had to write some code once and never revisit it, then it wouldn’t be so important. The vast discipline of design patterns ultimately support the principle of maintainability. Maintenance = Cost.
I suggest taking a look at the book Code Complete, if you haven't already. At the time of writing it is top of the list in the answer to the Stackoverflow question "What is the single most influential book every programmer should read?".
If you don't already have a coding standards document, then create one. There is contention here that this could slow the developer process down to firstly create the document and secondly to have the developers adhere to the standards. Productivity can be reclaimed by the introduction of IDE plug-ins such as StyleCop, FxCop, CheckStyle and JSLint. I have a love/hate relationship with these type of plug-ins as I sometimes have flash backs of refactoring somebody else's code written prior to usage of such plugins and having to wade through 500+ compiler errors from working code, albeit badly formatted.
Code reviews are another useful process for attaining good code quality. I'm aware that this is yet another process, and too many processes can kill productivity, but I think an exception should be made for the introduction of code/peer reviews. Studies such as the Hawthorne Effect suggest some improved metric in performance if an employee is aware the work they are producing is going to be assessed. Another fun approach I've heard is to imagine that a serial killer will be reviewing your code - do you want the serial killer to come to your home and ask you for clarification about your code?
Code that meets its functional requirements and behaves as expected regardless of implementation detail.
Any method of obtaining feedback helps to maintain correctness. Feedback can come in many forms whether it be another person reviewing your code, testing it or talking over the functionality. It could also be the use of computers to give feedback, by way of unit testing, automated testing or using some kind of digital checklist to ensure that your code meets its objectives. There can never be too much feedback and the faster the response time between change and feedback the better.
I'm a huge fan of TDD and BDD. Whichever you choose will be down to a matter of preference, there are advantages and disadvantages to each approach. Whichever approach you choose, you will end up with a suite of tests that will act as a safety net when
introducing new bugs adding new functionality in the future. I also love to write unit tests for my code due to the feedback loop. The increased response between making the change and verifying correctness with a unit test is something I cannot live without. Gone are the days of making a code change, compiling, opening the browser, navigating to the correct point, verifying the change and then rinsing and repeating n times.
If your project has a UI e.g. a web application, I strongly recommend creating full integration tests via the browser using tools like Selenium or Watin. You can create tests to check the main flow of the application e.g. for an e-commerce website, adding a product to a basket and checking out would be a great automated test. Having the build break if such a test fails acts as the backbone to correctness. If you have to choose only one testing methodology I strongly recommend choosing this over TDD and BDD.
The execution speed and memory consumption of code.
Don't Be Evil
I often hear the phrase "premature optimisation is the root of all evil" when it comes to writing performant code, however I don't fully agree with the statement. I think you need to be a little aware of the performance of your application as you go. For example picking the wrong data structure or badly designing the database from the offset would create a huge problem. Experience is a huge contributing factor to this pillar and the bad news for us is that experience = mistakes.
Focussing too much on this pillar comes at the expense of your code productivity and quality.
How quickly you can produce working code.
Master Your IDE
I always strive to apply the 80/20 rule when faced with repetitive tasks. Mastering your IDE is a great starting point to being more productive. Learning the shortcut keys for the actions you perform 80% of the time e.g. creating new files, navigating files, running unit tests etc will turn you into a productivity Ninja.
Knowing yourself is an important part of being productive. Understanding how and when you get distracted and being aware of your bad habits are just as important as knowing your IDE inside out. For me the starting point of procrastination is opening iTunes, I could easily lose ten minutes when I open the iTunes interface, so I don't… or at least I try not to!
Combining the Quadrants
Trying to be mindful of all four pillars whilst writing code is a challenge and becomes easier with experience. It cannot be forced and regardless of how many books read or screen casts watched, it's only by making mistakes that we can often realise what's great and not so great. Continually reviewing each quadrant and introducing minor changes will help us take baby steps towards the sweet spot in the center of the venn diagram. And besides, you won't be able to break anything along the way - your unit tests will catch any new bugs!
There is a slight bias towards .Net development in the links to further information I have posted. Please leave a comment if there are any missing tools that you feel would compliment this list.
FxCop (Visual Studio)
StyleCop (Visual Studio)
CheckStyle (Eclipse IDE/Java)
ReviewBoard (Take the pain out of code reviews)
Team Foundation Server 2012 Code Reviews. TFS now has integrated code review features.
Refactoring: Improving the Design of Existing Code (The 3rd Chapter of this book is dedicated to detecting "code smells")
TDD Master Class (paid screen cast)
Behavior-driven Design with Specflow (free screen cast)
Watin project page (Web Application Testing In .Net)
Selenium project page (Selenium automates browsers. That's it)
10 Tips for Writing High-Performance Web Applications (ASP.Net. A little old but still has good information)
Making simple benchmarks (my own mini library I use for benchmarks but I try not to use this too much as, you know, premature optimisation is the root of all evil!)
Resharper from Jetbrains (Developer productivity tool for visual studio)
Visual studio 2010 keyboard shortcuts. (Each time you reach for the mouse and don't use the keyboard, something bad will happen)
Code Generation and T4 Text Templates (Visual Studio)
Which build tool? (.Net specific Stackoverflow Q&A)
Team Foundation Server TFS 2010 and higher makes integrated build automation very easy.
Personal Productivity Tips Presentation (Video from Scott Hanselman)
I wasn't going to mention source control as I believe most companies use it in some form, however it has brought back
nightmares memories of a few projects ago where a company was managing code via a shared folder. Granted they were vigilant with backups but the entire process of finding code to work with and not overlapping somebody else's changes was so cumbersome.
What is modern software development? (See point #1 of the post)