Or let’s just keep talking?
photo by Alex Bunardzic
Writing software code is a very expensive activity. Many renowned programmers/developers have devised various methodologies distilled into so-called best practices, each aiming at taming this expensive complexity.
Here is one guru’s opinion:
Procedural code gets information then makes decisions. Object-oriented code tells objects to do things. (Alec Sharp)
The above may be true, but the question remains: where does object-oriented code get its information that is guiding it in what to tell objects to do?
Imperative Programming Considered Naive
The world appears as a complex, almost chaotic mess to our rational mind. Many attempts at making sense out of it end up as overly naive, simplistic models and simulations. Imperative programming is one such attempt. It starts from the assumption that we can say “do such and such” and the world obeys. We then naively say “now change that” and voila! it changes it.
Why is the above imperative approach naive and unsustainable? Because it assumes that it is possible to stop the world while we take a look at it and to keep the world suspended in mid air while we take the time to change it. But the world doesn’t work like that. In real world, there are no omnipotent agents. We may attempt to instigate a change in the world, but our attempts and efforts may get messed up by someone else’s attempts and efforts. The thing is, we cannot isolate some portion of the world in order to try to understand it and modify it. The world doesn’t wait for anyone. The world is pluralistic to its core!
Well, this is a problem, because most of today’s software development is done using object-oriented programming languages. And in object-oriented programming paradigm, one of the main dictums is to use the “tell, don’t ask” paradigm. In other words, object-oriented approach appears to be built on the imperative programming principles. Meaning, object orientation seems built on the naive assumptions that the world is easily manipulable and it will stop and wait for us to tell it what to do.
Interrogative Programming Considered Insufficient
Our rational world is the world of duality. Everything in there is polarized and split into pairs of extremes. If on the one end of the polarized extreme we have the imperative paradigm which claims that it’s best to “tell, don’t ask”, then we immediately have the other end of the polarized extreme which claims that it’s best to “ask, don’t tell.” Unfortunately, such polarized picture of the world is not even close to reflecting the reality.
Those who have no firm grasp on this would fall into a trap and would conclude that, if the “tell, don’t ask” approach is naive and unrealistic, then the “ask, don’t tell” approach is definitely the way to go. However, both extremese are wrong. To adopt the “ask, don’t tell” approach would mean that our resulting programs would be insufficient, because they would not be able to implement any meaningful behaviour without getting heavily enmeshed in the jungle of all kinds of intricate details.
Keep Talking
As is usually the case, a more mature way is somewhere in the middle. It is foolish to assume an omniscient, omnipotent position and claim that the only way to accomplish something is to just tell objects what to do. At the same time, it is equally naive to expect that by merely asking, we can hope to achieve our goals.
A less naive way would be to implement both capabilities: ask simple questions and let answers to those questions guide subsequent actions. And in the world of software programming, the only feasible way to accomplish that is to take snapshots and then work off those snapshots. It would be maddeningly complex to work directly with the objects that are susceptible to sudden unpredictable changes.
This is why immutability is becoming one of the most important aspects in the best practices related to software development. If a software object we’re dealing with is not immutable, we cannot predict how will the interaction with that software construct unfold. Because of that, if we’re not taking care to work with immutable objects, our implementation will end up being riddled with all kinds of errors and defects. Those defects are extremely difficult to diagnose and fix, simply because such sloppy code is extremely difficult to grasp, follow, and test.