As software developers, we deal with classes, interfaces, modules every day. But why do we need them? Yes, this is a stupid question — and you would probably say that they help simplify our programs. Let’s think about some fundamental questions — why is it difficult for our brain to understand and work with spaghetti code 🤯.
Why do we need classes, interfaces, modules, etc?
Computers don’t care how many classes, functions, or interfaces in your program. In the end, our program will be converted to bytecode without classes, functions, interfaces. Computers don’t care if your program is a terrible spaghetti code or a well-designed solution. They will equally easily understand and execute both options. The reason why do we use classes, interfaces, or software principles is to make your program easier for humans. A program that is easier to understand is easier to maintain and it has fewer chances of bugs. Ease of understanding for a person is the key to success.
How to make programs simple for our brains?
To make programs easy for us to understand, we need to turn to the basics of psychology. Pretty sure, everyone heard about The Magical Number Seven, Plus or Minus Two. The basic conclusion is
The number of objects an average human can hold in short-term memory is 7 ± 2.
Why do we split a function of 10K lines into classes and modules? Yes — because our 🧠 cannot hold it. I imagine our short-term memory as a RAM of the machine. It just doesn’t have enough capacity to allocate enough memory for the program.
To reduce required memory we move the logic to classes, modules functions, etc, making the body of the function shorter.
Focus on the Current Context
Let’s imagine some common web application. It has a few layers:
Such separation helps our brain focuses only on the current context. While we are working with the controller, our brain focuses on its context. We know that we need to
- get request data
- validate user input
- pass data to model
- return web response
And we don’t really think about how we get there — how the application has been initiated, how we load configuration etc. And we don’t think what happens next in the model layer. We are focused on the current context. By reducing the amount of the variables we simplify work for our brains.
The most important part is the clear boundaries between the layers. That will help us “isolate” the current layer. If we have connections to other layers — global variables (ENV, service locators, etc), dependencies — they will distract our brain.
Also, remember that when you remove complexity in one place, it usually appears in another. You can follow the magic 7 rule and for example, try to ensure that the number of methods in the class does not exceed 7, but then, in this case, the number of classes and the relationships between them also increases. So do not go crazy about the rules, keep a balance, and remain pragmatic.
But wait… when we split a program logic, we don’t reduce it, the same logic remains. We simply distribute it among different classes, modules. Still, we must somehow keep it in our minds. This is where another ability of our brain comes to the rescue — memory chunking.
Сhunking is a process by which individual pieces of an information set are broken down and then grouped together in a meaningful whole. The chunks by which the information is grouped is meant to improve short-term retention of the material, thus bypassing the limited capacity of working memory. A chunk is a collection of basic familiar units that have been grouped together and stored in a person’s memory. These chunks are able to be retrieved more easily due to their coherent familiarity. It is believed that individuals create higher order cognitive representations of the items within the chunk. The items are more easily remembered as a group than as the individual items themselves.
Doesn’t ring a bell? When we create some class or interface, we collect logically related elements together for a reason — our brain can remember and keep them in mind easily. The better the analogy with the real world in your class, the easier it is for the brain to retrieve it. Say Hi to OOP & DDD. If your class performs several functions, it will be more difficult for our brain to make a chunk.
In order to simplify work for our brains we have to:
- split logic between classes/modules/functions using logical relationship rule and following magic 7 rule, your brain cannot do more 😛
- reduce coupling
- balance complexity
- stay pragmatic
All of them quite fundamental but right now we understand the nature of these rules.
P.S. In the next article I will give some practical examples when we violate the Single Responsibility Principle.