As an Agile Coach, I typically find two shifts in perspective helpful for new agile architects: first, the possibility of delivering slices of functionality (typically prioritized by risk or value) and second, the possibility of delivering slices of architecture required to support incremental delivery.
I experienced this perspective change personally in what now feels like a previous life as an architect who was expected to construct solutions in addition to architecting them. As a result, I thought it might be most appropriate to discuss how an agile coach might approach the second shift in the spirit of the art of the possible while at the same time trying to keep it simple.
My goal is to incrementally and iteratively formulate a framework to help coach a new agile architect through the required transition of thought in designing architectures that enable incremental delivery of value. While it does not require BUFD, it does require thoughtful consideration of architectural requirements such as quality attributes, NFRs, and expected points of volatility and extensibility. As will eventually become evident, the details contain gotchas that are easily avoided with due consideration.
Two Potential Perspectives
The way my mind works, there are two obvious representations of the context.
In the first, I view an architecture using the following entities:
- Things – which commonly talk to other things using…
- Messages – which contain or, in some way, transmit…
- Information – for context, configuration or other processing
A second, and maybe more useful, perspective is to view the architecture in more traditional layers:
- Domain – the public face, internal or external, of architectural value delivery, typically in the form of services
- Capability – the functional or component building blocks
- Interaction – the integration of the capabilities that reside both in and on the architecture
While both perspectives resonate with me, for this discussion I will use the latter. In future posts I will delve in more depth, which will more naturally align with the former.
What are the challenges?
So what are the challenges I commonly face in this particular area as an agile coach? The following are common questions that arise:
- How to support domain service stability during incremental refinement?
- How to incrementally increase the complexity of integration points while maintaining robustness and managing volatility?
- How to support component stability while incrementally increasing capabilities?
In addition, each case typically comes with requirements to ensure extensibility and backward-compatibility, as well as the realization of quality attributes such as scalability and performance.
Recognize & Address Each Type of Challenge
As a result, any systematic approach that a new agile architect will find useful must address at least each of these types of challenges.
So I’d like to propose one way to look at this challenge and help your customers complete this mental transition. A particular benefit of this approach is that all the referenced content already exists, is in use, and has extensive information available in both books and the public domain. See the References and Further Reading section at the end.
So let’s dig into each challenge with a bit more detail.
How to support domain service stability?
I suggest approaching this challenge with a discussion of Service Oriented Architecture patterns. The primary benefit of these patterns is to manage the dynamic and volatile service contexts and contracts encountered as the architecture is extended in increments. More detailed information for each of these can be found at soapatterns.org (see references at the end).
Some useful patterns to leverage in this way include:
- Service Façade supports dynamic service contracts by decoupling the core domain capability from the public contract. This will allow either the core domain capability or the public contract to evolve independently.
- Agnostic Capability helps derive new service contexts by making available well-defined yet common domain capabilities as granular services.
- Protocol Bridging supports protocol volatility by ensuring differences in communication protocols – either type of variant – are handled adequately based on expected protocol volatility, planned or emergent.
- Compatible Change / Concurrent Contracts generally support ongoing modifications by introducing new capabilities without impacting existing ones, and by creating multiple contracts of the same domain capability for specific consumer types.
How to support incrementally built integration?
For integration that will be changing through incremental architecture development, introduce the Enterprise Integration Patterns body of work (Hohpe). The primary benefit of these patterns is to stabilize points of integration from Day 1 as they increase in capability and complexity.
Some common refinement patterns to identify and plan for include the following, which I have personally experienced on several large-scale projects:
- Basic Integration Refinement occurs as a simple integration becomes more complex and capable. An example evolution of integration may include transitions from hard-coding, to file sharing to shared memory to RPC, and finally to messaging. Using other protective patterns, this refinement can evolve with minimal impact to the solution and customers.
- Message Channel Refinement involves the paths of integration becoming more powerful and robust. For example, message channels may transform from Point-to-Point to Message Bus to the use of Message Bridging. This would use the EIPs called Point-to-Point Channel, Message Bus, and Messaging Bridge. (Hohpe).
- Message Routing Refinement occurs as the routing mechanisms used to put messages on channels move from relatively dumb to elegant and smart. Some examples I have used to incrementally build out a robust routing infrastructure include content-based routing, message filtering, Recipients List, Splitter & Aggregator, Composed Message Processor and Message Broker. While the core integration may have also required change, it was minimal compared to the message routing capabilities protected by architectural design patterns.
How to design capabilities robust enough for incremental development?
This is probably where most technicians are the most familiar, yet it is worth discussing within your coaching conversation as this not only ties the other pieces together but also provides more tools which can be applied at all levels. Here we consider GoF Patterns at the capability level.
Some common design patterns that bring great value to incremental delivery include the following from Design Patterns:
- Factory Method to abstract and extend creation functions. Through a creation interface and inheritance, the implementation determines which class to instantiate. In addition, more simple factory patterns that do not rely on inheritance may also be applicable here.
- Adapter, Bridge, Decorator, Façade, and Proxy to protect and stabilize structure. Each of these leverages abstraction to stabilize areas where the structure is or may end up being volatile. In most cases, if the extent of true volatility is less than expected, the cost expended for protection will have been minimal.
- Strategy, Command, Mediator, and Template Method for incremental extension of behaviors. Again, through the power of abstraction, component capabilities and behaviors can be extended as needed with minimal impact to the core solution.
My goal is to create a systematic approach to engage and coach new agile architects in the art of the possible when it comes to architectural slicing. Using generally available and proven patterns at each critical layer of an architecture: the domain, the capability, and the integration, architectures can be designed, communicated, and built in vertical slices which meet quality attributes and stability using an incremental delivery approach. As a coach, communicating this possibility and providing the tools to new agile architects is critical to empower early and often creation and delivery of value.