As we prepare to bring some new developers on board, it’s worth taking a look at a few of the things we do that make us successful. Sometimes we internalize these things and, not having had to explain them to anyone for a while, they kind of dissolve into habit. Or dissolve into habits we don’t think we need to practice anymore. Documenting our coding decisions is one of the reasons we can support so many customers with such a small team. It’s easy to overlook, but it works.
This is the second post in a series that formed the basis of my 2017 DevCon session on Increasing Code Quality While Staying Lean. Check out the first post for an introduction to the series. We’re looking at techniques that have made a big impact at SeedCode and we hope you’re inspired to incorporate some of these into your work.
Documenting Decisions – We’re Coding for Our Future Selves
We’re coding for our future selves—both in our products and in custom work. We end up coming back to our own code months later and sometimes it’s as opaque to us as if we’d never written it.
So when we make decisions, we want to document them so that our future selves (or our teammates) can more quickly pick up the thread when they return to our work.
This means you can restart projects more quickly, which in turn increases the delivery velocity: especially the velocity of delivering change requests and bug fixes.
[bctt tweet=”One definition of fragility: the original developer is the only one who can help this customer.” username=”seedcode”]
Here’s what we do:
- When we comment out or change code in a script or in a calculation, we include a note in the comment about why we did it.
- If work is related to a Manuscript case, we include the case number in the comments: it’s amazing to be looking at an If() statement you don’t think should be there and see this telling you exactly why it’s there… “If filter is not empty and field DOES NOT match this source: Case 30325”. Now you can go read that case and see the real-world situation that required the If() statement.
- When we’re building a new feature and we decide between competing alternatives we write about that in the case or in the product docs. (For an example, see “Why Make This a Switch?” toward the bottom of the article here).
- Sometimes we start docs for features that haven’t shipped yet so we have a place to record the details of implementation as we’re creating them. It’s much easier to jot down these details as we’re building than to try and reconstruct them later.
- In FileMaker, any script that’s changed gets the Manuscript case number related to that change added to the header comments in the script. For products, we also include the build number we’re working on. This means that if we want to see all the scripts changed in a particular build, we can just use The Tool to search for the build number across all our scripts. (We used the FBz prefix when Manuscript was called “FogBugz”.)
- And all commits to our repo (we use Kiln and GitHub) should include the case numbers related to that work. When we do that, our commits flow back into Manuscript, linking the commit to the customer. When we’re reading back through cases and wondering if we really solved / shipped this, the case numbers help us know for certain if and when we shipped a fix/feature.
[bctt tweet=”We write code once, but we support it forever.” username=”seedcode”]
Well, sometimes we write it more than once 😉
But all of these strategies are about creating a path from the customer’s cases (or feature specs) to the code that addresses them—a path that our future selves can follow. Creating a path means making links between things, not just comments. So paste in URLs and case numbers along with your comments.
Having a path reduces restart time and increases role portability. Meaning your organization (not just your code) is less fragile: less susceptible to schedule changes, minor emergencies, or one of your developers just having a low energy day.