A quick one today, but an important one.
When working at startups and in small development teams, something I’ve seen a lot is the dangerous idea that it is possible to write any kind of non-trivial software without having given it some serious thought first.
I suspect this often comes from the classic abuse of the term “agile” as an excuse to drop some of the less tangibly essential aspects of software development and “just smash out some code”.
In waterfall-style software development the idea of code being written without much design having taken place is unthinkable. There is clear design phase in the waterfall, and there are artifacts of that required for the next phase to begin. But just because we don’t create UML diagrams in agile doesn’t mean we shouldn’t have upfront design! Yes, coding can start earlier and with less of a complete blueprint, but this does not mean no design at all.
What often happens in small teams is that in lieu of up-front design work on a new project, a developer knocks up some code into a prototype. The prototype is then showcased, extended, showcased and extended again; and slowly but surely what started as throwaway code becomes the basis of production code.
Not only is this usually a disaster in terms of code quality, but it also typically results in the skipping of the design phase of the software development lifecycle. Even if the prototype code is “reworked” into something a bit more formal and tidy, the direction and ideas laid down in the prototype are indellibly printed into the production code, and the rest of the team are now bound by whatever “design” that was embedded in the prototype. A far cry from collective ownership and responsbility.
Design in the context of a small development team should manifest itself at the very least as something along the lines of a meeting that happens on a semi-regular basis in which developers get the opportunity to step back from the code and look at things in a more holistic way. How is this component going to fit in with others? Are we building this in an extensible way? Are we re-inventing the wheel? What design patterns might be of use? Is the fact that the code is already spaghetti symptomatic of poor design? It may seem expensive for a small company to have several or all members of a dev team in these meetings every week or two, but from my experience, it really pays off.
And the pay off is not just in terms of software structure or the use of design patterns. Design meetings are another opportunity to confirm that the dev team grasp what is required of the software to be written. On more than one occasion I’ve attended a design meeting in which it has become apparent that the conceptions that the devs had for a nascent project were totally off the mark in terms of the actual customer requirements. If you have a good agile process in which software is being reviewed by a product owner or proxy customer each sprint, you’ll likely catch these things before they waste too much time and effort; but even better, how about catching these mistakes before a line of code has even been written!?
Having a high-level design allows you to validate it with product owners or proxy customers, and I think that’s a useful guide to how much design is required in agile: Not so much that every interface has been defined and pinned down exactly, but enough such that both product owners and developers feel satisfied that when coding starts they are building roughly the right thing.
A good way to get started with the design of a project is to (as a team) sketch out some kind of software decomposition, for example using simple class diagrams or CRC cards. This can ensure that the team as a whole has the same high-level vision for the code structure, making swapping developers in and out of the codebase much easier later on.
The key mantra to bear in mind here is the “early bird” principle: the earlier in the process of making software that a coherent design is planned, a problem is detected or a good idea is conceived, the better. There is nothing worse than spending time and money on developing something flawed or, worse still, developing the wrong thing completely.