Notes from the book by R.C. Martin

Summary of thoughts

This is a long detailed book. Some of the examples could be better. But the general concepts here are very good and this is a must read. I think it is a bonus that it is so long, because it treats the good ideas with the detail they deserve.

3. Functions

Function Arguments

ideal number of function arguements for a function is zero

Flag Arguments

passing a boolean into a function is truly a terrible practise

we should have split the function into two: renderForSuite() and renderForSingleTest()

No Side Effects

Command Query Separation

Functions should either do something or answer something … not both

Extract Try/Catch Blocks

extract the bodies of the try and catch blocks out into functions of their own

4. Comments

The proper use of comments is to compensate for our failure to express ourself in code

Good Comments

the only truly good comment is the comment you found a way not to write

Don’t Use a Comment When You Can Use a Function or a Variable

Consider the following stretch of code:

    // does the module from the global list <mod> depends on the
    // subsystem we are part of?
    if (module.getDependedSubsystems().contains(subSysMod.getSubSystem()))

This could be rephrased without the comment as

    ArrayList moduleDependencies = smodule.getDependedSubsystems()
    String ourSubSystem = subSysMod.getSubSystem()
    if (moduleDependencies.contains(ourSubSystem()))

5. Formatting

Team Rules

6. Objects and Data Structures

Train Wrecks

final String outputDir = ctx.getOptions()getScratchDir().getAbsolutePath()

Active Record

treat the Active Record as a data structure

8. Boundaries

Exploring and Learing Boundaries

may be in our interest to write tests for the third-party code we use

Learning Tests are Better Than Free

Learning tests verify that the third-party packages we are using work the way we expect them to

Clean Boundaries

good software accomodate change without huge investments and rework

9. Unit Tests

  • tests should have one and only one assert statement
  • test a single concept in each test function

F.I.R.S.T.

  • Fast They should run quickly
  • Independent Tests should not depend on each other
  • Repeatable Tests should be repeatable in any environment
  • Self-Validation Tests should … either … pass or fail
  • Timely unit tests should be written just before the production code

10. Classes

Class Organisation

put the private utilities called by a public function itself

Encapsulation

for us, tests rule

The single Responsibility Principle

one reason to change

11. Systems

it is a myth that we can get systems “right the first time”

12. Emergence

run all the tests

17. Smells and Heuristics

General

  • G1: Multiple languages in one source file
  • G10: Vertical separation variables and functions should be defined close to where they are used
  • G13: Artificial Coupling things that don’t depend upon each other should not be artificially coupled
  • G23: Prefer Polymorphism to If/Else or Switch/Case
  • G24: Follow Standard Conventions
  • G25: Replace Magic Numbers with Named Constants
  • G28: Encapsulate Conditionals > if (shouldBeDeleted(timer)) is preferrable to if (timer.hasExpired() && !timer.isRecurrent())
  • G29: Avoid Negative Conditionals > if (buffer.shouldCompact()) is preferrable to if (!buffer.shouldNotCompact())
  • G30: Functions Shouls Do One Thing
  • G31: Hidden Temporal Couplings
  • G33: Encapsulate Boundary Conditions > if (level + 1 < tags.length()) is preferrable to if (nextLevel < tags.length())

Names

  • N1: Choose Descriptive Names

Tests

  • T9: Tests Should Be Fast