I think that most developers these days often have to play the role of architect. They are not only responsible for coding, but also responsible for the overall design of the application. Hence, we find ourselves putting on several hats during various phases and iterations of a project.
This is okay by me given that more and more companies are embracing agile software development. I find that I am focusing more on those tasks that lead to better applications in less time as opposed to paperwork and communication that only appease management and have little real-world value.
As “architects”, we need to understand characteristics of good application design. We need to follow proven principles and best practices that are language and development enviroment agnostic. If nothing else, we need to sound like we know what the hell we are talking about ;)
In several posts I have mentioned the application design smells of rotting software, which are unfavorable characteristics of an application (i.e. things you don't want):
- Rigidity - System is hard to change.
- Fragility - Changes causes system to break easily and require other changes.
- Immobility - Difficult to entangle components that can be reused in other systems.
- Viscosity - Doing things right is harder than doing things wrong.
- Needless Complexity - System contains infrastructure that has no direct benefit.
- Needless Repetition - Repeated structures that should have a single abstraction.
- Opacity - Code is hard to understand.
I have also mentioned my ever favorite GRASP Patterns from Applying UML and Design Patterns - An Introduction to Object-Oriented Analysis and Design and Iterative Development by Craig Larman, which are useful as a learning aid for OO design with responsibilities:
- Information Expert - A general principal of object design and responsibility assignment?
- Creator - Who creates?
- Controller - What first object beyond the UI layer receives and coordinates a system operation?
- Low Coupling - How to reduce the impact of change?
- High Cohesion - How to keep objects focused, understandable, and manageable?
- Polymorphism - Who is responsible when behavior varies by type?
- Pure Fabrication - Who is responsible when you are desperate, and do not want to violate high cohesion and low coupling?
- Indirection - How to assign responsibilities to avoid direct coupling?
- Protected Variations - How to assign responsibilities so that the variations or instability in the elements do not have an undesirable impact on other elements?
I also described a chapter of Code Complete 2 that mentioned several desirable characteristics of a design:
- Minimal complexity - Avoid making “clever“ designs. Clever designs are usually hard to understand. Keep it simple.
- Ease of maintenance
- Loose coupling - Loose coupling means designing so that you hold connections among different parts of a program to a minimum.
- Extensability - You should be able to change a piece of the system without causing a huge impact to other pieces of the system.
- Reusability
- High fan-in - Refers to having a high number of classes that use a given class. High fan-in implies that a system has been designed to make good use of utilitity classes at the lower levels in the system.
- Low-to-medium fan-out - A given class should use a low-to-medium number of other classes. High fan-out (more than about seven) indicates a class uses a large number of other classes and may be overly complex.
- Portability
- Leanness
- Stratification - Try to keep the levels of decomposition stratified so you can view the system at any single level without dipping into other levels.
- Standard techniques - Give the whole system a familiar feeling by using standardized, common approaches.
And last, I talked about several Object-Oriented Principles from my Agile Software Development Principles, Patterns, and Practices Book Review:
- Single-Responsibility Principle : A class should have only one reason to change.
- Open-Closed Principle : Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
- The Liskov Substitution Principle : What is wanted is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2, then S is a subtype of T.
- Dependency-Inversion Principle : A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions.
- Interface-Segregation Principle : Clients should not be forced to depend on methods that they do not use.
As I look back at all of this conceptual information, I see a consitency. Actually, I see a redundancy where all of these books are talking about the same principles of good application design in their own way. I find this great and really enjoy the reinforcement, because it helps me when I need to put on that “architect” hat. I can speak and think with confidence with respect to all the authors who have much more experience on these subjects than myself.
Keep this list handy as I hope it will be useful when you need to think about the design and architecture of your next application.
Resources
David Hayden ( Sarasota Web Design / Blog )
Drinking: Dragon Well Lung Ching Green Tea