G1: Multiple Languages In One Source File - Mixing more than one language in a single file is confusing and carelessly sloppy. JSP, HTML, XML, English they all contribute to making things less clear. Ideally, keep each file in one language (at most 2)
G2: Obvious Behaviour Is Unimplemented - Based on The Principle of Least Surprise, any function or class should implement the behaviours that another programmer could reasonably expect. When an obvious behaviour is not implemented, readers and users of the code can no longer depend on their intuition about function names and behaviours.
G3: Incorrect Behaviour At Boundaries - Programmers open write functions that they think will work but often fail at the boundary conditions and corner cases. There is no replacement for due diligence - every corner, boundary condition, quirk and exception should be discovered and test-covered.
G4: Overridden Safeties - It is risky to override safeties like compiler warnings or failing tests. You might get immediate benefit by ignoring the problems in front of you, but will likely create much larger problems down the road.
G5: Duplication - Every time you see a duplication in code, it shows a missed opportunity for abstraction (perhaps a method or a new class). By folding the duplication into an abstraction you increase the vocabulary of the language of your design. Most obvious forms of duplication are copy/pasted code which could be abstracted into simple methods. Next most obvious form is switch/if..else blocks which should be replaced with polymorphism. Less obvious are routines which share a similar algorithm, but have different implementations and could use a Strategy or Template design pattern. Most design patterns are actually just well-known ways of removing duplication in code.
G6: Code At The Wrong Level Of Abstraction - It is important to create abstractions that separate higher level concepts from lower level detailed concepts. We want all low-level (detail) concepts to be in the derivative classes, and all high-level concepts to be in the base classes.
G7: Base Classes Depending on Their Derivatives - The most common reason to partition concepts into base and derivative classes is so that high-level concepts (base concepts) can be independent of the lower level concepts, and the base and derivatives can be deployed independently of each other. Where a derivative concept is found in a base class we generally smell a problem. The exception to this is when there are a finite number of tightly coupled/controlled derivatives for a base implementation, and will always be deployed together, however we want to minimise this as much as possible.
G8: Too Much Information - Help keep coupling low be limiting information. Interfaces should be small, and have few methods, additionally with few arguments. Implementations should have few instance variables. Hide data, constants, temporaries. A well-defined interface doesn’t provide many functions to depend upon.
G9: Dead Code - Dead code is code that isn’t executed. This might be because it is commented out, or because it exists in an IF block which never evaluates to true, or it exists in a catch block of a try..catch which never throws. Dead code starts to smell. The older it is, the more it smells because noone is updating the code with newer conventions and rules. The best thing for dead code is to give it a decent burial (and 21 gun salute)
Clean Code: Chapter 17
1 month ago