Make your code digestible for others
Why you should put effort and care into naming things
Naming things appropriately in code is extremely important because it:
- Improves general readability
- Reduces cognitive load when understanding concepts
- Helps others understand your code too — you aren't the only contributor!
- Which follows … the easier it is for others to understand, the faster it is to work with, and less chance of causing bugs due to miss understandings etc.
Code should read like a story, not a detective novel
- Danial Markham
Imagine you open a news article that captured your attention titled “Covid natural vaccine with 100% success rate, rolling out in 2 weeks”, and this is what the author opened with:
A group of scientists have been working on a naturally activated antibody found in the human body by splicing the mRNA with fnt6C8 cluredene that naturally forms in biocellular wall of the vascular endothelial cell membranes.
… I don’t know about you, but I would be left confused. The title said it all, but the opening contents was a cryptic puzzle. It might have made sense to the reporter at the time of writing: when they did all their research and they were in “the zone” typing up all their knowledge for the article.
Communication is at the forefront of a reporters job. They must strip away their own biases, and use terms that could be simple, cross cultural, and easily understood by almost anyone.
As coders, we write a structured bodies of text, that has to be digested and understood by contributors, other than ourselves. There is a lot of creative freedom in writing code. And it is influenced by your mother tongue, cultures and general background. So it’s extremely important we consider these differences as we code.
Often we (coders) don’t always consider others reading our code. Sometimes we do, but slip into “the zone” and hash out some “brilliant” code that maybe we can understand. And I bet you, your future self probably won’t.
There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors.
(Martin fowler originally famously quoted 2 hard things in computer science)
When establishing a new term for something in the codebase: its best to get a consensus on, this might come out during code review stage. But if its a major new concept its best to draft-review your ideas with your team before coding.
So are there some rules for naming things … ? yes, please read on…
Naming things presents itself as a technology programming problem, it’s actually a socialization coding problem.
- Danial Markham
Guidelines
Names in code should convey intent.
Be consistent with names: avoid slight variants. subtleties with different names of the same thing can cause lots of confusion, especially for newcomers to the codebase.
Microsoft has some good guidelines for the dotnet language family (e.g. C#):
- https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/general-naming-conventions
- https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
Every language will have their own standard guidelines. In my opinion its best to keep to to the most official guidelines as possible rather than custom preferences, so people moving between companies / codebases can easily and freely do so without mixing up standards.
Note: don’t confuse style guidelines with naming guidelines. Styling/formatting is completely different to naming things.
A few simple examples
- Class named
class HealthCheck { … }
, would be better namedHealthChecker
(change from a verb to a noun) class DeviceTypeBusiness
: why “business”? does your code really need to know which “layer” its in the architecture by adding suffixes to names? With people not familiar with the codebase’s reference architecture, they might be left scratching their head what “business” means.- If you separate data classes from classes containing logic (quite common), try to have a conventional to set apart Data (entity) classes vs business/domain logic classes (services interfaces).
Example: consider using something likeConsumerRepository
instead of just a)Consumer
or b)Consumers
. a) sounds like a single entity, and b) seems a bit ambiguous as it sounds like a general memory backed collection. I would reserveConsumer
as a data class name. - Avoid overusing temp variables with short hands like
x, y, z
especially with nested logic. e.g. rather thanreports.Where(x => x.IsPublished && x.References.Any(y => y.Date > Today));
You might want to have:reports.Where(report => report.IsPublished && report.References.Any(reference => reference.Date > Today));
- Avoid short-hand notations for identifiers in method bodies:
var psn = _personFactory.Create();
Please, don’t be lazy and do this:var person = _personFactory.Create();
- Avoid generic method names: be descriptive. I literarily start by spelling out what the method does, and if it’s too long it might be that the method is doing too much and I refactor into smaller methods (SRP).
For example, this is one of my pet hates:Validate(person);
What does it do? throw if the person is invalid? Or something else?
If it does throw, how aboutThrowIfPersonInvalid(person);
? Or maybe even better, don't rely on exception flow and allow the caller to decide:var errors = GetPersonDataValidationErrors(person);
- Likewise, please don’t mislead what the functions or classes do. If there is hidden behavior behind the code that the name doesn't not convey, then you haven't named it properly and you have written cryptic code.
Please please please, remember to …
Code for humans, not computers
Borrow a technique from TDD’s Red Green Refactor cycles — if you don’t want to follow TDD
If you don’t subscribe to TDD, you can still benefit from some of the great techniques TDD has: by doing a final refactor cycle. TDD is a continuous series of red-green-refactor cycles: write a failing test, get the test to pass without fussing about clean readable code, then refactor: focus on making the code clean. If you do after-thought testing (or dare I say it, no automated testing!), you can simply refactor at the end of your cycles (maybe it’s just a single large cycle, where you refactor at the end before you submit a PR or push to source control). Put on your “clean coder” hat, separately to your problem solving hat, so you don't get them mixed up. Your code will become much, much cleaner and simpler this way.
Things you can do now and further readings
Read the Microsoft naming guidelines (it’s a short read)
- https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/general-naming-conventions
- https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
- During code reviews if a name doesn’t make sense for you, suggest an alternative.
- Refactor: renaming most things is extremely low risk and very easy to do. Especially with all the refactoring tools out nowadays.
- Consider TDD: even if you write the tests afterwards, do a refactor at the end of all of the testing to make the code more readable.
- Take extra care when renaming web apis / contracts, or public interfaces/classes on share libs: as they can cause breaking changes.
- Consider listening to clean coders podcast on naming things: CC 009: Naming Things with Daniel Markham | Devchat.tv