To answer this question, we have to start off with the definition of ‘Good code’.
- Is clear, efficient, easy to maintain, and easy to read
- Follows a clear, logical sequence of operations, and relies on no invisible or external machinery
- Carefully checks to ensure that inputs follow documented specification
- Handles external error cases gracefully
- Scales well under load
- Is well-documented, and the documentation accurately reflects the code and is maintained with it
- Is well-tested, with clear links between tests and the specific actions of the code being tested
You’ll note that none of these things incorporate concision as a first-order requirement. All other things being equal, tight code is preferable, but this list should be achieved first.
Good programmers write their programs with a good architecture. Bad programmers write complex architecture hard to understand and maintain. And as a result – end up writing far more code, to fit in with the complex architecture of the program.
There – the aim is not to reduce the lines of good code as such. But to make it easier to read and more maintainable, and easier to write. Which often has the result of reducing the total lines of code.
As an example from my own code – just an example of a way that my code has improved – some time back I found a way to write a single line of code which
- Adds a user variable (e.g. check state or the value of a parameter in the user interface) to the .ini file so that it is persistent when the user exits the program and starts it up again
- Displays that value to the user
- Adds that value to global undo for the program
- Records that variable as associated with a particular window or windows – so the user can save all the values for any individual window in the program
- Associates its id with tool tip extra help – which I can then edit within the program – several pages if necessary of extra help telling the user how to use that control and what it does.
- Doing this with just one line of code immediately eliminated many potential bugs that I’d had before. Now they can never arise again with new code. This replaced what previously were many lines of codes that had to be entered in many parts of the program each time I added a new user visible variable to it.
Nothing as effective as actually trying it out to find out if the architecture works. Of course – your mileage may vary. And I’m a sole developer so can just do that at any time if I want to. Do it very rarely, perhaps every few years – but there’ve been a few times I’ve changed the architecture and been so glad I did it – such as for instance that one line method of adding user variables to the program – one of the best programming decisions I made I think :).
But back to examples to show that this process of reducing the lines of code can be taken too far. There are competitions to make surprisingly tiny programs to achieve a particular task, with the size usually measured usually in terms of the total characters in the program, but they often have surprisingly few lines of code as well.
Often deliberately obfuscated as part of the competition, but the very act of making it as short as possible (e.g. using single letter variable names wherever possible and using the C capability to redefine things with shorter names e.g. single characters for standard functions etc) makes it hard to follow what it does.
In my experience, GOOD CODE is about being conventional for readability and maintenance. This means the best code is the shortest it can be without sacrificing clarity. This approach allows the most flexibility.
- When you need to adjust it, it’s the easiest.
- When you need to read about the algorithm, it’s the simplest to recognize and look up.
- When you need to debug it, it has the smallest hiding spaces for bugs.
- When you need to break it apart and refactor it, it is already concentrated as much as it could be instead of sprawling.
Therefore, the best programmers do not typically use the fewest lines of code. Instead, they write the code in a fashion appropriate for its intended use.
- High-speed of execution. In certain cases this will be the shortest source code, but it will be arrived at by carefully choosing which intrinsic functions to use, order of comparisons, and many other things you wish an optimizer could take care of correctly for you. The examples I’ve seen were painful to maintain and debug.
- High speed of development. For example, prototype code to demonstrate a concept or refine an algorithm. This code tends to be concise, ‘happy case’ code. It’s also usually modular in ways the developer expects to extend or experiment with.
- Commercial production. If the programmer is producing code which is expected to be long-lived, and which must be robust to corner cases, it’s typically written to be clear, maintainable, and bullet-proof. Code I wrote for research in five lines might require 200 lines to write in a manner appropriate to ship in Windows.