In the world of programming, documentation is essential for developers to understand how a particular codebase works. It's a key component of a successful engineering team. It helps developers to understand the purpose of the code and how it works so they can contribute to projects, adding features and fixing bugs. There are several ways to document code, including comments, README files, and wikis like Confluence or Notion. The problem with this type of documentation, particularly those that are external from the code, is that once a document has been created it often loses it's connection with the project and is not maintained over time as the code evolves. However, well-written code itself can be a form of documentation. This blog post explores how well-written code can serve as documentation.
As a developer, you might be familiar with the concept of "self-documenting code" or "readable code". The idea is simple: when you write code that is easy to read and understand, you are essentially documenting via the code itself. This means that other developers who work with your code (including future you) will be able to understand what your code does and how it does it, without needing to read through a separate document or ask you for clarification. In other words, well-written code can be its own documentation.
So what makes code "well-written"? Here are a few characteristics:
Clear Naming Conventions
One of the most important aspects of readable code is clear, consistent naming conventions. This means using descriptive names for variables, functions, and classes that accurately reflect their purpose and functionality. For example, instead of using generic names like "foo", "bar" “x” and “y”, use names that describe what the variable or function actually does. By using descriptive names, you can make it much easier for someone else to understand your code without needing to read through lengthy comments or documentation. It's always a good sign if your code reads almost like a natural sentence, just like you might speak it out loud. Making sure to use ubiquitous language is also key to ensure the same terminology and concepts mean the same thing throughout the code and the rest of the business.
Well-written code can reduce the need for further excessive documentation, making it easier for developers to get up to speed and contribute to the project.
Well-written code is often modular, meaning it is broken down into smaller, more manageable pieces. This makes it easier to understand and modify, since each piece has a specific purpose and can also be tested independently. Bounded contexts are also relevant here, making your code more cohesive and enforcing boundaries around related domain concepts. Breaking down your code into modules makes it clearer where code should live and can make it considerably easier for newcomers to get started on a project. Modules can also make it easier to reuse code in future projects or to share code with other developers. This can save you and others a lot of time and effort in the long run.
Well-written code is consistent, both in terms of coding style and overall structure. This means that it adheres to industry best practices and follows established patterns and conventions. By following established conventions, you can make it easier for other developers to understand your code and to work with it. This can also make it easier for you to understand and work with code written by others, since you will be familiar with the conventions they are following. There are many successful and well known design patterns and practices that you can follow. Check out patterns.dev for some great explanations and examples!
When you write code that meets these criteria, you are essentially creating documentation at the same time. This can be especially valuable for larger, more complex projects, where understanding the overall architecture and functionality can be difficult and engineers come and go over time taking their knowledge with them. Of course, even the best-written code can still benefit from additional documentation and this post is by no means advocating against that; in fact I highly encourage it. Code should be supplemented with comments, external documentation, and other resources to ensure that developers have all the information they need to work effectively.
However, by focusing on creating well-written, self-documenting code, you can greatly reduce the need for extensive further documentation and make it easier for others to work with your code. Naturally, if code is self-documenting it is updated as it changes, whereas additional separate documentation can often get outdated unless it's maintained with discipline.
Also note that the concepts in this post, including ubiquitous language and bounded contexts, are fundamental concepts from the domain-driven design philosophy.
So the next time you sit down to write some code, remember that the code itself can be its own documentation if it is well-written and easy to understand. Your future self and other developers will thank you!