A none-too-profound musing on requirements mutability
It’s one of the best-known truisms of software development: No matter how carefully you gather your requirements, they’ll likely be wrong and always, always be incomplete. No battle plan survives contact with the enemy; no development plan survives contact with the users. The moment your client sees what you are making, he will realise that it’s not quite what he wants and your requirements will changed. This is well-known; it’s why agile methodologies are praised and inflexible methodologies are disparaged.
What I realised biking home from work today is that this is not just true in practice, but in fact necessarily true.
When you design a software system, its purpose is to help users solve a problem. Your model, then, must take into account
- The problem domain itself.
- The user’s existing tools, which determine input and output for your system, provide opportunities to make use of, and present obstacles and inefficiencies to resolve.
The purpose of your software system is, of course, to address the shortcomings of the user’s tools in solving the problem. But the moment the user begins to use your software system, it becomes part of the toolchain and thereby part of the system you are analysing and building a model of. As soon as it springs into existence, its opportunities, inefficiencies, powers, and foibles become part of the things you need to leverage and to resolve. Your model now needs to take into account
- The problem domain itself.
- The user’s existing tools.
- The model itself.
This obviously means that it is impossible to fully model the system in the absence of the software system that is to integrate with it, because the software system you are designing is part of the system. It’s not merely practically, but logically impossible to fully specify the system without considering your software…and your software cannot be designed and presented for consideration without some set of requirements. That set of requirements, then, is by logical necessity incomplete.
Much like a mechanical problem moves from mathematical certainty to the vagaries of perturbative methods the moment you add a third body, so software design necessarily relies on iterative and perturbative methods the moment your own system enters the picture, as it must, if it is non-trivial. (Maybe biology is a better metaphor: The solution to the chicken-and-egg problem is to become a chicken by degrees, over generations.) Of course you could in principle carry out this iterative design on paper (literally or otherwise), but to my mind this shifts the picture from one in which you might ideally design everything in one fell swoop but are practically constrained to doing iteratively (one way or another), to one where it is only possible to do it iteratively (again, one way or another).
Of course, the practical outcome remains absolutely unchanged, so my little thoughts have no practical consequences. But it amuses me, sometimes, to think of stuff like this.
no subject