Thoughts on software design
10 Jan 2011
As we are in the middle of crunch on our big project at work I thought I'd write down what I (currently) believe is the correct way of designing and implementing software. My views are heavily influenced by Emacs and dynamic languages, although both of the major projects I've worked on so far have been implemented using a statically typed language (C++). As I'm mostly interested in writing software that serves a purpose, all of the professional projects I've worked on so far have been consumer-oriented products.
This factor alone will make or break a project. If a majority of the team hasn't worked on a project together things get dangerous. My advice to management in this case would be to let the team free-roam for a month or so and let them work on writing tools and libraries needed for the project. It might look like a folish waste of time but for the team this period is critical. First of all, senior people get the chance to see new hires in action and secondly they can easily spot people who are not a fit for the team for this specific project.
Why is this important? I believe that the state of your software is determinted by the least competent developer on the team. This is the key if you want to run a successful software development project and in general if you want make money in this business. Good programmers are well worth paying for as the value you can extract from their work far exceeds what you have to spend to make them stay happy.
The team should consist of people with one or more of the following traits:
- High-energy, creative
- Detail-oriented, guru
- Customer and usability-oriented
If you don't have any team members with the high-energy trait, suspend the project and wait until you get the right people instead of wasting time and money. The team should not consist of more than 3 or 4 people, larger projects should be done with multiple teams. Well motivated smart people will do the right thing and manage themselves. Project managers should manage projects, not people.
- If you don't have a clear picture of the user, don't bother unless you're doing R&D work.
- Unit-test or die.
- Analyze and design top-down. Buzzwords like Agile and Scrum don't remove the need for thinking and knowing what you're doing.
- Implement bottom-up, short delieverable iterations.
- Design composable software and libraries, because you'll end up doing X when Y isn't Z if Q is P.
- Make the software configurable at runtime.
- Make the internal data structures of the software inspectable at runtime.
- Make the system composable (pluggable) at runtime.
- Always start by attacking high-risk problems with prototypes. Plan to throw the first version away.
- Experiment, observe, adapt...
Lessons learned in 2010: (2), (4), (9)