Clean code should read like a good book: clear and concise.
According to Boston engineers, a developer’s work in a code base must be readable enough that an engineer of virtually any level could quickly understand, add to and even fix code months or years down the line.
The six professionals we spoke to agreed on a number of best practices their teams use to ensure clean, maintainable and expressive code.
First, they rely on simplicity. For instance, if a method is a verb, it should be labeled as such. Naming conventions should be precise, not too long or complex. Furthermore, standardization across the team takes precedence over an individual dev’s personal preference. To fuel assimilation, code reviews and automation tools help teams quickly correct inefficiencies and spot bugs early on.
Hervey’s best practices for clean code: First and foremost, come up with a plan. Writing code without fully understanding the scope of the problem can lead to hitting unanticipated use cases. Or you can miss design requirements that may lead to shoehorning code into places it doesn’t belong just to get the job done.
Engineers get excited about writing code and want to jump right into it. Instead, we should take time to plan and ask probing questions. Understanding whether requirements go beyond what’s defined in the design specifications results in cleaner code. It also prevents devs from context-switching from a coding mentality to design mode, and back again. Sometimes additional requirements are uncovered while coding, but minimizing them up front — by planning for them during design — will help produce cleaner code.
Promote consistency in code by defining the best practices that will guide engineers.”
Habits devs should stop: Engineers sometimes don’t have a deep enough understanding of the frameworks they use, which leads to either unanticipated behaviors or poor software performance. Object-relational mappings seem to trip up new developers as far as understanding the performance impacts of queries generated behind the scenes. Frameworks are a double-edged sword: they make our lives easier, but only when we know how to use them appropriately.
In terms of clean code, use descriptive variable and method names. Nothing drives me crazier when reading and understanding someone’s code than keeping track of nondescript names. Avoid writing monolithic “do everything” classes. Keep classes succinct and remember the single-responsibility principle. A class should only do one thing, so make it do that one thing well.
How The Predictive Index prioritizes clean code: One of the most powerful tools, for both developing clean code and training developers, is the code review process. Experienced engineers providing meaningful feedback to junior devs evolves the next generation of coders who will educate others on best practices.
Don’t just point out what is wrong during code reviews; suggest options for improvements. I found reviews to be a transformational tool. They provide opportunities for growth, make me a better developer and improve the quality of my code. Promote consistency in code by defining the best practices that will guide engineers. If developers know what’s expected, they will save time refactoring code that doesn’t hold or scale to the organization’s expectations later.
Jones’ best practices for clean code: My first recommendation is to absolve yourself of as much responsibility as possible and let your tooling do the work for you. Depending on the language, it is likely that there is a linter and a code formatter available. The combination of these tools will make code automatically consistent. They will take care of the low-hanging fruit, but it is still on the dev to write good code. To that end, I tend to focus on readability over performance. I only consider performance when code is not performing to the level it should. If code is easy to read, and formatted consistently, it should stay clean on its own.
Finally, make sure the code does what you think it does by writing tests. Tests provide confidence that the code works now. When refactoring, developers can run tests at every step and ensure nothing breaks and the code stays clean.
Not writing tests at all is asking for bugs.”
Habits devs should stop: Developers often try to make their code as concise as possible and sacrifice readability in the process. The most frustrating part of these efforts is single character variable names. If names were more specific, other engineers would immediately know the purpose of every variable on any given line of code. Single character names reduce devs to studying the context of every line to figure out intent.
Another bad habit is not writing tests. I have little preference between writing tests before or after implementing code. Depending on context, both approaches have their value. But not writing tests at all is asking for bugs. The best part about tests is that one can prove that the bug you just fixed doesn’t exist. So you can push code and never worry about that bug again.
How Markforged prioritizes clean code: Review isn’t something that just happens at the end of a job, and we have regular check-ins with reviewers. A development task typically has three stages: architect, implement and polish. A reviewer’s insights are valuable at every stage. I have often submitted code for review, naively seeking feedback on the polish type, only for a reviewer to suggest sweeping architectural changes that force me back to the drawing board. Reviewing at every stage of development leads to better solutions.
Giraldi’s best practices for clean code: Writing code feels like experiencing déjà vu; it’s important to see whether or not I’m repeating myself. I always take opportunities to reuse code I’ve already written. Also, look at comments and descriptive names from an outside perspective. Make sure names are appropriate and helpful for someone unfamiliar with the codebase.
We try to consider future cases when designing our databases. Keeping them generic avoids growing pains as our APIs evolve.
Make sure names are appropriate and helpful for someone unfamiliar with the codebase.”
Habits devs should stop: Code siloing. When an engineer doesn’t share their knowledge, they are limiting themselves because others cannot provide feedback. They’re also leaving the rest of the team at a disadvantage. Unobservant engineers sometimes don’t conform to formatting that everyone else seems to be following.
Refactor legacy code when there are opportunities. Making frequent, small changes while accomplishing other tasks allows teams to keep moving forward and improving code. Long names are debatable. Some say descriptive variable naming is important but if names become too long, they’re compromised by becoming unreadable. Also, make comments. You may know what a complicated function does today, but maybe not in six months.
How Buoy Health prioritizes clean code: All code is reviewed, and many projects require two reviewer approvals. We also maintain front and back-end style guides for engineers working on different teams. All of our devs are encouraged to suggest changes to these guides as the tools we use evolve along with the industry. We exchange ideas, search for feedback and ask questions.
We have regular engineering meetings where one or two engineers present on topics of their choosing. These presentations can be about internal changes we’re implementing, or they can share their knowledge on something they learned externally with the rest of the team.
Nguyen’s best practices for clean code: When I draft some functionality, I’ll rewrite it multiple times. Rewriting makes me examine many aspects of the code, such as how understandable my variable and function names are. But most importantly, it tells me how easy it is to change my code and check the result. I want code that’s easy to understand and safe to change.
Along those lines, tests give devs the confidence to work on the aesthetics of their code while delivering the same functionality. There are lots of philosophies on tests, but they should be written, and try to make them fast.
Lastly, make sure to understand the context into which your functionality fits. It could be something as simple as figuring out what happens downstream when an endpoint succeeds or fails. No amount of work to keep code clean will save you if you’re not solving the right problem.
If something goes wrong with our code, we always have someone on call to investigate.”
Habits devs should stop: Non-descriptive variable and function names, a lack of comments and unnecessary abstraction cause the code to be less understandable. Code could also be more easily understood if it was written more verbosely rather than condensing a bunch of logic into a one-liner, making the code overly “clever.”
There are also a few bad habits that can cause instability. These practices include coding so that multiple versions of the code can’t co-exist, not coding to allow for graceful version changes and not having a feedback loop or a tool to know whether functionality is working. Having good logs or metrics can usually solve this issue.
How Takeoff Technologies prioritizes clean code: If something goes wrong with our code, we always have someone on call to investigate. Providing support for production issues is a top priority for the team. Knowing it might be your turn to be called at 3 a.m. to resolve an issue makes the importance of writing good code very real to us.
We make sure to have appropriate reviews and testing for our code. To help improve contextual knowledge around the things we are building, we pair up, hold learning sessions and temporarily embed ourselves on other teams. The key here is to take active steps in figuring out what works best for the group by reflecting, and improving.
Ghozati’s best practices for clean code: I spend a great deal of time thinking about the problem domain and how it’s modeled by nouns and verbs. As an engineer, I think through and solve problems using these abstractions. I can intuit a lot about the solution by modeling the abstractions properly. Clean code reads like a well-written, concise piece of literary work. I keep my methods and functions short and cohesive to keep the reader focused and ensure that the work is being done at the same level of abstraction within that body.
Finally, I make use of functional programming techniques whenever I can. By composing functions out of more atomic elements, I can build flexible pieces of software and reuse those pieces to solve more complex problems. Brevity is king with software.
Clean code reads like a well-written, concise piece of literary work.”
Habits devs should stop: I wish developers gave more thought to naming their variables, methods and classes. I’ve seen methods named “do_it” in an interface that was implemented by nearly 20 classes. It’s not that these names are wrong or misplaced. But sometimes something could be a curator or a horologist that could help frame a problem better to the uninitiated reader, or to me nine months later.
Additionally, I wish developers would restrict access as much as possible with their variables. Declare a variable as constant when it should be constant. The same goes for methods, functions and classes. By being disciplined and thorough, you will catch bugs much faster than you would otherwise.
How Alert Innovation prioritizes clean code: My team makes clean code a priority through vigorous code reviews and trying to learn as much as we can from one another. We automate as much as we can and have pretty stringent linting rules. When code comes up for review, there is already a baseline set by our tools that helps keep the review focused on functionality and design. By following these practices and principles, we are able to ensure high software quality, which means less bugs to fight in production.
Conn’s best practices for clean code: Our best practices make code easier to read by starting with the fundamentals. Methods that do things should be phrased as verbs, while methods that return a boolean can normally be phrased as a question that reads naturally. Variables and class names should explain why they exist in a concise way. Functions should have one intentionally-focused area of concern.
These clean code fundamentals help to make your code look like language phrases, and then everyone has a better understanding of the project. When you are coding complex projects, especially when maintaining them, that ease of readability definitely helps.
If we try to use these tools inappropriately, things will get hard to read very quickly.”
Habits devs should stop: I think there is a tendency for us to forget that code is a tool. We tend to favor the languages, frameworks and paradigms we know and sometimes try to use them in inappropriate ways. Neither object-oriented programming, functional programming, nor procedural are always correct. People will pick React or Vue as their framework of choice but sometimes jQuery might be good enough. Or someone might choose jQuery where a more modern framework could get things done quicker. If we try to use these tools inappropriately, things will get hard to read very quickly. When things flow, they’re easier to follow.
How Mimecast prioritizes clean code: We have a set of principles called “The Mimecast Way,” two of which are “make things better” and “invest in one another.” We have diverse team members in the UK, USA and New Zealand. We invest in one another — and build cleaner code — by sharing perspectives and looking for common understanding. Pair programming via video chat and code reviews help us discuss code flow and naming conventions. Our main focus is determining whether better words could be used to describe a situation for everyone that needs to read it.