Beautiful-ugly/explicit-implicit
Let’s start with beauty. They say beauty is in the eye of the beholder. And this is why, when you behold improperly indented code, you begin to understand the beauty of actually indented code. Here is the same code written correctly in JavaScript and Python:
- JavaScript:
const value = 5; for (let i = 0; i <= value; i++) {console.log(i);}
- Python:
value = 5
for i in range(value+1):
print(i)
The JavaScript code works, by the way. It does the same thing that the Python code does. You could write all of the scripts for JavaScript on a single line if you wanted to (and when you build JS frontends, sometimes you do to save space). But which one can you read better? Which one breaks down the information in a better way for you? Python forces this syntax due to its removal of semi-colons in favor of indentations as a way to separate code lines, making the code more objectively beautiful.
But something is missing. You may understand the fact that the code is clear and concise, but you might not understand the code. This is where we must be explicit, in the definition of the code and its variables. Python encourages comments describing every code block as well as a defined structure when it comes to assigning variables. Snake case (snake_case) is used for variables and uppercase snake case is used for constants. Let’s re-write our Python code following these guidelines:
“”” Initial constant that doesn’t change “””INITIAL_VALUE = 5″”” Loop through the range of the constant “””for current_value in range(INITIAL_VALUE+1):””” Print current loop value “””print(current_value)
You don’t need to do this for every line; I’m just being a little more explicit than usual for posterity. But this is the basic way to define variables and comments. No more of that i, j, and k stuff. Be kind and be defined.
Definition simplifies things, which is what we are going to discuss in this next section.
Simple-complex-complicated
Simplicity must be maintained wherever possible. That is the rule because, well, it’s easier that way. Keeping things simple, however, is hard. It’s impossible sometimes. As an application or a solution becomes greater in size, the complexity becomes greater too. What we do not want is for the code to become complicated.
What’s the difference between complex and complicated? Code is complex when it is written to sustainably deal with all the scenarios presented before it dynamically and understandably. Code is complicated when (in a complex solution) it is written in a way that handles every possible case based on static, very specific parameters (hard coding) and in a way that becomes difficult to understand, even for the person who wrote it.
I have seen a lot of it over my career; I wrote a lot of it at the beginning, too. It’s a learning process and if you don’t build good habits, you will fall into bad habits or fall back to a simpler solution for a more complex problem.
Once, when reviewing an old Django code base, I encountered an API written not in any API library but written using the pandas data science library with the ensuing result being presented using the Django JSONResponse function. It was baffling, and I couldn’t help but think about why someone would write the code this way, until I found out that the person who had written it had had no previous web development expertise and was instead a data engineer. So, they reverted to what their vision of simplicity was: data science libraries, even for backend development.
Now, this slowed down the application immensely and, of course, had to be refactored, but – since we are blameless on individuals in this book – we couldn’t blame the developer. We have to blame the habits that they fall back on and the simplicity they seek that eventually results in complicated code, when a slightly more complex yet concise solution would have resulted in better code.