In stories, you will often find the motif of a powerful demon that can be controlled only by knowing its true name. Once the hero finds out that na...
For further actions, you may consider blocking this person and/or reporting abuse
Counter-argument : I don't find
fetchDemographicStatsForFirstAndLastName
"clean" at all.Uncle Bob acts as if there is no downside at all of using super long names
But there is a clear downside : cognitive load.
Imagine an article that was written like that.
Full of german words like PersonalEinkommenSteueerungsKommissionsMitgliedReisekostenErgänzngsRevisionsFund.
See how clean it is ?
Not.
The writer's goal is to increase the signal to noise ratio of his writing.
I strike instead to find a balance between clarity and verbosity.
Frequent words are shorter and less frequent functions longer.
The issue with first name and lastname in your example is that you are victim of primitive obsession, using strings instead of a real type.
I would refactor that to
function fetchDemographics(user) : Demograhics
Also "clean" is judgmental and nonsensical, no real code ever is clean.
Uncle Bob doesn't produce production code so for him that doesn't matter much.
But people who do should not stress out if they don't reach arbitrary levels of cleaness that don't matter to the customer anyway.
Totally agree!! If I'm reviewing and see this:
fetchDemographicStatsForFirstAndLastName
it's a no go!
Naming should be meaningful but readable. There's a balance and a matter of good taste to put it in practice.
Yeah I don't like that example either, but mainly because firstName and lastName are already described in the definition in the arguments. Seems redundant, especially in the age of IDEs that'll pop up the function definition or the definitions of all potential candidates as soon as you start typing it to call it.
Still, I would opt for a longer name than a comment above it any day.
Interesting! I see both sides. What would be the ideal name for you? Also, I like very much the idea of using types to tell the story, if possible.
The naming is ideal if it's clear for your coworkers so pull requests is the place to ask for feedback.
As a rule of thumb, I prefer to use shorter names for frequent actions and longer / more explicit names for less frequent actions.
❌
queue.removeElementAtFirstPosition()
✅
queue.pop()
❌
queue.remove(7)
✅
queue.removeElementAtPosition(7)
Primitive obsession -> refactoring.guru/fr/smells/primiti...
As Jean-Michel said, depends also of your coworkers culture and practices, for me a simple getDemographic or getUserDemographic will suffice. The first one is fine because it's clear that we need to pass User as an argument... but with we have several types of demographics in the app I'd go with the second.
Different cultures and languages communicate differently. In Europe for example, Mediterranean languages rely more on the context to pass the correct intent and be understood, while germanic and slavic are more about making it clear verbosely.
Same in code, for me, even the above queue.removeElementAtPosition() could have the Element dropped because it's a queue of elements... of course we are removing an element at that position.
And totally agree. Types tell you the context. I had a discussion recently with a new member in my team about adding the Async suffix to some methods in our api just because it's Microsoft's convention for c#. It's an API, everything is async by default, synchronous DB operations are the exception, so let's use the suffix for situations when we have an async and a sync methods to distinguish between them. For the rest, the type Task<> should be clear enough to indicate it's a asynchronous operation.
amazing write up, thanks so much for sharing Rai 🙏 I completely agree, context is the king. The most important thing is that team is in sync and consistent it the naming practices they agreed upon.
Author here - I agree, that might be a better name! Note that I was sticking to JavaScript here, so didn't want to use types - but I agree that if we have precise types, it can be ok to ommit that same info from name.
I use Haskell a lot these days - and there types are the name of the game. But, Haskell has no function overloading - so if you have two functions that fetch demographics, you will suffix them with some extra info about args, to differentiate them.
Soit really depends on the language:is it strictly typed, does it have function overloading, ... .
And while I agree that shorter names result in code that is easier to read quickly, practice has still shown to me that when not sure it is better to err on the longer side. It does depend on how often name is used also, as you said: but the name from my example is probably not going to be used often, it is quite specific, so I don't think making a name shorter will bring any benefits.
Your refactoring is interesting but I don't think I would go for it: it has arg "user" which is not as specific as "firstName" and "lastName", so it is not clear how is search really being done, which attributes are used to determine the people that are part of the demographic? Maybe you misunderstood and thought that we are getting demophragic data for just one person? But that doesn't make much sense because demographic is defined as statistics for a group of people.
As for "clean" being judgemental and not being realistic: I sometimes hear this argument about Uncle Bob being overly extreme in his book and not being practical, and I found so far that those who make this argument haven't really understood the essence of it. Of course there is no clear delineation between clean and non clean code, and sure, the book sometimes goes to a bit extreme lengths - but if you take the advice from it with a grain of salt and apply it, you will see a big difference, and your code will be much improved, so that is all that matters. Again, it is all about context, it depends on people, project requirements, tevhnology - a good engineer will figure out, with experience, how to apply the "clean code" to their situation with the right measure.
Maybe you misunderstood and thought that we are getting demophragic data for just one person
Indeed, I did :)
That's the thing, it's all context dependant but Uncle Bob delivers the same rules for everyone.
More often than not, devs end up delivering "quality" that don't matter one bit to the client.
They implement "clean architecture" because they don't want to be dirty devs.
Doing so, they loose sight that what really matters is usually not that but the time to market.
Why not both you may ask ?
If you are lucky it may work, but there is a real danger in poursuing the wrong goal.
Worse than that it often makes life worse not better for the people that are hired after them. Since programming is all about communicating with your colleagues, if you reach that point it's your failure not theirs.
One of the best articles I've read lately and it's a must-read for anyone. Naming things properly is one of the most important things we do.
And this isn't just important for projects that have teams around them. Think about coming back after some time on your code and you see incomprehensible names. It's such a time-waster trying to dechiper what you thought at the time.
Yes exactly, I usually do it for myself first, then for others :D! Even a couple of days later, I hardly remember what I was doing -> if it wasn't for clear names I would get lost.
This is great, and agreed - naming goes across everything. I remember trying to come up with a name for our first startup ... and we couldn't find a good one, so finally called it 'PlanForCloud' - that name existed till we were acquired, and quickly killed hahaha
Hah oh yeah, the name of the project is one thing that is the hardest to change :D. I love "Infracost" though, it is easy to remember and on point -> captures the essence ;).
In addition to Clean Code by Uncle Bob, The Pragmatic Programmer is worth a read!
Absolutely! My favourite is also "The Software Craftsman".
I read both and personally wasn't keen
Uncle Bob especially, dude broke his own rules in his examples, and just wasn't consistent at all in what he was saying.
This is a great article! I've always named variables and functions based on what they do and it makes code a lot easier to understand but something I noticed about myself was that I would do this but still over comment..
Commenting is important but it doesn't have to be extensive. If you write clean code it will speak for itself.
I completely agree with your statement.
Personally, I would also like to emphasize the importance of accurate indentation and file separation in addition to these points.
In the case of bun, the number of lines in a single file exceeded 20,000.
Absolutely love this article, and could not agree more!
I was literally discussing some of the same points with a friend yesterday :)
Essentially, if someone names their code properly, it's beautiful and typically easy to follow; as you also stated, the main reason being that writing clean and good code is a prerequisite to good naming. And such code is easier to understand.
The converse is also typically true -- if code was named recklessly, ... good luck in understanding it.
Since I've been thinking about this quite a lot, here a tidbit of my reasoning related to self-descriptive vs non-descriptive names:
MORE GENERALLY, giving an idea (e.g. a system component/server/etc) a name is crucial because it makes it immediately possible for everyone to think about it in bounded terms (as long as we have a shared understanding of it basic meaning, we will all mostly agree what you mean when you mention X, or agree on whether Y is part of X or not, etc.).
This was nicely emphasized in Orwel's 1984 and its Newspeak: if you don't have a shared name for a concept (or are forbidden from using it, like protest in 1984), then it is very hard to plan/collaborate because you need to be providing the idea's boundaries and description every time: "let's go to the main square and cause a bit of upheaval and raise attention to our cause, but not too much so that it does not become dangerous", rather than simply say "let's go and protest".
HOWEVER, as much as I love (and typically use) self-describing names in code (no need for comments/less documentation!), it is actually often beneficial to name certain types of entities closer to how we name children: use names which are disconnected from their characteristics (as those are not known at creation time :D).
This is typically true with ideas whose names are hard to change (e.g. companies!), but whose functionality evolves.
Using nondescriptive names like "fluffy", "lookingGlasss", "Armadillo", "Beast", essentially creates a layer of indirection/mapping that allows us to gracefully extend/change change their characteristics/behavior/responsibilities with time by simply updating the documentation to take the changes into account.
Otherwise, we end up in a typical situation where each name has a caveat about "historical reasons why it is indeed called ProxyServer, but that name is long deprecated,it actually also does A, B, C and D".
That is an interesting take and makes perfect sense to me, thanks for sharing!
I guess this would be for bigger sub-systems, where as you said, the role of it may change to some degree with time, and it is not yet clear what it is going to be exactly.
I agree that for common concepts it is good to have short names. And it works, because we assume everybody working on project will have to learn what those stand for, and in return we get easier naming / reading / talking about them. In the current project I am working on (Wasp), we have such names: Entity, Analyzer, Generator, Operation, ... -> these do require context to be understood, but they are so widely used and central to the whole project that these short names work fine.
I love your inclusion of cartoons, really adds to it
Great article! 100% agree with everything here! Naming (and structure) is what makes your code clean so it is easy to get back and continue working when you need to, same with having a tidy clean room or workstation.
Whenever I need to add comments to my code, I always stop with it and think about a better naming instead.
I also use specific rules for naming variables, e.g. dates and timestamps always end with
<name>At
(createdAt
,lastModifiedAt
), maps are always<key>By<value>
, (e.g.personById
,titleByCode
), sets have prefixunique<x>
, booleans start withis<x>
,has<x>
, etc.Thanks, love those prefixes/suffixes! I listed only a couple of them, but I also use stuff very similar to what you described, especially the thing for maps / grouping "By".
I think it would be very interesting to add more examples to the article but it started feeling very long at some point.
it would be nice to produce some kind of naming cheatsheet / styleguide that people can refer to and fork
Such a nice article!
Creating names is a big part of the reason I like TailwindCSS so much by the way.
It takes a lot of effort coming with reasonable and good names everytime. Having this weight lifted off your shoulders at least for CSS classes is pure relief.
Good job, @martinsos!
+1 on this, the best thing with Tailwind is not having to invent names - that's an amazing point Lucas :)
Great article. Some of the recommendations are language-specific, though.
I am still getting used to the fact that, in Julia, being a language with multiple dispatch, the best function name is usually a short word. For example,
mean(A::AbstactArray)
is expected to compute the arithmetic average, whereasmean(d::UnivariateDistribution)
provides the theoretical expected value of a distribution.Great Article!
Just for fun, here's some more examples of less-than-ideal names and misnomers in the tech world:
double
- A ridiculous way to call numeric datatypes, but we're all used to it (float
is not the best name either).That's all I can remember for now! :D
Love it!
In Raku language there is a feature that makes names super consistent across whole codebase by sheer force of laziness. Like this:
greet
function signature:$person
means it is expecting named param called 'person'.:$person
in a syntactis sugar forperson => $person
.You may ask - what is the big deal?
Well, if you can write less by simply aligning your naming with function interface - you will intuitively do that both ways. Define matching variable names when having function and define matching function signatures when having variables. You will immediately spot misalignments like:
This ability to use variable as named param if name matches is by far my favourite feature of Raku.
BTW: "Clean Code" by Robert Martin is indeed an excellent book.
Great article! Typical parents, getting you the thing they think you need 😂
Pieces of this article would make for some great Twitter threads and probably start some interesting discussions.
This might easily be the best article I've ever read on programming :).
Nice article and discussions here and I agree with some readers: the chosen name seems overly long. Would be unnecessary for me to add first and last name to the function name. Other than that I‘d always opt for balance between clarity and verbosity. With slightly more comfort on the clarity side. Comments I completely neglect until it becomes inevitable to use them.
dang! I had never considered some of the points before. learned a lot
Hey, this was a good read.
Do you think I could also write for Wasp?
Hey Angel, join our Discord at discord.gg/rzdnErX and ping us there!
Right away. I am grateful for the opportunity to do so. Check out my articles as well and let me know your thoughts 🥂
Last time, I often ask ChatGPT for variable or function names.
That's a good idea! How does that work out for you? I guess one thing it is missing is a wider context though?
The context can be provided to ChatGPT with links to a documentation or GitHub Copilot X can be used on a whole code database.
Simple example:
You can even try to improve you ugly code:
Code cleanliness is extremely important.
Great article, I especially liked the part on what is a good name. It reminded me of the classic: Long Names Are Long.