Debating about pros and cons of different code styles quickly tend to enter “which color is best”-territory, so this is not what I’ll do here, but consider the following an internal debate of mine that occurs from time to time.
The “Structure” of a piece of code spans various topics: from syntactical preferences like conventions for curly braces, to case conventions, naming variables, indentation, line breaks and whitespace in general, how to distribute methods between classes, between files, up to its high-level architecture. I am strictly not talking about the higher levels here.
However, in the finer levels of your code, you will apply a mixture of conventional choices coming from the programming language, the culture surrounding it, and your own background. Some will be shaped by your IDE. Keep in mind that all choices are to be done to aim for one goal:
To produce readable code which is straightforward to argue about.
“Readable” is a heavy word as it bears the inseparability of both (a) prerequisites the reader has to fulfill (who are they and why are they even reading my code?) and (b) that getting used to one convention can greatly affect the reading speed more than any in-grained perks of that convention, but nevertheless, there does exist a dimension outside that.
There is some remaining variability in choice, for example, in how to continue the intendation in a multi-line argument list, how to place newlines in chained calls like fluent interfaces / LINQ in .NET / Promises in JS / … or in chained conditionals – the list goes on.
But for example; what is the optimum, e.g. in this Python example
if (self.evaluate_user_input() and user_role is in (UserRole.Admin, UserRole.ProjectOwner)): do_stuff()# vsif (self.evaluate_user_input() and user_role is in (UserRole.Admin, UserRole.ProjectOwner) ): do_stuff()# vs if (self.evaluate_user_input() and user_role is in (UserRole.Admin, UserRole.ProjectOwner)): do_stuff()# vsif (self.evaluate_user_input() and user_role is in ( UserRole.Admin, UserRole.ProjectOwner )): do_stuff()# vs ... outsourcing any of that logic into its own place,# but even that comes with risks of cluttering structure elsewhere.
Another example are braces in any language that uses them, because I’ve encountered a couple of scenarios where the convention would suggest…
if (theThing) { quiteALot(); ofDifferent(); lines();} else { nowSomeCompletely(); differentStuffToDo();}# breaking the brace convention, just for that "else",# conveys a lot purpose to distinguish these branches. for me.if (theThing) { quiteALot(); ofDifferent(); lines();}else { nowSomeCompletely(); differentStuffToDo();}
Line breaks and continuitation can be crucial because they influence how far the eyes have to extend to the right (maybe requiring horizontal scrolling, which is a dealbreaker in any measure of quickly-understanding), but whitespace can be beneficial in distinguishing your product from a pile of unicode vomit (which is why gofmt is wrong in believing that inline formulae are always better with any spaces distilled out).
The more I think about it, the less I would agree with anyone convinced that one should just strife towards one certain style and then stick to it. Moreover, the actual content of a line of code can dominate the decision at hand more than a well-meaning thought of “all of these decisions are equal, do not waste any time about them”. The point is, that time saved in reading this can outweigh your time saved in not caring about said reader.
Of course, the title of this post was chosen somewhat demandingly because the actual goal with that is consistent code. The point in such situations being, that uniform guide lines do not automatically lead to consistent expression of intention.
Aim for what your specific piece of code needs to convey, then allow the idea of choosing a style that is not the same choice as for difference pieces of code. Do not overthink it either, but do not think that deviances in uniformity are a code smell.
A more variable, more purposeful coding styles is likely to to conflict when more than one developer is involved (because of the accustomization effect), but treat it like any performance optimization – discuss it when your Merge Review is actually troublesome, with intention, not miles ahead for some hypothetical horror scenario.