For any given amount of work, there is at least one order of doing that work which is the most efficient.
If there are dependencies with the sub-tasks, then there is at least one order of doing the work that is least efficient.
For any two tasks, there may be obvious dependencies, but there may be non-obvious secondary ones as well. If one task requires speed and the other requires strength, even though they do seem to be unrelated, there could be issues like muscle fatigue or tiredness of a person if they are the same one for both tasks.
With most tasks, most of the time, you should assume there are known and unknown dependencies, which means there is very likely, almost always, a most-efficient set of orderings. Assume it is rare for this not to be the case.
For any given dependency, its effect is to reweight the effort needed for both tasks. Doing the one task first means the second one will now take a little longer. We refer to this as friction on the second task.
Like dependencies, there is obvious friction and then non-obvious friction. If you do some task and many of the lower sub-tasks take a little longer, but you don’t know why, there is some non-obvious friction happening, which indicates that there are some non-obvious dependencies involved.
All this applies heavily to software development. When building a big system, there are ways through all of the tasks that are more efficient than others. From experience, the difference is a multiplier. You could spend 3x more effort building it one way than some other way, for example. In practice, I have seen much higher multipliers, like 10x or even crazy ones like 100x.
It’s sometimes not obvious, as large projects span long periods and have many releases in between. You’d have to step back and observe the whole lifecycle of any given project to get a real sense of the damage that some more subtle types of friction have caused.
But the roots of the friction are often the same. Someone is trying to do one task that is dependent on another one before the foundational task is completed. Which means that changes to the lower task as it goes are causing extra work for the higher one.
We can skip over architectural discussions about height and just simply assess whether one piece of code or data depends on another piece of code or data. That is a dependency which, when handled out of order, creates friction.
Overall, it always means that you should build things from the bottom up. That would always be the most efficient way of getting through the tasks. Practically, that is not always possible, at least overall, but it is often possible within thin verticals in the system. If you add a new feature, it would be most efficient to address the modelling and persistence of the data first, then gradually wire it in from there until you get to the user interface. What might have driven the need for such a feature was the user experience or their domain problems, and that analysis is needed before the coding starts, which is top/down. But then after that, you flip the order for the implementation to bottom-up, and that would be the fastest that you can make it happen.
That the order is flipped depending on the stage is counterintuitive, which is why it is so controversial. But if you work it back from the first principles above, you can see why this happens.
In development, order is important. If you do build too slowly, that spins off politics, which often starts to further degrade the order, so getting control of this is vital to getting the work out as efficiently and smoothly as possible. Most people will suggest inefficient orders, based on their own understanding, so it is better to not let it be in the hands of most people.
No comments:
Post a Comment
Thanks for the Feedback!