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. This doesn’t mean you need a microservice! Imo a microservice is only needed if at least one of two things is true: one – you need to scale the service independently, two – you need to invoke the service from different applications. If these things aren’t true, you simply need a component, not a microservice. i.e. a module, with a public API and tests inside the module.
  2. You should have a repeatable, incremental build. i.e. if you have 50 modules and you only change code in the very last module, only that module should rebuild and only the tests for that module should run. Maven does not support this, but Gradle is a great tool for this. By repeatable, I mean checking out the same commit anywhere and running the build should produce the same result. e.g. don’t have a step on your CI server which mutates the source files to set a version number
  3. 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 (e.g. Spring beans) and each API should just be a thin layer.
  4. 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.
  5. 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:
  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.


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.


  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, integration 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 integration 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. Understand how to perform data driven testing, where you can list off different permutations of input data. Available in both TestNG and JUnit. For the TestNG docs, see
  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, Cobertura or Jacoco. I am pragmatic about code coverage – although it does help to see what areas you are lacking in tests, remember that normally all you are seeing is if a line is executed by a test, you aren’t seeing if the result of that line is checked by an assertion, and unless you explicitly configure it, you won’t see branch coverage. i.e. if a code has two if statements and each one has two branches, you actually have 2 x 2 = 4 routes through the code. You could have 100% line coverage but only test 2 out of those 4 routes.
  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 SpotBugs. 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.


  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.


Code Development

I use IntelliJ. I think it is an amazingly powerful IDE. See my hints and tips here: IntelliJ Hints and Tips

Text editing

I use Atom for some text editing tasks, but most of the time I just stick with IntelliJ because it is so good.


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

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

HTML tags are not allowed.

513,458 Spambots Blocked by Simple Comments