A practice is something we, as a community, have discovered is simply always a good thing to do. For something to be promoted as a practice, it must be truly universal (we can always do it, and everyone should do it). Therefore, it must be:
- Easy to do. We don’t want to burden ourselves or slow ourselves down because of a practice.
- Easy to teach. If we want everyone to do them, it should not be a burden to propagate their use across the entire team, organization, and the profession itself.
- Highly valuable. A good practice should pay us back over and over and over again.
A common medical practice is all doctors wash their hands before dealing with their patients. It is not hard to do, it’s easy to teach others to do, and it has made the entire profession fundamentally more successful.
These are practices that meet all three of these standards.
Programming by Intention
The eXtreme Programming movement brought with it a set of practices that can help to keep code quality high without over-design or wasteful implementation. Similar to the concept of “top down programming” that was popular among Smalltalk and COBOL developers in the past, programming by intention essentially consists of creating methods by calling them, in consuming code, before they actually exist, and then implementing them afterward.
This simple procedure produces a surprisingly large number of positive results including:
- Method cohesion
- Good interface design
- Ease in subsequent refactoring
- More granular tests
Make State Private
State variables should be made private by default. If there is the need to make an object’s state available to an outside entity, then accessor/mutator methods (in languages like Java) or properties (.Net) should be provided.
This prevents other entities from become coupled to the nature of the state (such as how it is stored, that it is stored at all, where it is stored).
Similarly, state that is intended to be accessed by a derived class should be kept private in the base class, but protected accessor/mutator methods or properties should be provided. This keeps derived classes from coupling to the nature of the state it the base class.
Encapsulate Constructors
The details of the construction of classes or subsystems should be hidden away from the rest of the system, so that if/when their design is changed the impact elsewhere is minimized. This may involve one of a number of creational design patterns (also known as “factories”) but that is only recommended if the class or subsystem’s construction is complex.
If it is simple, then a good fallback practice is to make class constructors private and then to provide a static method on the classes themselves to access them. This method is typically called:
getInstance()
This is an advantage when again, things change. A developer cannot change what a constructor produces, but has complete control over what methods do, and return.
Hiding constructors in this way is a very simple action, but enables emergent design in a profound way. Such a static method can, for example, be changed later to delegate to a factory if and when it becomes needed due to increased complexity.
Perform Commonality-Variability Analysis
In his seminal work Multi-Paradigm Design (1998), James Coplien suggested a technique for analyzing domains that tends to produce strong, useful abstractions that create architectural longevity and increase ROI. We feel this is such a valuable effort that we consider it a practice: Commonality-Variability Analysis.
It uses our natural ability to conceptualize complex elements in our environment to create opportunities for open-closed-ness in design.
How Will I Know I’ve Done That?
Many people think of acceptance test-driven development (ATDD) as an advanced practice. Others think that using given-when-then (GWT) from behavior-driven development (BDD) requires the use of tools. However, neither of these are true. The easiest way to start using ATDD and/or BDD is simply to ask the question, “How will I know I’ve done that?” whenever we are given a requirement. Even if the requirement seems obvious.
It is the obvious requirements that are often most misunderstood. “How will I know I have done even that?” will eliminate these misunderstandings.
Notice how this passes the criteria of being “easy to do, easy to teach and highly valuable (at least at times).” It also starts us down the road of considering behavior prior to implementation. And that’s a good thing.
May 2023
Core Developer Skills Overview
Core Skills
Related Resources
Recommended Book
- Bain, Scott. Emergent Design: The Evolutionary Nature of Professional Software Development. (2008)