Principles for Selecting Software Architectures

Reference Architecture & Frameworks

By Alok Mehta, SVP and CIO – Business Systems of Kemper Corporation, and Sujay Chauhan,  Senior Manager – IT of Kemper Corporation

Alokmetha
Alok Mehta

Selecting a software architecture often leads to hot debates and “religious wars” amongst engineers who are responsible for building solutions to meet business needs. To select an architecture, it is important to know what options are available from the trusty old monolith to the modern microservices/front-end based architectures. However, regardless of the choice, there are foundational software engineering constructs that can serve as guiding principles. This note serves to outline these guiding principles and explain how to use them when making architectural selections.

These foundational software engineering principles include:

  • Cohesion: Refers to the degree to which elements inside a module belong together. We would want high coupling, meaning, like functions should remain close together from an implementation standpoint.
    Sujay
    Sujay Chauhan
    • Example: A class that groups together arithmetic operations.
  • Coupling: Refers to the degree of interdependence between software modules. We want loose coupling among software components within an architecture, reducing impact when maintaining or changing the software functions at a later point in time.
    • Example: A separate class that utilizes the functions of the arithmetic operations class.
  • Abstraction: Refers to the process of creating abstract objects by mirroring common features or attributes of various non-abstract objects. We want our solution to be as abstract as possible.
    • Example: Creating a calculator interface with add, subtract, multiply and divide functions.
  • Testability: is the degree to which a software artifact (i.e. a software system, software module, requirements- or design document) supports testing in a given test context. If the testability of the software artifact is high, then finding faults in the system (if it has any) by means of testing is easier.

Cohesion, coupling, and abstraction are very theoretical and often not practical, especially when you are trying to manage software projects with large teams across the globe. So how can we simplify these theoretical concepts into a practical guide? Focusing on foundational principles of software engineering allows us to have better long-term maintainability, improved scalability, and higher agility.  We can view maintainability as minimal effort required to make changes to the architecture or application post-production. Scalability can be viewed as the ability for the architecture to allow for more users (vertical scalability) with minimal effort. Lastly, we can view agility as more functionality (horizontal scalability) with minimal effort.

Below is a simple guide that brings the notion of software architecture and software engineering principles together to aid in the selection of the optimal software architecture for your needs:

1. Survey the architectures available: Software architectures have evolved over time. It is important to keep educated. Architectures that are available to a software engineer today are Monolith, N-Tier, Client-Server, Service-Oriented, Event-Driven and Microservices.  Each architecture has its pros and Selecting the architecture is going to be the most important decision to make so take your time and ensure you have conducted peer reviews before proceeding forward.

2. Focus on the use case: A good software architect and engineer will respond – “it depends” when asked about how would you solve a particular problem? Focusing on the problem you are trying to solve dictates which architecture to apply. For example:

  • If you are looking to develop a headless (no user interface) service to solve a problem – you could get away with using a Monolith architecture on Mainframe.
  • If you are developing a web-based application, you would likely choose an N-tier architecture.
  • If you are developing a desktop application with a user-interface, you could use Client-Server architecture.
  • If you are integrating inter or intra applications, you may focus on Service-Oriented architecture.
  • If you are trying to develop a complex workflow application that require real-time updates of data across software components, you might choose an Event-Driven architecture
  • If you are developing a mobile app to be hosted in the cloud, perhaps Microservices-based architecture is best for that use case.

We have identified some common use cases above but there are many other use cases and variations.  The key takeaway for us is to focus on the problem and the use case before selecting an architecture.

3. Always think maintainability: A software engineer who builds the application or a solution, may not be the one to maintain it in the long term. The engineer who is building must put himself/herself in the shoes of the engineer who is going to maintain and the QA person who is going to test it, and then ask the following questions about each decision – how easy will it be to modify the decision I am making? Answering this question might affect the decision making.

4. Scalability is important: Seldom do you develop a solution for one user so, it is important to ask:How many users are expected to use this solution directly or indirectly over time?  Who are these users (or processes)? And most importantly, where are these located?  Basic questions about scalability will help to select the right architecture.

5. What about agility?: Every software architect wants more agility in their solution. But agility comes with a cost and a lot of pre-work. Keeping solutions abstracted will allow for more agility but it requires deep architectural and engineering expertise. Thus, peer reviews become even more important when considering highly agile solutions, which allow for making changes often by independent teams.

Conclusion:

The table below provides a summary of general architectures available to software engineers, and a summary.  While it’s not perfect, it allows us to be strategic in nature when deciding what architecture to use and what is at stake:

Typical Use Case Target Architecture Perspectives on Maintainability, Scalability and

Agility

Online/Batch processing on Mainframe Monolithic Mainframe programming in general is hard and requires years of experience and training. It requires specialized skills (which are rapidly diminishing in the marketplace) to practice sound software engineering principles. However, for a skilled mainframe programmer, maintainability is simple as all the code is together, but there is low agility. As the size of the application grows, scalability, and specifically cost-effective scalability,is a challenge.

 

Web-based Applications N-Tier Within N-Tier applications, it is easy to see how the fundamentals are implemented. However, due to the distributed nature of tiers, it requires many roles to successfully develop and deploy these apps. However, we see higher levels of scalability and agility. Separation of concerns in each tier (cohesion, loose coupling) leads to better maintainability.

 

Desktop Applications Client Server These apps are simple to implement and generally suffer from scalability when users are added over time and require additional server processing resources, due to the tight coupling. Nonetheless, these apps are relatively simpler to develop and maintain. Agility is a factor of how well the code is organized and abstracted.
Application Integration Frameworks SOA – Service Oriented Architecture SOA apps require lots of cross IT expertise like security, infrastructure, data management and software architecture. These are complex apps and must support backwards compatibility, which makes them one of the ideal candidates for practicing software engineering fundamentals. By nature, these are highly scalable, independently deployable services. Maintainability and agility are also high.
Asynchronous Workflow Based Applications Event Driven Event Driven architectures, while highly scalable, require a keen understanding of software design principles. A major barrier in these systems is complexity. Trying to keep systems consistent when order or sequence of processing matters, and maintaining transactional integrity & boundaries, are very hard. There is a raised abstraction level in these systems leading to the ability for independent teams to develop within their domain.
Cloud Based Applications Microservices Over the recent years, Microservices-based architectures are becoming popular.  These apps are like developing N-Tier apps but are further broken down in terms of their functionality. They’re generally fully automated (via Dev-Ops) and require full-stack development skills.  Since they focus on automation right from the onset, we believe this architecture is here to stay and enables engineering fundamentals in an explicit manner. These are highly scalable and maintainable applications with a focus on agility. Each module of cohesive code is bundled as a service and can be independently developed, deployed, and scaled.

 

We hope that we have simplified the decision-making process to select what architecture is best when solving a problem.  We have simplified many constructs in this short article.  In the end, there are many other things to consider when selecting an architecture that will depend on cost, resources, other applications in your eco-system and many other functional and non-functional requirements.

Venkatesh Padmanabhan contributed to this article.