At the start of a new development effort, there is considerable uncertainty. There are unknowns in hardware, software, product goals and requirements. How can we get started with all this uncertainty? Isn’t better to wait? If you wait, there really is no end to the waiting, so its better to get started sooner even though there will be some things you decide early that get changed later.
When there is uncertainty in the hardware/software boundary, you can start from the inside by solving the application problem, working your way to where application code meets the hardware. When the application gets closer to the hardware, create an interface that provides exactly the services the application needs from the hardware. This is part of your Hardware Abstraction Layer.
A nice side effect of letting the application drives the interface, it is less likely that hardware implementation details will pollute the application’s core.
If you are working with another team, with an interface between you, don’t work out the interface details before work begins. Agree in principle how the interface will work, but not in detail. Go as far as creating initial names, but don’t settle on function signatures yet. If it is a rather wide interface, develop a subset of the interface, and integrate early. Use test doubles to get the feel of the interface, assuring the interface is convenient for the client. Later, when the approach is confirmed, the interface can be broadened to cover more of the needed functionality.
As requirements become more clear, the design has to evolve. That’s no failure, that’s good news that we’ve learned more. Evolving requirements led to changing design. The problem with much of the legacy code out there today, is that as requirements evolved, designs we not improved to more naturally accept the changes.
One reaction to imperfect knowledge is analysis paralysis: we can’t start because we don’t know everything yet. It’s by the doing that we learn. If we keep things modular, then when outside factors change, the system can evolve with less pain. If code is not so modular, the surgery needed to improve design is too major and probably postponed. There is nothing new about this advice: keep your code modular and loosely coupled.