Software architecture is the foundation of Enterprise Software. The underlying architecture should be well designed and thought through. Regardless of the technology selected for a Enterprise, certain underlying principles guide the initial development and evolution of the software. In this article I will be presenting the principles I have found most useful.
Collaboration applies across all major activities, from organizing and executing, to deployment and maintenance/operations. Collaborate with folks both inside and outside the known systems, and collaborate with folks that know the customer/business side.
Creating an environment where innovation can thrive is an important aspect of collaboration. Brainstorming sessions can be useful when conducted in a open, non-judgmental atmosphere. It is important to separate the communication of ideas from deep analysis of each idea. I recommend having an initial session to capture all ideas, and a separate session for diving deeply into each idea. During the capture session, all ideas are welcome, and are not immediately judged. Often this will lead to a chain of related ideas that ultimately lead to solution options. Always be open to improvements in the software architecture. In my experience, incorporating good ideas into the software architecture leads to a stronger architectural foundation.
Like Collaboration, Continual Improvement applies across all major activities. Utilize Effective Retrospectives at end of each sprint or activity to continually improve team performance.
Organizing is often a very challenging part of constructing software. Poorly organized initiatives often leads to poor architectural foundations. It can be quite complex to organize a software construction initiative. At a high level:
- Research domains inside and outside system
- Select appropariate tools/frameworks
- Plan execution
- Attract stakeholders and collaboration
- Include retrospectives in planning and execution for a continual improvement feedback loop
- Proactively identify unknowns and challenges and develop options to mitigate
Form a vision of where the architecture is evolving. Use the organizing phase as a tool for gathering the information needed to develop the appropriate vision for the organization. The vision should be continually refined. Start at a high level and work your way down, then work down and back up to verify the integrity of the design.
When breaking down the initiative into tasks, insure that each task takes no longer than 2 days max, if it does break the task down into smaller sub/dependent tasks. Organize efforts into 1-2 week sprints. Conduct a demo and retrospective at the end of each sprint.
Take an iterative approach to building out slices of functionality. Monitor progress and adherence to architectural principles. Utilize code reviews to train development team on best practices and preferred software patterns. My article Beyond Code outlines many useful activities related to sustained software development.
If you are working with a outdated legacy system, map a realistic path of transformation. A useful framework for working with legacy systems is based on an article written by John Boyd, titled “Destruction and Creation“. The basic concept is to break a system down into smaller pieces (Destruction), look for synthesis and integration, build up a new system outside existing domain concepts (Creation), test new creation by validating you can trace the concept back to it’s original domain. Rinse and repeat until successful validation.
Many folks use terms for software architecture goals, however to achieve architecture goals it is important to clearly understand what each term means at software level, and be able to communicate this to different levels of the organization from developers to CEO. And of course translate the goals into a solid architectural foundation of code.
Emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.
The capability of software to handle a growing amount of work, or its potential to be enlarged in order to accommodate that growth.
Systems design principle where the implementation takes future growth into consideration. It is a systemic measure of the ability to extend a system and the level of effort required to implement the extension. Extensions can be through the addition of new functionality or through modification of existing functionality. The central theme is to provide for change – typically enhancements – while minimizing impact to existing system functions.
Maintainability is the ease with which a product can be maintained in order to:
- Isolate and correct defects or their cause
- Repair or replace faulty or worn-out components without having to replace still working parts
- Prevent unexpected breakdowns
- Maximize a product’s useful life
- Maximize efficiency, reliability, and safety,
meet new requirements
- Make future maintenance easier, or
cope with a changed environment
Layered Software Approach
Layered Software Approach is a very useful framework for organizing, categorizing (layer), and selecting appropriate software patterns for a modular, scalable, extensible, and maintainable architecture. Derek C. Ashmore’s does a excellent job detailing this approach in his book The Java EE Architect’s Handbook. His blog, The Java EE Architect’s Blog, is also an excellent resource. I have experimented with many of the concepts discussed in his writings, and I have found them to be very effective and useful.
Front end systems can change at a very rapid rate. Decoupling UX layer from the rest of the system enables this layer to be extendable. A REST API helps achieve this. If you decide to utilize the REST architecture style it is import to understand and honor the architecture properties and constraints this style describes.
The principles discussed thus far build a solid foundation for constructing software systems. Automated testing is critical for long term continual evolution of the architecture and underlying modules. It is important not to overlook this from the very beginning of a new system. For legacy systems there are many techniques to explore to introduce automated testing. In either case, it is important not to over look robust automated testing, as this supports ongoing quality, extension and evolution of the system.