February 28, 2009

Clean Code Cheat Sheet

Apparently there is no definitive Grand Unified Theory but all of the following processes and principles contribute to create good software. Please print on the wall.

[PROCESS] The Get It Done Adagio Text borrowed from related Agile in a Flash card.

  1. Make It Work. Program with your mind focused on the feature’s basic behavior. Just make the feature work. Ensure that all the test(s) pass for that feature.
  2. Make It Right. Now that you have your feature working (all tests passing), focus on refactoring the code. Tests will provide the necessary feedback. Clear up structural and aesthetic issues, remove duplication, rename variables, etc.
  3. Make It Fast. Once the the tests are passing and the code is clean, you can focus on tweaking its performance. Use a profiler of course. Once again, you can feel confident in your changes because the tests will ensure that functionality is not broken.

[PROCESS] Popping the why stack Use this process in front of the customer to decide when to implement a feature. Thanks to Ben Mabey for bringing this up once again in his talk.

  1. Keep asking why? no more than 5 times until you reach one of the following “right” answers: protect revenue, increase revenue, manage costs.
  2. Accept feature if right answer. Then discuss scenarios, describe acceptances.
  3. Reject feature if not right answer. The feature doesn’t need to be written.

[PROCESS] The Three Rules of TDD

  1. You are not allowed to write any production code unless it is to make a failing unit test pass.
  2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
  3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

[PRINCIPLE] S.O.L.I.D.

  • SRP (The Single Responsibility Principle) A class should have one, and only one, reason to change.
  • OCP (The Open Closed Principle) You should be able to extend a classes behavior, without modifying it.
  • LSP (The Liskov Substitution Principle) Derived classes must be substitutable for their base classes.
  • ISP (The Interface Segregation Principle) Make fine grained interfaces that are client specific.
  • DIP (The Dependency Inversion Principle) Depend on abstractions, not on concretions.

[PRINCIPLE] Law of Demeter

  • Bad smell: one should not have a chain of messages a.getB().getC().doSomething() in some class other than a’s class.
  • Local methods: your method can call other methods in its class directly (one should not call methods on a global object)
  • Local fields: your method can call methods on its own fields directly (but not on the fields’ fields)
  • Local params: when your method takes parameters, your method can call methods on those parameters directly.
  • Local objects: when your method creates local objects, that method can call methods on the local objects.

[PRINCIPLE] Connascences

  • CoN (Connascence of Name): changing a name forces a change to all the references to that name (tools: refactoring moves, mass search-replace)
  • CoP (Connascence of Position): changing the order of data forces a change in the algorithm that processes them (tools: CoN => CoP, related refactoring moves). Example: named parameters as a hash, create new method for different parameters.
  • CoM (Connascence of Meaning): changing a label used to identify a particular meaning forces a change to an algorithm that processes that label (tools: CoM => CoN using a global constant, extract constant refactoring moves). Example: using “1” or “2” to identify a completely uncorrelated business function.
  • CoA (Connascence of Algorithm) the same business rule implementation is duplicated and changing the algorithm in one place forces a change to the other algorithm (tools: CoA => CoN with DRY, extract method refactoring moves)
  • Contranascence: the same name is used to identify different things depending on the context (tools: namespace). Example: Node class in XML and Node class on an user interface API.
  • Rule of Degree: Convert high degrees of connascence into weaker forms of connascence
  • Rule of Locality: As the distance between software elements increases, use weaker forms of connascence

[PRINCIPLE] Coupling

  • Coupling between modules/components is their degree of mutual interdependence; lower coupling is better
  • Content/Pathological Coupling: (worst) When a module uses/alters data in another
  • Control Coupling: 2 modules communicating with a control flag (first tells second what to do via flag)
  • Common/Global-data Coupling: 2 modules communicating via global data
  • Stamp/Data-structure Coupling: communicating via a data structure passed as a parameter. The data structure holds more information than the recipient needs.
  • Data Coupling: (best) Communicating via parameter passing. The parameters passed are only those that the recipient needs.

[PRINCIPLE] Cohesion

  • Cohesion of a single module/component is the degree to which its responsibilities form a meaningful unit; higher cohesion is better
  • Coincidental Cohesion: (Worst) module elements are completely unrelated. Example: Utils class.
  • Logical Cohesion: elements perform similar activities as selected from outside module, i.e. by a flag that selects operation to perform (see also CommandObject).
  • Temporal Cohesion: operations related only by general time performed (i.e. initialization() or FatalErrorShutdown?())
  • Procedural Cohesion: elements involved in different but sequential activities, each on different data. Example: usually found in Controllers.
  • Communicational Cohesion: unrelated operations except need same data or input
  • Sequential Cohesion: operations on same data in significant order; output from one function is input to next (pipeline)
  • Informational Cohesion: a module performs a number of actions, each with its own entry point, with independent code for each action, all performed on the same data structure.
  • Functional Cohesion: all elements contribute to a single, well-defined task, i.e. a function that performs exactly one operation

[PROCESS] Common Metrics

  • LOC (Lines Of Code): the less is usually the better for the same features implemented
  • Coverage (Test Coverage of Code Sources): the higher the better
  • Cyclomatic Complexity: the lower the better. Usually indicates the complexity of algorithms that should stay as low as possible
  • Churn (Number of Commits per File): high churns on a file usually indicates an SRP violation
  • Code Duplication: the lower the better. Usually indicates DRY violations.
And many many more…
Comments (View)
blog comments powered by Disqus