My software design principles
Tuesday, October 27, 2009 at 1:24PM I haven't done much programming lately and was more busy with the design of a large application. In the realm of enterprise software development the process is often much less formal than everybody pretends it to be, so it is very important to stick to some general principles in order to come up with a good, long living application. Here are my principles:
Keep it simple. Simpler programs mean less code to be written, tested and maintain. I believe the elegance of an application lies in its simplicity. That's not as obvious as it sounds as many designs pride themselves with being as flexible and have as many functions as possible, which usually leads to complex code.
Good design is if an application can be used for unknown requirements it was never designed for. I read this somewhere, but is sums it pretty much up. In two ways. First, a design should be flexible enough to be easily adapted to future requirements. Second, those requirements are unknown. Don't try to analyze them upfront, because at some point you have to deliver something of value. Making a design hold for future unknown requirements, requires a lot of domain experience, educated guesses and luck.
Optimize for the most common, not the most complex use case. Complexity usually balloons during requirement gathering phase. One main reason is that the users of an application often try to avoid making hard decisions that may prove wrong in the future. So you get often something like "I've never seen this use case, but it doesn't mean that it can never happen". Coding for all these rare use cases often lead to complexities like many-to-many relationships, name/value pairs or unlimited hierarchies and thousands of lines of code to handle them. If this code is rarely or never needed, it's difficult to be tested and maintained and it becomes stale over time, means that after a few iterations nobody is really sure if it is still working. This doesn't necessarily mean that rare use cases cannot be supported: often there's a work around that still fulfills requirements, maybe at the cost of usability - which doesn't really matter if it's happening only rarely.
Don't go overboard with abstraction. Abstraction is an important tool to achieve flexibility, reuse and better testability and maintainability. But there is a too much, which is often observed in Java application. Compulsively abstract away every concrete implementation has a negative effect on code readability. There are common sense abstractions, like UI vs. business logic, logical vs. physical data model and data manipulation vs. business methods. But often it's better to choose an implementation and stick with it, rather than squeezing in another layer of abstraction.
Configuration does not always trump code. There's a general aversion against "hard-coding" configuration parameters in code. But it doesn't necessarily make it better to put them in a, for example, XML file. As long as the configuration is encapsulated from code, I don't mind if it's Java or XML or a properties file. Java code is especially useful if the configuration doesn't only contains strings but also logic, like validation rules. Pure text configurations make a lot of sense only if they are maintained by a non-programmer or they can be changed at runtime.
If it looks like some of those principles conflict - yes, they do. That's what makes good design a challenge. There's a middle ground to be found. Perfection is impossible and only leads to missed deadlines.

Reader Comments