Clearing the Path for Future Developers
“We must find out for ourselves what it means to love; because if we don't love we can never be thoughtful, attentive; we can never be considerate. Do you know what it means to be considerate? When you see a sharp stone on a path trodden by many bare feet, you remove it, not because you have been asked, but because you feel for another - it does not matter who he is, and you may never meet him.”
At Lab Zero, we’re often hired by clients to create brand new products, and thus brand new codebases. When our time on a project is complete, the client’s own developers inherit the codebase. We’re usually working side-by-side with these developers and are constantly engaging in knowledge transfer.
We never presume that that is enough; that the developer we’ve been working with understands what we’ve built and will carry it off into the sunset, living happily ever after. We’re realistic. We don’t worry about that developer—we worry about their future colleagues. Our clients need the flexibility to have any developer drop into our code and make changes.
We keep that unknown programmer in our minds throughout our development cycle; they are our invisible colleague. That programmer may be junior or may be new to this language. Even if they’re the client’s strongest developer, maybe they’ve been battling insomnia, or the family dog has gone missing; for whatever reason, they’re struggling to focus. We believe that a bit of care today can help that future developer have a productive day even in the toughest of circumstances.
Human naming
- We always make sure to match variable and model names to how people talk about them in the real world. The future developer will likely be acting on a request from a product owner. When they dive into the code, the nouns and verbs they see should match what they’ve heard.
- We use method and class names descriptively—not just in the moment, but in the context of the entire application.
- We try hard not to overload, watching out for similar names representing different concepts in the application. If there’s overlap, we carefully consider changing names to avoid confusion.
Convention over cleverness
- We consider where developers are most likely to go looking for the things we’re building.
- We adopt radically unusual approaches with caution, weighing the benefits against a more conventional approach. This leads to (mostly) self-documenting code, but if we’re doing something surprising, we supply good documentation of the motivations that led us off the well-trodden path.
- If there are multiple ways to implement something that happens several times in an application, we try to stick to just one way, so developers can quickly recognize what they’re seeing. Being consistent pays off.
- We sacrifice flexibility in design decisions by adopting the conventions of more convention-based frameworks that other developers already know (e.g. Ruby on Rails).
Descriptive code
- Code should read easily. If we have a nagging feeling that another developer would need a comment to understand what they’re seeing, we restructure it until no comment is necessary.
- If our code looks cluttered, we look for ways to simplify the structure.
Helpers
- We use helpers to make code more descriptive or to hide away code that may clutter and distract.
- We intuitively name our helpers (and document them if their purpose would not be obvious to a newcomer on the project).
- We never use helpers as just a gateway to several other complex decision trees elsewhere in the application.
Thoughtful design
- We consider likely code-change scenarios—programmer use cases. Will that programmer encounter gotchas?
- A recent example: when initiating a new project for a client, we took the time to think through how localization would be managed—not just by the application, but by the people who would be adding languages and changing the application’s bits of text in the future. Who will those people be? What tools will be familiar to them? Where would they expect to find the text strings? What organization structure would be simple and intuitive for them?
Code checks
- Our approach to code review is persnickety. We put a lot of care into fine-tuning each other’s code, and delight in potential improvements spotted by our colleagues. We use code linting tools to ensure that our code is all created in one consistent style. This sanding of rough edges makes it much easier to read.
Documentation
- We rely on comments as little as possible. Code should be self-descriptive. (Of course we still use comments when they’re really needed.)
- We use README documentation as an excellent place to elaborate on how to operate within the universe of the application. They often contain local environment setup instructions, links to external documentation, a peek into the mindset of the developer, and examples of how to make changes.
- The Lab Zero Ruby on Rails Developer Guide has a section elaborating on our Documentation philosophy.
Our software isn’t built for sunny day conditions; it is built for the rough weather of the real world. We believe that simple consideration for our fellow developers can make the hard days better, and the good days great.
Continue the conversation.
Lab Zero is a San Francisco-based product team helping startups and Fortune 100 companies build flexible, modern, and secure solutions.