Good code feels good, bad code feels bad : Trust your instincts

There’s been many attempts over the years to measure code quality with quantifiable metrics, such as cyclometric complexity (a measure of complexity caused by nested conditional branches). An experienced developer who has seen good code and bad code will have an instinctive feeling whether code is good or bad. Gut feel is valuable because it’s almost always right. If you look at code and it feels wrong, you’re probably right. Based on experience, you get a feeling that something’s not right. The difficult part is nailing down what’s not right, and then refactoring to make it better.

There’s been a number of best practice principals established over the past decades of software development that have stood the test of time, and are widely accepted. There are many other ideas and concepts that are topics for hot debate, but these few core ideas seem to be largely accepted by most developers.

In order to understand what it is we’re aiming for, I’ll take a stab at defining what I consider to be the core qualities of good quality code. Quality code is:

  • easy to read, and easy to understand
  • easily testable (with unit tests)
  • easy to fix, and easy to modify

You could expand this list with many other factors, but I think these distill the essence of high quality code. There’s a direct relationship between these qualities and the complexity of the code too. Remember cyclometric complexity measures the complexity of code based on number of branches – code that has a high number of nested branches with a high cyclometric complexity count would probably fail all the above qualities: deeply nested conditional code is usually difficult to read and understand, hard to test, and also usually hard to fix and modify.

As a broad generalized statement, simple code is usually high quality code, complex code is usually poor quality (based on the factors above).

The problem is, it’s not easy to write simple code, it takes time, effort and experience. It’s pretty easy to write complex code, but simple code usually takes considerably more time and effort. Without thought and attention, even as you work on simple code over time, there’s a danger that the code becomes more complicated the more changes are made to it. It takes effort to keep code simple, to keep it from deteriorating over time.

Best Practices for Writing Quality Code

There’s a number of established best practices in software development, many of which if followed help you towards writing code that achieves the 3 points above (easy to read, easy to test, easy to fix). Bob Martin in his book Agile Software Development, Principles, Patterns, and Practices, captures a number of these in the SOLID mnemonic:

  • Single Responsibility Principal
  • Open Closed Principal
  • Liskov Substitution Principal
  • Interface Segregation Principal
  • Dependency Inversion Principal

Other popular industry best practices include DRY (Don’t Repeat Yourself), and the YAGNI (You Ain’t Gonna Need It) idea also contribute and guide you towards developing simple, quality code.

Many of these concepts are deeply rooted in the first of the SOLID principals, the Single Responsibility Principal. If you have a Class that ‘does one thing and does it well’ (another common way this principal is expressed), or a method that does one thing, this code is typically easy to read, easy to test and easy to fix.

Many other best practices and guidelines tend to result indirectly in achieving the same desirable results. In many cases regardless of the approach or best practice followed, the ultimate result is code that does one thing and does it well. Code with this ultimate quality meets the criteria of easy to read, easy to test and easy to fix.

InfoQ interview with Martin Fowler : 2nd Edition of his 1999 Classic, Refactoring, is now shipping!

Martin Fowler’s classic software development book, Refactoring, was first released in 1999. It’s been a staple on my bookshelf since I got a copy in 2000, something that I regularly refer back to for advice on how to improve the structure and maintainability of my code.

The 2nd edition of the book has now been released, updated for 2018, with all the code examples in the book which were previously in Java now replaced with equivalent examples in JavaScript. I have my copy on order with Amazon and should be receiving my copy before the end of the year.

InfoQ have a great podcast interview with Martin, discussing the motivations for releasing an updated edition for 2018, 19 years after the 1st edition was released. Check out the interview here.

The Unavoidable Compromise of Business Driven Development

Given enough money, time, experience,  technical experience and creative input, time has shown as an industry we can build awesome things. Unless you’re working on a self-funded project with unlimited supplies of cash and time, it’s unlikely that most of us will ever have the experience of working with minimal or no resource constraints.

Software development in ‘the real world’ is really no different from any other business, and the concept of the Triple Constraint has been well understood in Project Management for some same. This describes the inter-relationship between 3 attributes of:

  • schedule
  • scope
  • cost

and how they interact to affect quality of the final product. At a high level, it’s generally understood that you can have ‘any two’ of these, but it’s impossible to have all three at the same time. Each of these attributes translates to desirable qualities of:

  • fast (deliver the product in less time)
  • good (include all desired features)
  • cheap (deliver at low cost)

So, you can have fast and good but it won’t be cheap, or you can have fast and cheap but it won’t meet all your requirements (some features will have to be left out).

So back to the original topic. How is software development a compromise? Invariably because your client or your company wants all these things: “we want it developed in an impossibly short amount of time (get it ready for tomorrow), we want this massive list of features (and no, we’re not prepared to leave any out), and oh by the way, we only have enough money to pay for 1 developer to work for 8 hours”.

While technology can go some way to helping produce more for less (code generation etc), the reality is that software development in the real world is not a technical problem. It is a business problem of negotiating contracts and managing expectations. For the technologist, this is the continual struggle – pretty much everything you work on will be under less than ideal conditions.

Business Driven Development (BDD). Welcome to the Real World.