Software development best practices

There is a lot more to good software development than just knowing the syntax of a programming language. This is my attempt to compile a list of best practices covering all aspects of software development. (My background is in enterprise application development so the list is oriented towards that and some of it is less applicable for solution development or web development.)

If you know any useful tips or best practices that I haven’t listed, please comment!

Different kinds of software development

There are different sorts of software development and the optimal approach is slightly different for each one.

Kind of development What is it? Important characteristics
Application Developing an application for multiple users. Could be a “boxed” software product or software as a service. Lots of code, often millions of lines. Design is highly complex and time consuming, as code will be used by multiple users with varying requirements, so needs to be highly flexible. Application will be composed of large scale components. Long application lifetime, e.g. 15 years. Hence large amount of effort required to maintain and update existing code, as opposed to developing new functionality from scratch. Effort/reward ratio for automated testing is high. Documentation, both in code and external is very important.
Solution Developing bespoke solutions for individual clients. Design is typically easier than application development, as code can be bespoke to specific customer. Testing and documentation approach may depend on whether your business is maintaining the solution after the initial delivery. Automated testing may be more useful for the initial development of functionality as opposed to for regression testing.
Web Developing a browser based UI, either for an application or as part of solution development. Code is split between server side (e.g. JSPs, PHP) and client side (html, css, javascript). On the server side, code reuse can be achieved by e.g. JSP tags, on the client side by javascript functions. Automated testing could mean web testing (e.g. selenium) or javascript testing (e.g. QUnit).

Architecture (large scale)

  1. An enterprise application should always be split into components, which should be loosely coupled, and can be built and/or tested independently. For a typical app, you should expect to have 5-15 components, with each one between 10-100kloc. Java hasn’t traditionally had a good architecture for components, as EJBs are too finely grained. OSGi is probably the best choice, but it is still in its infancy, so you might be better just making good use of interfaces to design your components.
  2. Many applications have several ways they can be accessed. e.g. web browser, desktop app, web services, file exchange. In this scenario, all of your useful code should be in the core app (probably in EJBs or Spring beans) and each API should just be a thin layer.
  3. Whenever you integrate a third party library or application, always write an abstraction layer over it. Otherwise you’ll kick yourself two years later when you need to replace the third party code and discover you have references to it in 500 classes.
  4. For logging, use SLF4J as a facade so that you and your customers can plug in a logging framework as needed.

