Thursday, June 22, 2023

Control

Control issues play out in multiple ways in large software projects.

The most obvious is that the nontechnical stakeholders sometimes seek to control the development focus, but as I’ve often said that can lead to chaos.

The other issue is that for everything you put into production if you don't directly control it then when it runs into a problem your options are extremely limited.

For example, if you rely on some small open-source library and it has a bug with a fairly large impact, you will probably not be able to convince the authors to release a patch right away. If you fork, then your version will drift away from theirs. So, often it is better to find another similar library, or just write a replacement. Finding another library might be faster, but you haven’t actually fixed the problem, you’ve just pushed it away again.

It is never a wise choice to assume that there won’t be bugs. Code is still written by humans, bugs will always happen and any testing to catch ‘all’ of them is prohibitively expensive. If you write your own code you also have to assume there will be bugs, but you now have the means now to correct the problem and get it back into production.

That is, with the library you can use it, but you have no real control over it. If it is your code, you have control; we’ll at least if you have someone around that understands the code.

Now, while that works for small or core functionality, it does not work for large technology issues. For instance, you always need to persist some data. But writing reliable persistence is quite tricky, it involves a lot of deep understanding of both technology and theory. So, where you might not want to be dependent on little libraries, you would be insane to try and write your own database. It’s too complicated, you’re too likely to get it wrong, and it takes a huge amount of time for that code to mature. Unless controlling persistence is a ‘core’ part of what you are doing — e.g. you’re a software company and need your own database product — it is not reasonable to try.

The general rule for coding then is that you should always write your own stuff, but only if you can. And it’s that second part which is really tricky. If you have to build a large system that shows tangible results in a six month window, the amount of time you have to write code is incredibly limited. You need to pick carefully. And you need to accept that you may have to lean on less desirable dependencies for the first phase of the work. That is, you include a library now, but with the specific intention to replace it later, when time becomes available.

If you can get into that mindset, that each and every dependency you have could be a candidate for replacement someday, it will help. As time allows, you will get rid of the low-hanging fruit — the trivial libraries — and use that as an excuse to also properly refactor the code around them. Then as the work grows it also evolves and matures.

That type of effort then isn’t just about writing your own code but rather it is really about increasing the amount of control you have over what you are releasing. If you want the project to be stable, you have to control enough of what goes out that you can make it stable.

The corollary is you always want to be increasing control; over everything, if possible. If you don’t, the project will become increasingly out of control until it shakes apart. You want to be successful, you want to deliver good solutions that really help your users. Being in control isn’t fun, but it is what allows you to deliver.

No comments:

Post a Comment

Thanks for the Feedback!