First make the change easy, then make the easy change

Background

Your systems should be built in such a way so that it is easy to make changes. While this seems obvious it may not be so straightforward. The more flexible you want your system to be the less assumptions you should make. But this comes at a cost. So the trick is in balancing the configurability of the system and effort it takes to build the systems.

It is for this reason that platforms that make least number of assumptions can be used to build any kind of systems. But it also means that those platforms will be barebones and you will end up doing a lot of work. Whereas the platforms that are opinionated might have much less flexibility but they reduce the overall effort and time it takes to take something to the market.

A good architect is one who can decide what the right mix should be for a given use-case based on his experience. It is sometimes better to start somewhere in between and then move left or right based on how the project grows. If you are very sure what the scope of the project and domain is you might as well go with opinionated or turn key Tools and get it done with. If you want the system to be completely flexible you might be better off not using frameworks(at-least those that make assumptions).

Refactoring

Gone are the days when you had hard rules about how to code. Today most of the advice end up with some version of "Do what works for you". And that is the challenge as most of the advice also becomes subjective and for may people who are starting it might even sound vague.

For example many architects today agree that pre mature optimization and pre mature refactoring is bad. From pure programming perspective this might sound like bad advice. But for somebody who is realistic, considering the costs and doing ROI analysis this is great advice.

So my only hard advice these days is "As long as you are confident that you can make changes easily, keep doing whatever is working and keep making systems better as and when you can afford".

In my opinion "making the change easy" is the primary goal of Refactoring. When your mental model of the code base is better you can refactor the code with more confidence. Refactoring the code is find the right balance between generic and the specific scale. Starting with the center and making it more generic as the usage increases or the code duplicity increases it a good strategy.

Tell me what does this mean

Example 1

Let us say you find similar or same code in two places. Now you are asked to make some change to the logic. Instead of making the change and then figuring out if it works, don't do the change to begin with. First refactor. Move the code to a function. Use the function in both the places. See if the current functionality is working fine. Now you have refactored and you are confident that everything is working fine. Now go change the logic in the function and it will get affected in all the places.

May be this is a very dumb example. But it gives you an idea of what the concept is. If you find a better example let me know.

Example 2

Another example could be, let us say that you are using a particular implementation of Array Search in your code. Now the requirement is to change that. Instead of changing it directly, see how you can make the process of changing the algorithm easier. You had this requirement once, it might as well come later. So now is a good time to make it generic or make it easier to change the search algorithm. What do you do? Code to interfaces in program. The specific version of search that can be used can be decided using a configuration. So that they next time you want to change the search algorithm, you don't need to change code but you can change it directly from the configuration.

By programming to interfaces and moving the search algorithm to be used to the configuration you made the change easy. Now you can do the easy change by changing the configuration. Let us say you want to compare two algorithms to see which one performs better. Even testing that out is easier now. You just need to write a test case which creates two version does the same thing and then we can compare the results. Easy Peasy.

Outside programming

While this makes a lot of sense in programming, I think that impact of this is much more when applied outside programming. These days I see where all I can apply this. I apply this to goal setting as well. An example. My goal is not to write more, but my goal is to make writing and publishing easy. As an outcome of these the frequency of my writing naturally increases. What you are reading is an example of that. I didn't write two articles that I promised but instead of pushing myself to write I finished my set up of My Mind Map, theMost important project I am working on. This has helped me write many more pieces, which I am sharing with my Trust Bank and getting their feedback. In due course I will complete these two articles also but may be by then they would have become irrelevant too :P

Applying this logic recursively I have come to the observation that bettering the workflows, getting clarity and building systems in which making change is easy can have long term compounding effects. So I am trying to concentrate on these more. But while I do this I am also making sure that I have some short term wins when doing these and also I generate some artifacts frequently so that irrespective of how the experiment turns out we will have something useful come out of it.

Also each time there is a requirement for changing the system or the workflow, I look at how I can make this whole process of making the change easy and what can we do for it before implementing the change.

Hope this helps. If you find some interesting articles around this topic, better examples or better implementation of this advice tweet at me. Would love to discuss this over coffee.

    All notes