Solution Architecture in a Nutshell
The very term ‘Architecture’ is a borrowed from engineering and is probably the most loaded expression you’d hear in the realm of computer science and software engineering. There are myriad of definitions, and disagreements on what software and solution architecture really is; SEI (Software engineering institute ) and IEEE have built some larger definitions around defining what software architecture is, what however we would keep it simple by stating that software’s architectural design is a way of providing structure of practices which help simplify domain modeling, and help make design decisions in alignment with business problems.
For the purposes of our discussion we take the perspective that Solution Architecture essentially fits in the space between Enterprise Architecture and Application Architecture and primarily concerns itself the set of capabilities or “bounded context” that a particular IT system sets out to solve. From there, it focuses on ensuring that the system appropriately meets both the functional and non-functional requirements established by the customers of the system.
At all levels of architecture, the objective is generally to effectively communicate requirements that ensure maximum productivity. The idea that good architecture improves “productivity” is a helpful thought, but one that requires a degree of dissection. What exactly should productivity mean?
Eliyahu Goldratt’s book “The Goal” suggests that the primary goal of a business is to make money, and therefore everything that moves the needle toward that goal should be seen as productive, and everything else is precisely the opposite. This is an important realization, as it directly leads to the conclusion that time spent optimizing non-constraining parts of a system are wasted and that we must properly instrument in order to deliver true value to the organization. This line of thinking is what has led to Agile and DevOps practices that are now the norm among high-performing IT organizations.
Different Architectural Lenses
A reasonable basis for comparing Application, Solution, and Enterprise architecture is to consider each as being concerned with a broadening scope at a less deep level as you move from Application to Solution to Enterprise contexts.
Within the application context, we are concerned architecturally with ensuring that the application is maintainable and structured in a sane fashion. As an application architect, you are also concerned with ensuring the various layers of the application interoperate cleanly and that other engineers are able to contribute efficiently without interfering with each other.
Stepping just outside the internals of the application, a solution architect establishes how the team will satisfy the requirements imposed by customers of the product and the surrounding organization. This can include specific behaviors or deliverables in addition to less concrete requirements intended to mitigate risk or improve organization performance.
A given organization will have a variety of value streams that each have their own solutions attached. To maximize productivity across those solutions, the practice of enterprise architecture strives to provide guidance to the various teams and ensure reusable patterns and practices are both useful and being followed.
Thinking About Requirements
As a solution architect must map from requirements into plans for satisfying them it is critical that we understand the type and nature of requirements. Additionally, we should consider areas where they may unexpectedly emerge to avoid being surprise later in the implementation.
A clear way to describe functional requirements is to think of them as the things your solution must do. These requirements do not define how you must accomplish a given outcome, simply that the outcome is expected in the face of a given input.
Here are some examples of such requirements:
- Service must provide a method to query for active users
- Uploaded documents must be checked for grammatical and spelling errors
- Inactive accounts should be notified before being deleted
In each case, take care to note that there is no specific boundary or direction indicated by the example requirements. Instead, the requirement simply maps from an input or triggering event onto the expected outcome.
Non-Functional Requirements – Getting the functional right (boundaries)
To rationalize what can be considered a non-functional requirement the picture of a guardrail is a helpful analogy. Functional requirements describe the destination, non-functional requirements establish the guardrails to keep the solution from falling off the cliff, and the solution architect paves the road from starting point to destination. Often the sources of non-functional requirements are outside the direct customers of your solution. For example, regulatory bodies introduce a number of requirements on solutions ranging from data retention policies, encryption types, to notification or consent requirements. Organization risk mitigation bodies will place requirements designed to ensure business continuity and protect intellectual property, and security focused contingents within and organization may require specific log and correlation data be made available for analysis and forensics. Further, a team should place a number of non-functional requirements on themselves, such as defining and measuring their key performance indicators (KPIs) for each functional requirement or requiring strict separation of commands from queries within the solution. We will study various types of solutions for non-functional requirements, but for a good reference we recommend reviewing the 12-factor app framework.
Components of a Solution Architecture
As suggested earlier when comparing Solution and Application architecture, the component of a solution can be thought of as a superset of an application architecture. Beyond the artifacts for demonstrating the relationship between the layers of the application a solution architecture can be expected to contain recommendations for people, processes, and other non-functional aspects.
Fig – Application Architecture View showing the relationship between layers of the application, but lacking detail for the areas external to the application.
Modalities of Software Architecture
Within the industry a variety of patterns and practices have emerged the help guide the software development lifecycle (SDLC) of projects from need to completion. Regardless of which approach an organization ultimately follows, they are generally guidelines and should not be followed dogmatically. Waterfall
The waterfall or “big design up front” approach seeks to clearly outline all requirements, both functional and non-functional, before any construction begins. This can be thought of as conceptually similar to how a skyscraper is first designed, simulated, and reviewed before the foundations are laid. Under a waterfall-based process, customers and architects strive to perfectly and unambiguously describe the desired behaviors, and all of the value is delivered at the end of the process in a single “big-bang.”
Rational Unified Process
The “rational unified process” is another form of software development practice where the focus is on getting the design and requirements established up front. Typically, it is expressed in four key phases: Inception, Elaboration, Construction, and finally Transition. During the inception phase, the developers focus on establishing the scope of the effort based on an already established business case. Next, during the elaboration stage, developers attempt to establish the entire detailed description of the features to be developed. At this point the customer would sign off on the features to be constructed in the following phase. Finally, the completed solution is transitioned to the customer for use.
Extreme Programming / Mobbing is a practice where teams build side-by-side with not only engineers but with the business interests. The goal of this practices is to dramatically increase visibility of the implementation, locate and resolve bugs as early as possible when evidence suggests they are 2-5 orders of magnitude less costly to fix, and to get the customer / business interests actively involved in building their own solution. Extreme programming can be combined with other agile practices such as Scrum or Kanban, but those are not strictly required. Often the most value from XP can be achieved by sprinting to a proof of concept or minimally viable solution while mobbing and capturing “user stories” or tasks that define the larger picture as progress is made.
The Scrum practice seeks to ensure a product is always in a functional state, and that value is captured as early and often as possible. Teams practicing Scrum usually establish a fixed cadence or “sprint” during which a jointly-agreed upon number of tasks are accepted from the “backlog” to be pursued. The team will typically observe a collection of ceremonies each sprint – opening with a planning session, daily “stand-up” meetings designed to avoid individuals becoming blocked from completing their task and concluding with a demo where team members can show the stakeholders what was constructed during that sprint.
Similar to Scrum in that it also tracks work in a series of discrete units of work, Kanban differs in that the focus is on limiting “work in process” or WIP. This focus ensures the team is constantly moving toward completing tasks and is guided by the idea that even a single completed task is better than an unlimited number of partially completed ones. Another differentiating aspect of the Kanban process is the “pull” based nature – work is never pushed onto an engineer’s lap. Instead, when an engineer completes the task they simply look at the backlog and begin working on the next item.
The lean manufacturing revolution taught us that for an organization seeking to engage in construction should aim to reduce lead time and work in process inventory levels. Anyone who has been involved in planning a software-based solution can attest to the difficulty in predicting which precise approach and timeline will be required to satisfy a particular set of requirements. When combined, these two thoughts drive toward “iterative” thinking when designing, constructing and operating a given solution. The tighter this loop can be made, the less waste the process will have, the solution can remain healthier via pruning of dead weight and optimization, and there is a far lower likelihood of “gathering dust” post “completion” Modern iterative processes such as DevOps leverage agile planning such as Scrum or Kanban and seek aggressively to create feedback loops to ensure that the team remains truly productive, and not simply “activated” (working, but not doing anything that helps the organization achieve its goal). In summary – “Project” thinking tries to define and create perfection out of the gate, but this is rife with hidden assumptions and difficult to deliver value quickly. “Iterative” thinking (often described as “Product” based) is focused on quickly testing each assumption and delivering value as quickly as possible.
Common Artifacts of a Solution Architecture
When considering what the output of a solution architect’s effort should be, we should first consider the value brought to an organization by the discipline of practicing solution architecture. In general we will favor “actionable” or “executable” documentation – communication vehicles or frameworks that first and foremost enable the consumer to directly act on the information provided and which are strictly bound to the software development lifecycle and required to be correct as a foundation for the solution at large. Communication of Solution’s Intent
What is the point of the solution? If either customer of the solution or the engineers implementing a solution are unclear – the results both in terms of product and process will be subpar. Customers are likely to feel their needs have gone unheard. Engineers will over/under build and will disagree on what should be done and when. Finally, stakeholders will be hard pressed to evaluate if the solution has delivered the expected value or return on investment! When thinking about how best to communicate intent, you should:
- Make the documentation accessible and ensure common understanding between both customers and engineering
- Iterate and update as new capabilities are introduced, or old ones modified
- Tie capabilities to service level objectives and measurements of success so stakeholders clearly see value and engineers know if they are meeting expectations
Communication of Solution’s Interface
With intent established and agreed upon, customers will need to understand how to use the solution, and engineers are uniquely situated to share this information. We will explore the idea of “contract first” development in more detail later in this book, but in a nutshell, it is the idea of mapping the intent to code-based contracts describing the methods a customer would use to interact with capabilities that are going to be developed. When implemented well an API contract will define the data format required for invoking the solution’s methods, the action that will be taken (as related to the intents described above), and the data format that can be expected to be returned. Strict versioning practices (for example the “Semantic Versioning” format described at https://www.semver.org) enable customers to be protected against changing implementations and engineers practices that enable freedom to evolve the solution as a whole.
Communication of Solution’s Runtime Environment
A solution’s infrastructural needs can be thought in terms of the following broad topics:
- Disaster Recovery / Continuity of Service
- Other Services
Modern “cloud” thinking has led to dramatic increases in the ability for solutions to describe their infrastructure needs “as code” in such a way that the precise needs are not only documented, but easily versioned, migrated, and directly used to create and modify the runtime environment. For example – compute can be described directly (“use instance type xxx-yyy of size G1”), networking (“create a gateway, attach it to subnet xyz with IP range 10.0.0.0/8”), and even scaling (“scale out by 20% when fleet average CPU exceeds 65% for N minutes”).
Documentation of dependencies on third parties can be captured by proactive health monitoring – simply including in your solution regular programmatic evaluation for the availability of components that are required for your solution to function properly. This accomplishes two key outcomes – communicate the need for that third party, and enable your team to quickly diagnose when an issue has occurred! Communication of Application Architecture
The final key area a solution architect must ensure is clearly described is the architecture of the solution itself. Here again, the goal is not to translate but to directly convert from the implementation to a human-readable format.
This aspect of communication is dominated by concepts like Interfaces, Dependency Injection / Inversion of Control, Command Query Responsibility Segregation, Unit Testing, and more. In each case, the goal is to have the name and purpose of each component be absolutely clear with as little ambiguity as possible, with solution complexity minimized and localized to ensure an engineer has to keep the minimum amount of information loaded into short term memory before accomplishing a given task. Whenever possible, favor describing the intent and structure of the application as code that directly drives the implementation and behavior to ensure it is up to date and accurate. Without accuracy, some documentation is worse than no documentation – it points consumers in the wrong direction and makes them second guess!
Agile and Solution Architecture – The New Paradigm
In times long past, it was thought that an architect’s involvement in a project should start with deciding what was needed, prescriptive recommendations on how to get there, and participating in “sign-off” that a solution met their expectations and the functional / non-functional requirements. The influence of “agile” thinking and the significant productivity gains have challenged that thinking and resulted in new approaches that require a solution architect (and even enterprise architects) to be much more directly involved in the implementation cycle of a solution. The role of a solution architect can be thought of as a cycle beginning with discovery/analysis, proofs of concept for the hypothesized solution, development and grooming of the team’s work item backlog, and finally measuring results to drive the next phase of discovery & analysis. It is worth noting that these phases are not strictly discrete steps – a solution architect may be involved in several features at different stages of the process at any given time!
Discover and Analyze
To relate this phase to the scientific method, one can think of discovery as the “observation” step. In this phase, a solution architect would primarily focus on identifying a single phenomenon or concept. Once identified a hypothesis would be stated predicting the outcome if a particular change is implemented in addition to the associated measurement that would establish whether the hypothesis had the expected effect.
Get Your Hands Dirty with a Proof of Concept (POC)
Armed with a hypothesis a solution architect would then be intimately involved with the creation of a proof of concept (even producing it on their own) designed to demonstrate and evaluate the correctness of their hypothesis. This proof of concept should be as lean as practical to be trustworthy.
Backlog Development & Grooming
Throughout the solution’s lifecycle an agile team will rely heavily on both the leadership and humility of their solution architect. You must clearly articulate the purpose and requirements of each capability the team maintains, establish acceptance criteria, and actively participate in code review, testing, and other ceremonies observed by the team. If a team member notes an observation that contradict the core hypothesis of a particular concept that has been implemented, they should be explored and used to help strengthen the solution as a whole!
Measurement, Feedback & Iteration
Similar to the humility mentioned above and key to the scientific method is the idea of prediction and measurement. Our goal is to ensure our assumptions are accurate and that feedback in incorporated as quickly as possible. This results in higher satisfaction and significantly less rework overall and helps the team understand and feel the meaningful impact of their activities.
References and Further Reading
- Fowler, Martin, et al. Manifesto for Agile Software Development Web site, 2001.
- Cohn, Mike. “Advice on Conducting the Scrum of Scrums Meetings.” Mountain Goat Software Web site, May 2007. (Originally published in Scrum Alliance Web site.)
- Evans, Eric. Domain-Driven Design: Tackling Complexity in the Heart of Software. Boston: MA, Addison-Wesley, 2004.
- Bass, Len, Paul Clements, and Rick Kazman. Software Architecture in Practice. Second ed. Boston, MA: Addison Wesley, 2003.
- Goldratt, Eliyahu. The Goal: A Process of Ongoing Improvement. Fourth Edition. The North River Press Publishing Corporation, 2014
- “Clean Architecture with ASP.NET Core 2.1.” https://www.youtube.com/watch?v=_lwCVE_XgqI