You can read each symbol, but you canât make sense of the text.
Disclaimer: Since I work with JavaScript mostly, the article can be seen in the light of JavaScript aura, nevertheless, it is a general issue and should not be limited by boundaries of one language. All said below is applicable to entire software development.
We are too much obsessed with how do we write code
New design patterns, new frameworks and libraries, or, even new languages (TypeScript, Elm, Reason, ClojureScript, Dart) being created each full Moon, to help developers to do the same thingâââto write down application logic. Hadnât we already had multiple ways of writing code before? Do we really need that one more framework, which will help us to describe application logic a fraction better than weâve been doing already? Maybe. Donât get me wrong, I like constant improvements in existing frameworks, and I like new frameworks and tools being created, but, I donât think we should spend all our energy and give all our attention only to that. As an industry, we are too much obsessed with how do we write code, we want to make writing process perfect, while the way how do we read code is totally left behind.
Observation #1: We donât write code in the vacuum, almost always we rather edit or extend existing codebase than adding new features on the blank page.
Code reading phase must follow first
It means all code changes you plan to make will fit only if you read and understand code around. And you may think: âHe must be kidding, of course, we understand code around before doing changesâ. Do we? So many times I caught myself on a thought that I have quite a narrow view while making changes in code. Itâs just that one more line, one more property, one more simple behaviour to already existing feature, I can just write that code right away, right?...
Observation #2: We do local code changes and totally miss the big picture.
Now multiply all of that by the number of team-members who edit your codebase without picturing an entire application. What will happen in long term?
Remember all the projects youâve built from scratch? We all had that. Nice and fancy architecture, clean code, separate modules, encapsulated logic. Clean code, did it look the same a year later? Two years later? Probably, the answer is ânoâ and you may already start wondering, why is that? What obstacle we had to continue building nice and clean architecture? Itâs an easy questionâââwe already had code there, thatâs why. All we need to do was: to read code around, understand it and make proper changes, not just put âone more method call thereââââonly because code lines should be executed at one moment of time it doesnât mean that code lines should be in one method (but I know, itâs easier like that).
Observation #3: It seems like we have quite a struggle to write code properly if we need to read and understand existing code before that.
Reading is hard, thatâs whyâŚ
âDeadline tomorrowâ, âthat old legacy from the previous teamâ, âI am a bit sleepy todayââââall these and many other excuses we use to not read code. We do assumptions instead: âI believe we donât have this util method yet, Iâll add itâ, âI think itâs a bit duplicated logic, but I canât refactor everything nowâ, âOne line fix, it must be the best solution everâ. That means we make changes in code blindly, only based on our guesses about code, but not based on knowledge after reading and analyzing code.
We avoiding reading code not because we are bad engineers, but, because itâs super hard. Itâs the hardest task you can imagine in programming.
You take thousands small pieces and you need to generalize them to something more meaningful and less granular, in parallel recognizing repetitions and patterns, you are trying to see the big picture and make sense of all of that.
Observation #4: We either spend too much time ineffectively reading code, or, just decide to not read it at all.
What does it even mean to âread codeâ?
Well, first of all, letâs finally describe what it means to read code. Itâs definitely different from reading your favourite fiction book, right? But letâs define code itself first. If you try to come up with the definition of application code in your own words, it may look like this:
Code is a set of instructions (spread between files) that follow and transform data for pre-defined journeys, based on user behaviour and current environment state.
Now, when we know what is code, itâs easier to understand what we trying to achieve when we are reading code. We want to:
- find out key steps for main journeys within an application (e.g. user registration, order submission, etc.)
- find out possible instructions which may affect data flow within a particular journey
- find out current environment state or circumstances which may affect it
And we want to find out that fast. And have that knowledge forever in our minds. Because if you have that in your mindâââyou can see the big picture of the entire application logic being mapped to codebase. You feel that power, donât you?
You got a bug, and you already know why it happened and what line in code you should change, without even reading code. Or, they asked you about new feature, and you already know what refactoring in what file you should make in advance to keep clean architecture.
And then you woke up. Sounds too sweet to be true. Or can we do that?
Engage with code, donât just look at it
And now you may think: âCmon dude, I am losing my temper here, why are you talking about these obvious thingsâ. Well, obvious things that bother no one. How many tools or techniques do you use to read and understand code? Effectively. Itâs a key word here. We can understand and make sense of any code if we have all the time in the world, but usually, we donât. And usually, we just open codebase in our favourite code-editor and start jumping from file to file in full chaos. And it bothers me. We can do better than that.
First of all. in order to start understanding code, it is not enough just to read it. You need to dive deep into it to be able to feel it. You need to engage with code, it reinforces your learning abilities. That is why refactoring helps so much to understand codeâââyou read and make adjustments in parallel.
But not only refactoring can do that. You can start doing harmless changes in code by writing comments. You can start leaving breadcrumbs in code: itâs very important thing to mark places in code where you already been, places you already have seen and analyzed, or places you just donât want to miss. You can always use them as a trail to find your way out of a code-maze.
And, since I mentioned code-maze, letâs think about it. Maybe, weâve been looking at code from the wrong position all this time? Itâs hard to find a way out from a maze (meaning, hard to read code lines and connect dots in your mind) when you are already deep inside a maze. Maybe, we should do one step back here. Imagine you are not inside a maze, but you are looking at it from the topâââso itâs not a maze anymore, you can clearly see everything! And since you are imagining, think about even crazier scenarioâââwhat if entire maze just had gone and youâve been guided where you should go and what file look to? Imagine all that noise of huge code base just disappeared..
What if there may be solution for all of thatâŚ
Stay tuned, more coming soon.
If you liked this post and want to have updates about my next articles, please follow me on twitter @bliashenko!