Coding (small scale)

  1. Code to interfaces, not concrete classes. You make it much harder to update your code if you don’t use interfaces. My default approach is: an interface to define the contract, an abstract class to contain functionality that I can already see is reusable, then the concrete classes. When you need to add new functionality in the future, if it is close to what you already have, you can write a new class that extends your abstract class, but if it is noticeably different, you can write an entirely new class without breaking the contract with the calling code.
  2. Favour composition over inheritance. Inheritance fundamentally breaks the concept of a public API. e.g. you override several methods in a class. each one invokes the superclass method to perform some of its processing. Sounds okay right? But…for one of the methods, the super class method internally invokes a different method, which you’ve overridden. The process of dynamic dispatch means that it invokes your new version of the method, and the code falls over…
  3. Think twice about coding helper classes. An OO approach suggests that you might need to reconsider your object hierarchy and push the functionality down into the correct classes. (Thanks to: http://www.carlopescio.com/2011/04/your-coding-conventions-are-hurting-you.html)
  4. A method should only do one thing. When designing an algorithm, it should be broken down into small steps, each of which becomes a separate method. A top level method can then call each of these methods in turn to perform the required task.
  5. Methods should be short. As a rule of thumb, most methods should be fewer than 20 lines. If you are writing a method and it gets longer than this, it indicates that you’re trying to do too much in one method. Split it into multiple methods.
  6. Don’t use instance variables to share state between methods unless you really have to. By doing this you are giving all methods in the class access to it, but it might only be required by some of them. Generally, try to use the return value of the method to return data required by the calling code.
  7. All or most data required by a method should be passed in as parameters, rather than being accessed within the method. This is for two reasons:
    1. It makes it easier for the caller to see what data the method requires.
    2. It makes the method easier to unit test.
  8. If you need to provide several methods or constructors that do similar things but take different parameters, put the implementation in one method and have the other methods call it, rather than copying the implementation code into several methods. (Method chaining.)
  9. Methods shouldn’t have side effects. i.e. they should do what the method signature implies they should do, no more, no less.
  10. Don’t design or write code that includes “special cases”. There are two related reasons for this: Firstly, the special case code is usually hidden within a method, so other developers can’t tell that it exists and won’t understand how the code works. Secondly, once you have introduced the special case in one part of your code, it will have to be added to other sections of code as the application grows. This is a bug waiting to happen as (because of point one) other developers won’t know about your special case so won’t account for it.The correct thing to do is to push the special case functionality down into the class that requires it, so that it happens automatically when the calling code calls the appropriate method on the object.

Performance

I think its hard to generalise about how to write performant code, but here are some pointers:

  1. For code that is querying a database and processing the result of the query, you need to maximise the amount of useful data you get in the initial query, minimise the amount of unnecessary data and minimise the additional processing that you need to do on the query results to get what you need. There is no need to instantiate large numbers of objects and perform processing on them if you can actually get the end result simply by writing a better database query.
  2. Any code that accesses large numbers of database records should retrieve them in batches to keep the memory footprint low.
  3. Use database indexes to reduce lookup times for fields that are commonly used for retrieval.
  4. Does the code you’re writing actually need to run in real time? Or could it be done asynchronously? e.g. either the user initiates it and gets the result later, or the action is performed periodically and the user just views the results of the latest run
  5. For web apps, Apache Bench is great for simple performance testing.

Development processes

  1. For all new functionality, the specification should be written based on a specification template. I’d recommend making the template as detailed as possible. If sections don’t apply, the developer can mark them as such, but if they miss something crucial you’ll be in trouble later. As well as the obvious requirements, design, code changes etc, you might like to include: assumptions and limitations, security, performance, automated testing, configuration parameters, database changes and interaction with third party systems.
  2. Use an issue review process and/or issue template. It means that even issues which don’t fall into the category of requiring a specification (like bug fixes) are still checked.

Testing

  1. Use automated testing to test all of your code. I recommend using Test Driven Development (TDD) as it helps developers to tie down how the code should behave, explore all of the variations of input parameters and means that code can be tested as soon as it is written. My recommended approach is:
    1. Write your unit tests, system tests and empty application classes.
    2. Run all of your tests and confirm they fail.
    3. Start writing your application code from the inside out – first write the methods that can be unit tested and rerun the unit tests. Then, when you get to writing the code that can only be tested by running your system tests, if the tests fail, you know the error can only be in the portions of code that aren’t covered by your unit tests.
  2. I recommend TestNG rather than JUnit, as it provides much better support for data driven testing and has a number of other features that JUnit doesn’t have.
  3. If your app has a web API, you’ll probably need web testing as well as code level testing. I recommend Selenium.
  4. You want to be able to run your tests quickly and easily, so as many of them as possible should be unit tests that only need the compiled class under test,  rather than system tests, that need your entire app running. Remember you can use mocks, stubs and in-memory databases to make more of your tests into unit tests. The TestNG book has lots of good info on this.
  5. Use a code coverage tool like Emma or Cobertura. Personally I’d recommend always having 100% coverage. You might think that it’s unnecessary to get 100% as some of your code is just getters and setters, but if you don’t write tests for these methods, it is very difficult to see if you really have got tests for all of your code. Writing tests for getters and setters is very quick so it pays for itself.
  6. Use static analysis testing as well as runtime testing. It is fast to run and has the advantage that once you have configured the rules you are going to apply to your code, they will run against new code automatically. I recommend PMD and FindBugs. I tend not to use CheckStyle as it is mostly stylistic, rather than finding real bugs. PMD is good because its easy to write your own rules so if you can identify conditions that must be true across your app, you can enforce them easily.

Productivity

  1. Learn a scripting language. They are great for automating small tasks. My preferred scripting language is Groovy, but Ruby and Python are also good languages. Perl and PHP aren’t as powerful.
  2. Learn the keyboard shortcuts for all apps you use.
  3. Learn regular expressions.
  4. Install Cygwin so you can use grep on Windows.
  5. Keep up to date with current technology. An easy way to do this is to subscribe to a few mailing lists. I get:
    1. Java Developer Journal
    2. IBM Developerworks
    3. Java Code Geeks.

Tools

Text editing

For text editing I actually use three different tools, all free:

  • Notepad++ – my default
  • jEdit – better for JSP editing
  • vim – not to everyone’s taste, but I used to run Linux on my workstation so I’m used to it, and it has an excellent regex engine.

I suspect I’ll mostly use jEdit in the future, as has a good plugin architecture and a very active user community.

Windows

TweakUI – allows you to customise the left hand pane in file dialogs.
CommandPromptHere – adds a context menu to open a command prompt in a specific folder.
Agent Ransack – a simple and quick search tool. In theory either Windows search or Google should work, but I’ve had problems with both.
FreeCommander – a more advanced file manager.
Folder Size – adds folder size to Windows explorer.
FastCopy – quick copying from network drives.

Firefox plugins

Firebug – the standard plugin for web development.
FirePath – for writing XPath expressions. I use it when writing Selenium tests.
Web Developer – adds some useful menu options.
Selenium IDE – for web testing.
Clear DNS cache – allows you to update your Windows hosts DNS entries without having to restart Firefox.

PuTTY – for SSH connections.
PuTTY Connection Manager or PuTTY tray – both allow you to save PuTTY login details and login at the click of a button.

FileZilla – for ftp and sftp.
Cygwin – for grep and other unix commands on Windows.
WinMerge – visual diff. (Although for a three way diff you might want to try the Perforce Merge Tool.)

Outlook and e-mails

  1. For every e-mail, you should do one of three things:
    1. Bin it.
    2. Archive it.
    3. Flag it for action.
  2. Use rules to automatically process e-mails when you can.
  3. Use categories to make it easier work on your task list.
  4. Use the Outlook pst backup plugin. (Thanks to Dom Day for this.)

8 Responses to Software development best practices

  1. Naina U says:

    I am aspiring to be a technical architect and am very happy to read your article. One of most comprehensive yet easy to absorb. I would like articles on android development from you if you dig into that. Thanks for the gyan.

  2. paul C says:

    I loved the post, but i have one observation:50 lines of code is way too much for a method. You should always try to keep your code as little as possible, maybe around 10 lines or even less. You should use additional methods to call to in order to reduce the line numbers and their names should be as explicative as possible. private methods should have long explicative names(longer the method longer the name), whereas public methods should have a little bit more abstract/sorter names.
    Basically what I’m trying to say is that naming conventions help you code as much as patterns(well a little less). IMHO, bad naming conventions usually separate developers from programers.

    • hedleyproctor says:

      Yep, I agree. I’ve thought for years that methods should be 10-20 lines long at most. However, when I originally started pulling together a list of best practices for other developers to follow at work, I felt like I didn’t want to be overly strict with them, so I choose to say that methods shouldn’t be longer than 50 lines. However, I no longer see the point in being lax. I think I might update the article.

      Your points about naming are good as well. One of my colleagues recently said that if you find yourself adding a comment to some code to explain what it does, you should consider refactoring that block of code into its own method, with a name that explains what it does, which I thought was a very good suggestion.

  3. Website Designing says:

    Very inspiring article for us Thanks for the great article. ….
    It’s definitely a good idea for me and my friends to learn
    the things that’ll expand their skill set Your ideas and presentation is very
    effactive and useful for all. I am loving all of the in turn you are
    sharing with each one!… Being a user i really like your visible information
    on this page

  4. Ayan Nigam says:

    Great Article with very useful tips. I believe now a days Continuous Integration is a must for agile. Tools like Jenkins, Hudson will allow us to keep monitoring on failed builds. Performance section can have mention about front-end, tools like YSlow can be handy.

  5. conativeitsolutions says:

    Your blog provided us valuable information to work on. You have done a marvellous job.
    ==========================

    Software company in Indore

  6. Dev says:

    Nice Blogs!!
    Really its a Best practices of Software development

  7. Uma Mahesh says:

    very good explanation. Appreciate your efforts for writing this.

Leave a Reply to Naina U Cancel reply

Your email address will not be published. Required fields are marked *

502,426 Spambots Blocked by Simple Comments

HTML tags are not allowed.