muhuk's blog

Nature, to Be Commanded, Must Be Obeyed

January 13, 2019

First Order Thinking and Pragmatism Are Not the Same Thing

Most non-technical people think software development is a standardized, repetable process. That is why they come up with enterprise agile frameworks. If it was standardized we would not need to write software but we would generate it from specifications[1]. Every new project, every new task has a component of discovery. It requires us to think outside of the box. Therefore assembly line approach to software development produces mediocre results at best.

If we were solving the exact same problem again, we would not be repeating the same actions but we would be copying (reusing) the existing code. If the code was not written with reuse in mind, we can refactor it. Then reusing it would be a simple mater of configuration[2], not development. This is the right thing to do™. This post is about how to identify the right thing and what to do about it.

Pragmatism vs Perfectionism

pragmatism
An approach that evaluates theories or beliefs in terms of the success of their practical application.

Pragmatism is about associating choices to the right outcomes and making our decisions within the right context. If we are in a chaotic environment, we are probably forced to react to the events around us. Or if there is undue time pressure on us. Or if there is too much information asymmetry and ambiguity about our project and our organization. When we are in reaction mode, our ability to make pragmatic decisions are crippled. At the risk of offending some of you, I will say that you would find yourself in this sort of situation because you have been intellectually lazy. Pragmatism requires analysis and thinking.

perfectionism
The demand for the highest standard of excellence.

Just like how pragmatism is used as an argument for you to sacrifice yourself for others’ success, perfectionism as a label is used to guilt and shame people for being professional. If somebody is calling you a perfectionist, you probably are and you probably are not. By the definition above, you probably have high standards and you probably are a perfectionist in that sense. But if you ask for your accuser’s definition it will most likely be something along the lines that you are not compromising in a way that will enable them to attain their goals. You are not a perfectionist in this sense because most likely the compromise will put you at a disadvantage. If the compromise would achieve a common, greater goal the accusation would be one of uncooperativeness, not perfectionism. If it was a win-win situation accusation would be stupidity.

Beware of False Velocity

After this philosophical detour let us get back to the subject of programming. Pragmatism in the context of programming is all about the success of the project. That it does what it is supposed to do, it only does what it is supposed to do and it is delivered as agreed before. In that order. First two points are no-brainers. All complexity lies in the third requirement.

Fast, cheap & good; you can pick two. No, you cannot pick all three at once. What is possible is; fast but not quite fast and cheap but not quite cheap and good but not quite good. You also cannot pick fast & cheap first and then pick good & cheap. You picked twice, you have paid cheap two times. In the end it is neither fast, nor cheap. And I doubt it is even good.

Velocity is a subjective/qualitative metric used for agile planning. Used right velocity can help the team deliver a predictable amount of value at each iteration. When velocity is used as a vanity metric[3] incentives are aligned to just maximize a number. This is akin to just picking fast. These teams will accumulate so much technical debt to sustain their fake velocity, eventually they will not be able to delivery much, if anything.

You cannot pick fast and cheap and good. I know a lot of people who will challenge this. It is not always wise to argue about this as an abstract principle. While we are under the impression we are having a philosophical discussion, can we have have our cake and eat it too, these people will start forming ill-informed opinions about us. Most people are not capable of discussing things at an abstract, theoretical level. They operate on an emotional level, occasionally getting ascending to rationality for short periods. This does not mean we have to compromise our thinking. If there is a possibility of doing well on all three metrics, it starts by acknowledging that they are goals that are at odds.

Finding the Balance

First order thinking is only taking immediate consequences of a decision into account. On strategic scale this is laziness and a sure way to achieve mediocrity. However on tactical scale this kind of thinking might be optimal sometimes. “All the tests are passing, what is next?” Also known as the flow. We are being pragmatic when we find the right frame to assess our decisions.

If you have seen my CV you would have noticed it is quite plain, almost lame. First order consequence of this is that it is unlikely to get picked in a keyword search over a database. It would also be quite weak against all those other CV’s with phrases like mentoring and enormous experience. I am willing to pay the price of not getting too many job offers. In exchange, this is the second order consequence, I get to interact with only those companies who have realized focusing on CV’s would produce a lot of false negatives. And that is the kind of company I would like to work for.

When avoiding mistakes become the overriding goal in what we do, tautologically it means we are not pursuing our original goal. When the compiler throws yet another annoying exception in our face, first thing we should do is to try and understand what it is all about. That is how we get better. When we get better compiler will also behave. Of course, I am joking; compilers do not have agency, they are tools. Those exceptions we are seeing is a consequence of the code we have written. We should take it as feedback and the first step is to understand. Understand before starting to type.

We are a professionals. Unless and until we are explicitly asked to cut corners, we should not cut corners. Comprimising does not necessarily mean self-sacrifice. We can put a comment in the code, explain precisely what we are doing, why we are doing it and how it should have been done. The date, relevant parties and any external links. Noone can blame us for meticulously documenting technical debt. And it is more likely to get fixed in the future if it is made more visible.

We have focused on good up to this point. As professionals we need to be able to deliver good and also we need to be able to do it fast. Fast here does not necessarily mean pressing more keys. It means producing production quality code in less time. When someone underperforms in this area it is usually because of two reasons; they are not one of those few people who can do all their thinking inside their minds and they have not discovered the method that will help unstuck their thinking. Most of us need to use our bodies in this way or another for our thoughts to flow. Some of us do their best thinking when they are talking (rubber duck programming), some of us prefer diagramming. There is another method, I think to be useful for everyone, is to practise explarotary coding/ [4]. We can create prototypes and throw them away. If we are using git we can work on a local branch[5], start with something okay and iterate towards the end goal.

I want to end with an Ayn Rand quote:

Contradictions do not exist. Whenever you think you are facing a contradiction, check your premises. You will find that one of them is wrong.
[1]See also formal methods.
[2]This can be thought as project configuration like adding a dependency or object graph configuration like passing a reusable instance of some interface into a constructor.
[3]See also Why vanity metrics are dangerous.
[4]I have found the 2nd advice in this video to be quite useful, for sketching as well as for coding. You can skip to 9:39.
[5]You should become familiar with what this command does; $ git rebase -i HEAD~4

If you have any questions, suggestions or corrections feel free to drop me a line.