I'm a software engineer working as a full-stack developer using JavaScript, Node.js, and React. I write about my experiences in tech, tutorials, and share helpful hints.
Helps in scanning files if everything is "as it should be", exact styles aren't as significant as some make them out to be, but consistency is.
Naming things well.
Some developers have trouble with this, but I like to think of it in a simplistic way. If someone came to you and asked "what does this do?", rephrase the response into a name. If every variable is a basic noun, things can get muddled and there is extra overhead to understand the code when repeat names that are basic continue to show up. Being slightly more descriptive makes a huge difference.
Comments that are complete sentences (subject/predicate) that do not only restate the code.
I don't say that to test English, but I have seen a lot of comments that are very vague or cryptic. They might be a sentence fragment or phrased as a question without a question mark, so it can be confusing as to what the meaning is.
Avoiding brevity and making code for humans to read.
Abbreviations and acronyms might make sense when writing it, but it might not mean anything to others or yourself in the future.
Formatting, style rules and code documentation aside, I try to get rid of anything that adds cognitive load, no matter how tiny that load is. Braces, nested structures ifs and elses and other control structures can add to that. I try to get my logic as "flat" (indented on a single level) as possible.
If there is a bunch of ifs and elses in a method, I refactor them out into smaller private methods with self-describing names. If those are still too big I repeat the process until I have small methods that pretty much do just one thing each.
I try to keep methods brief. They should not span over the height of one editor page.
I try to keep classes small. I guess if a class grows beyond 500 to 600ish lines it's probably time for a split.
If an if-condition is complex then I split the condition out in a separate method with a self-describing name.
I often do that even with simple if-conditions, because sometime's it's not clear why we do:
if (sku.endsWith("X")
but the following is much clearer and doesn't require asking any questions:
if (isRetiredProductSku(sku))
If a method / function has too many arguments (3 is already scratching the limit) then I try to refactor so:
Either most of the argument values are stored as properties if possible (and if it makes sense)
Or the arguments are consolidated in a single configuration or context object, where grouping them together makes sense
Using the builder pattern can also help with reducing the amount of method arguments
That's... just off the top of my head at the moment π
Hi Thomas, I loved your small example. This is exactly why I was fighting for in my ex-team, "yeah, but I won't create a function for only one line of code"... Stubborn junior devs, they've made me loss a few hair ahah.
I guess your former colleagues were still OK with adding comments in case of especially obscure logic?
So it's either this:
// Retired product SKUs end with X
if (sku.endsWith("X"))
or that
if (isRetiredProductSKU(sku))
The second version is actually more maintainable. The rules for detecting a retired product SKU might change over time. In case of the first version with the comment it would be necessary to update both the code and the comment, and usually the latter one is forgotten.
Anyway, for people who are really allergic to writing extra functions, here's another variant that is also more readable:
const isRetiredProductSku = sku.endsWith("X");
if (isRetiredProductSku) {
...
}
I think sometimes the best you can do in a team like that is to lead by example in your own contributions, and eventually they start appreciating the readability of the code you write and adopt your style π€·ββοΈ
I totally agree with you. Yeah, I've tried to lead by example, but that didn't work either. But thanks to that my manager moved me in another team, much much better! That was such an experience, professionally: working with really bad code, and personally: mental health ahah.
I think they didn't listen because I'm younger, by ego I suppose, I don't really know but that's bad for them.
We have to let your ego aside and listen to people to progress :)
I graduated in 1990 in Electrical Engineering and since then I have been in university, doing research in the field of DSP. To me programming is more a tool than a job.
I am on the side of readable names. In my opinion (and experience) if you use good names you can avoid most of comments in the implementation.
Sometimes I collect a piece of code in a procedure that is called just once, only to provide a "descriptive name" to that piece of code. Of course, it is not efficient because of the stack manipulation at call/return time, but if efficiency is not a strong issue (and often nowadays it isn't), the gain in readibility is worth the inefficiency.
Of course, coherent and good formatting helps a lot, but nowadays you can outsource that to the IDE.
About comments: I usually do not put comments in the implementation, comments that should explain what the code does. If you choose the right names and your language is fairly high.level (so you do not have to mangle with pointers at every line of code), the code is often self-esplicative.
I usually use comments to document stuff that (i) is not immediately clear from the code and (ii) it is pretty stable (so it does not change often when the code changes). Most of my comments are put in the spec file of a package (.h for C people) to explain (i) what is the objective of the package, why it is there and (ii) what is the duty of every procedure declared there.
Sometimes I collect a piece of code in a procedure that is called just once, only to provide a "descriptive name" to that piece of code. Of course, it is not efficient
It depends on your compiler: in C, if you write said function as static inline, the compiler might insert it in your code (it is said to be as fast as macros).
I graduated in 1990 in Electrical Engineering and since then I have been in university, doing research in the field of DSP. To me programming is more a tool than a job.
You're right. I think that many compilers could do that autonomously during the optimization phase. If I remember correctly gcc does this unless you specify an option.
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
Another master, whose words I bring in my heart is Winston Churchill, and there is two quotes of him I want to echo to inspire you as they did with me.
The first says:
All the great things are simple, and many can be expressed in a single word: freedom, justice, honor, duty, mercy, hope.
And the second,
Short words are best and old words when short are the best of all.
As those masters with theirs writings, I see my code as poetry. Sometimes I spend hours in a few lines, as if I was writing a testament. (If I must leave a legacy, I want it be precious.)
So, when writing your next line, remember those luminaries of the past and please,
Many people have already said almost everything I would put so I will just add one more little snippet: don't use every piece of magic and syntactical sugar known to humanity.
Something like a simple loop can tell a whole story where something like .map(...).filter(...) etc can be hard to reason about. Verbosity is not always evil.
Smaller functions - Huge functions make things difficult to comprehend and build a mental model of.
A function should do one thing and one thing only.
Complex tasks should be achieved by composing together smaller functions.
Smarty pants is bad - whether you are working alone or in a team. Not everyone has the same mental model for a piece of code. If you try to be excessively clever you will slow others down.
Verbosity is a fine line. Don't get overly verbose with your code nor make it so short that people have to break down steps line by line.
Add tools as your codebase grows. Don't start with every thing known to the ecosystem from the get go.
Be cognizant that all advice (including this one) is subjective. You should evaluate your condition and strategize accordingly. Just because one big company does things one specific way, doesn't mean you should go apply it immediately to your project. I've seen plenty of startups frustrate themselves by imitating how one particular FAANG does its work.
// , βIt is not so important to be serious as it is to be serious about the important things. The monkey wears an expression of seriousness... but the monkey is serious because he itches."(No/No)
My tips:
Formatting, style rules and code documentation aside, I try to get rid of anything that adds cognitive load, no matter how tiny that load is. Braces, nested structures ifs and elses and other control structures can add to that. I try to get my logic as "flat" (indented on a single level) as possible.
If there is a bunch of ifs and elses in a method, I refactor them out into smaller private methods with self-describing names. If those are still too big I repeat the process until I have small methods that pretty much do just one thing each.
I try to keep methods brief. They should not span over the height of one editor page.
I try to keep classes small. I guess if a class grows beyond 500 to 600ish lines it's probably time for a split.
If an if-condition is complex then I split the condition out in a separate method with a self-describing name.
I often do that even with simple if-conditions, because sometime's it's not clear why we do:
but the following is much clearer and doesn't require asking any questions:
If a method / function has too many arguments (3 is already scratching the limit) then I try to refactor so:
That's... just off the top of my head at the moment π
Hi Thomas, I loved your small example. This is exactly why I was fighting for in my ex-team, "yeah, but I won't create a function for only one line of code"... Stubborn junior devs, they've made me loss a few hair ahah.
Ah how rude of them! π
I guess your former colleagues were still OK with adding comments in case of especially obscure logic?
So it's either this:
or that
The second version is actually more maintainable. The rules for detecting a retired product SKU might change over time. In case of the first version with the comment it would be necessary to update both the code and the comment, and usually the latter one is forgotten.
Anyway, for people who are really allergic to writing extra functions, here's another variant that is also more readable:
I think sometimes the best you can do in a team like that is to lead by example in your own contributions, and eventually they start appreciating the readability of the code you write and adopt your style π€·ββοΈ
I totally agree with you. Yeah, I've tried to lead by example, but that didn't work either. But thanks to that my manager moved me in another team, much much better! That was such an experience, professionally: working with really bad code, and personally: mental health ahah.
I think they didn't listen because I'm younger, by ego I suppose, I don't really know but that's bad for them.
We have to let your ego aside and listen to people to progress :)
I am on the side of readable names. In my opinion (and experience) if you use good names you can avoid most of comments in the implementation.
Sometimes I collect a piece of code in a procedure that is called just once, only to provide a "descriptive name" to that piece of code. Of course, it is not efficient because of the stack manipulation at call/return time, but if efficiency is not a strong issue (and often nowadays it isn't), the gain in readibility is worth the inefficiency.
Of course, coherent and good formatting helps a lot, but nowadays you can outsource that to the IDE.
About comments: I usually do not put comments in the implementation, comments that should explain what the code does. If you choose the right names and your language is fairly high.level (so you do not have to mangle with pointers at every line of code), the code is often self-esplicative.
I usually use comments to document stuff that (i) is not immediately clear from the code and (ii) it is pretty stable (so it does not change often when the code changes). Most of my comments are put in the spec file of a package (
.h
for C people) to explain (i) what is the objective of the package, why it is there and (ii) what is the duty of every procedure declared there.+1 on the avoiding comments. I remember hearing somewhere that most comments are lies.
It depends on your compiler: in C, if you write said function as
static inline
, the compiler might insert it in your code (it is said to be as fast as macros).You're right. I think that many compilers could do that autonomously during the optimization phase. If I remember correctly gcc does this unless you specify an option.
I think readable is code is too subjective to provide a one size fits all solution to achieve it.
Qualities that make code readable?
How much can you understand with the least amount of context. Code that requires the least amount of context is often considered readable.
what helps one create readable code?
Context/information. Descriptive variable/function names and comments are a good way to give context.
Knowledge also plays a big part on what one person considers readable.
To make a code readable, the fewer words you must read, the better.
That's why I'm a big fan of terseness, (hence my nickname)
A great thinker I love is Saint-ExupΓ©ry. He once said:
Another master, whose words I bring in my heart is Winston Churchill, and there is two quotes of him I want to echo to inspire you as they did with me.
The first says:
And the second,
As those masters with theirs writings, I see my code as poetry. Sometimes I spend hours in a few lines, as if I was writing a testament. (If I must leave a legacy, I want it be precious.)
So, when writing your next line, remember those luminaries of the past and please,
Keep It Simple Sweetie
Many people have already said almost everything I would put so I will just add one more little snippet: don't use every piece of magic and syntactical sugar known to humanity.
Something like a simple loop can tell a whole story where something like .map(...).filter(...) etc can be hard to reason about. Verbosity is not always evil.
In addition to what everyone else has said -
Smaller functions - Huge functions make things difficult to comprehend and build a mental model of.
A function should do one thing and one thing only.
Complex tasks should be achieved by composing together smaller functions.
Smarty pants is bad - whether you are working alone or in a team. Not everyone has the same mental model for a piece of code. If you try to be excessively clever you will slow others down.
Verbosity is a fine line. Don't get overly verbose with your code nor make it so short that people have to break down steps line by line.
Add tools as your codebase grows. Don't start with every thing known to the ecosystem from the get go.
Be cognizant that all advice (including this one) is subjective. You should evaluate your condition and strategize accordingly. Just because one big company does things one specific way, doesn't mean you should go apply it immediately to your project. I've seen plenty of startups frustrate themselves by imitating how one particular FAANG does its work.
Being consistent, I think.
Sure, we all have our tastes, but if you read new styles every file, you go crazy.
The aim: Code my gran could read.
The reality: Code my dog could eat.
// , How do you test for that, and by what metric would you measure whether a given piece of code is "readable"?
It does what it looks like it should do. There are not unexpected results from running it after I read it.