Each software development project starts with a concept or proposal and a favorable business case, then ends with product retirement. There are many steps in-between: requirements, project management, architecture definition, design, implementation, build management, change management, document management, configuration management, problem/issue tracking, test case management, test run management, and customer tracking.
The successful software organization can manage complexity, in both the product and the process.
Product: Focus on Strong but Simple Architecture
Simplicity and good architecture are key to managing complexity and producing high quality product. Good architecture is a result of understanding the problem, the tools you have to work with, and good design. Also, there's no substitute for experience. One important component of good architecture is how you use your tools.
The C language, for example, has numerous capabilities. Some are good, some are bad. At Neuma, we tend to be fairly strict about how the language is to be used. Not just no "go to" statements, but a whole set of dozens of guidelines that help our developers produce good product. Some examples are:
- Use loops with conditions at the beginning of the loop, not at the end. It's easier to read and understand.
- Always use 0-index origin for arrays, loops, etc., and (start, count) rather than (start, end) pairs.
- Don't do arithmetic on pointers and avoid using pointers altogether.
- Name local variables/fields with simple names. Use full names for global identifiers.
- Create single entry, single exit procedures/functions (huge readability paybacks)
- Use common names for standard or recurring parameters in functions
The list goes on. You can use a safe subset of the C language, but without losing functional capability. The idea is to make all code simple and consistent. Simple formatting rules do not accomplish this goal. The overall set of guidelines help to make code maintainable and readable, while instilling an attitude of good design.
Using a smaller but adequate subset of the language also provides simplicity. If loops are always going from 0 to N-1, you don't have to spend a lot of time figuring out boundary conditions, because they all follow the same pattern while speeding things up and cutting down on errors. This is a very specific example, but if you have even a dozen clear guidelines explained, it's amazing how much simpler you can make your development environment.
Other ways to simplify your product include:
- Simplify the technology you use. Don't allow everyone to pick their own scripting or programming language.
- Perform code reviews so that you have fewer problems flowing through your product life cycle. Also review against design guidelines.
- Use design rules that help your configuration management rather than hinder it.
- Instead of variant builds, support run-time configuration of a more generic build.