The Art of Software Design
with No Comments

Having working programs is good. Having working programs with a clean design is excellent.

Many programmers focus on making their programs work then end at that. Software design is an afterthought. It should be the priority. Good software design has 3 qualities: safe from bugs, easy to understand, and ready for change.

  • Safe from Bugs: correct today and correct in the unknown future.
  • Easy to understand: communicate clearly with future programmers, including your future self.
  • Ready for change: accommodate change without requiring rewriting.

Clean code or good code design can seem like a vague concept at first. It simply means to code in a way that facilitates efficient maintenance, ease of updating, and effective collaboration between multiple developers. Dirty, smelly code means code that is good the one time it is written. If you had to go back to it, it would be hard to modify without breaking it or creating more bugs. It would be poorly documented and hard to read.

What are some practical principles of good code?

  1. Don't Repeat Yourself (DRY)
    Duplicated code is a safety risk. It makes it harder to refactor or clean bugs because you have to go through the whole file. Avoiding duplication can be done with control flow (if, for, while, etc), and creating functions/methods for anything that sees multiple calls, for example.
    Avoid copy-pasting.
  2. Comments Where Needed
    Use comments judiciously to promote good coding.
    Comment assumptions and references.
    Avoid comments that transliterate code to English.
  3. Fail Fast
    The program should reveal bugs ASAP.
    Static checking fails faster than dynamic checking, which fails faster than no checking.
    Avoid quietly passing wrong answers.
  4. Avoid Magic Numbers
    0 and 1 are given in software development. All other numbers are magic.
    Use constants, arrays. Use named variables.
    Bad numbers are computed manually by the programmer. This is also harder to read.
  5. One Purpose For Each Variable
    Don't reuse parameters and variables, because they are less safe from bugs and less ready for change.
  6. Use Good Names
    The best names are long and self-descriptive, which consequently need less commenting.
    'tmp', 'temp', and 'data' are awful names.
    Abbreviations are unclear.
  7. No Global Variables
    Don't use anything that is both variable and global (public static without final).
    Change global variables into parameters and return values.
    Encapsulate global variables inside objects that the program is calling methods on.
  8. Return Results, Don't Print Them
    Returning results allow them to be reused in another context.
    Only the highest level parts of a program should interact with a human user or console.
    Low level parts should take their input as parameters and return the output as results.

  9. Use Whitespace for Readability
    Use consistent indentation.
    Spacing between code lines makes them easy to read.
    Never use tab characters, only space characters. (tab character != Tab key).
    Set programming editor to insert space characters with the Tab key.

Summary

Following these principles allow a program to be safe from bugs. DRY code lets you fix a bug in a single location, without fear of extensive propagation throughout the program. Commenting your assumptions makes it less likely that another programmer will introduce a bug. Failing Fast allows bug detection and immediate response. Avoiding global variables makes it easier to localize and find bugs.

Easy to understand. These principles help other people reading it to quickly understand it, and therefore prepare them to identify obscure or confusing code. Using judicious comments, avoiding magic numbers, keeping one purpose for each variable, using good names, and using whitespace all improve code readability.

Ready for change. Good software design principles such as DRY code makes it more ready for change, because a change only needs to be made in one location. Returning results instead of printing makes it easier to adapt the code to a new purpose.