Evolution in Software Architecture

Img src :Unfinished Evolution by György Csepeli

Over the last decade, software engineering’s scope has risen to provide more responsibility and perspective. A decade ago, with lots of bureaucracy, the typical relationship between architecture and operations was contractual and formal. Most companies, trying to mitigate the complexity of hosting their operations, often outsourced operations for a third party company, consisting of contractual obligations for service level agreements. Nowadays, architectures such as microservices freely leverage former solely operational concerns. This article’s primary objective is to briefly discuss the ‘Software Structure’ as an initiative for our topic.

Introduction

What is Software Architecture?

Software architecture consists of four features; software structure, architecture decisions, architecture characteristics, and design principles described by Mark Richards and Neil Ford in their book (Software Architecture Fundamentals). Moreover, due to the rapidly changing software development ecosystem, software design has continuously shifted target.

In the same manner, it does not entirely elucidate an architecture by defining an architecture purely by its form. To properly understand the software architecture, knowledge of the architectural elements, architecture decisions, and design concepts should also be required.

Figure 1 : Software Architecture — Ref : Fundamentals of Software Architecture

Another feature in describing software architecture is software architecture characteristics. Many characteristics can be defined, and there are no hard and fast rules where any system’s architecture should comply with all software architecture characteristics. First of all, the software architect should determine the software’s business and functional objectives and define the characteristics that should follow in a way that best suits the business goals. Determining these characteristics is an act of balance that depends on what we are trying to achieve from the system. One best example to illustrate this is the usage of Graphic equalizer in sound systems. Based on the genre, intensity, loudness, clarity of the music, environment, etc., one needs to adjust its knobs to achieve optimal music satisfaction. As a more concrete example, if your system is more concerned about security, you need to compromise aspects such as performance.

Figure 2: Software Architecture Characteristics — Ref : Fundamentals of Software Architecture

What are the Expectations of an Architect?

Decision making

It is challenging to direct technology choices through architecture decisions and design concepts. The key to making the right architectural decisions is to consider if the architectural decision helps direct teams make the right technical choice or whether the architectural decision’s technical choice is made.

Continually analyzing the architecture

Keep current with the latest trends

Ensure compliance with decisions

Diverse exposure and experience

Have business domain knowledge

Possess interpersonal skills

Understand and navigate politics

The evolution of the Software Architecture

I will use the architecture evolution of one of the SaaS software products I worked on for few years to walk you through this journey. Furthermore, I would be considering only the structural evolution of software architecture.

Monolith

Many tend to think that the Monolithic architecture style is becoming obsolete now. But as I see, it is one of the simplest and easy to understand and implement architectural patterns that we do have.

Figure 3 : Monolithic Software Architecture

Subsequently, when many people try to get on board with the Monolithic SaaS application that we have created, problems such as scalability, elasticity, and resilience occur. In these situations, what is normally done is we identify which part of the module that users have been using more frequently and consequently take out that particular component from the initial Monolith.

Figure 4 : Distributed Monolith

We have exposed that separated component as a rest API, where our frontend client can access it independently. Here, in this case, our frontend clients have to maintain two end-points, one pointing into our main Monolith and the other pointing to our newly created service.

Distributed Monolith

One of the drawbacks of this type of architecture is that, in the deployment process, it would be a bit troublesome, as all components have to be deployed or released at once since the database is shared in between these services. Also, to overcome frontend maintenance, API gateway has been introduced in the Distributed Monolith system. In this circumstance, the frontend web application concentrates only on one endpoint where the API gateway knows about routing these particular API requests into correct services. Moreover, the API Gateway handles the authentication part as well.

The entire application is bundled into a single package in a monolithic architecture, including binaries, libraries, configurations, and all other dependencies required for it to run. With a distributed monolith, we have the heaviness and inflexibility of monoliths, microservices’ complexity, and a few of both architectures’ benefits. We would still have slow deployments and poor scalability. But we have added operational complexity and removed isolation between services. Here, in this case, the team would adopt new tooling and rebuild the applications to tolerate the dynamic and transient world of containers by adding tons of time and labor.

Distributed SOA

We had to live with this kind of distributed SOA for few months until we introduce the Event-Driven Architecture during our evolution.

Figure 5: Distributed SOA

Event-Driven Microservices Architecture

Microservices architecture emerged as a remady to many difficulties faced in all Monolithic architectures. In our solution, we never used pure Microservices architecture but Event-Driven Microservices architecture.

As the microservices are decoupled, they could scale more easily, and whenever you want to make a change, you could change just a single component. But still, there could be problems encountering. So to overcome these kinds of issues, some of the microservice applications have adopted event-driven architecture. The main disadvantage in a classical Microservices architecture is a dependency between synchronized service calls. Ie: we have a highly coupled solution even though we are using independently operating services. There could still be deployment dependencies if we have high coupling between services.

The main decoupling of services has been achieved using the event bus. Whenever there is an action, a service would publish an event to the event bus and where a specific set of services would be subscribing to it.

There are many technologies these days that you could use to stream events from one component to another, where ‘Kafka’, which may be the most popular streaming service, which is a good fit for Event-driven architecture as well.

Figure 6 : Event-Driven Microservices with enabling functions

Moreover, to remedy problems encountered when using Event Bus, as shown in Figure 6, Service Discovery and other required support services and functionalities.. Alert systems and self-healing systems have also been introduced to spin up new instances of that particular service.

In our SOA version of the product, the major pain area we had was scalability, resilience, performance, and maintainability ( it was an office fiasco during deployment days) mainly because of the shared database inter-service dependencies. With the introduction of EDM ( Event-Driven Microservices), most of these pain areas were evaporated, and the life of our DevOps guys became more relaxed.

With this, there is one more small note that I would like to make, especially when it comes to the individual services’ performance. We had few services which were heavy on both data reads and writes. To get away from the obvious performance bottleneck, we introduced the CQRS pattern as depicted in Figure 7.

Figure 7 : Command Query Responsibility Segregation to improve DB Performance

Most of our backend fine-tuning stopped from this point, but our frontend SPA application still lives in the Monolithic world. Lets see what we did for that.

EDM with Micro Frontends

Instead of working distinctly from each other, developers are all bound to the same codebase of a growing SPA or SSR app and are all forced to crowd in the same build pipeline. This makes development inefficient and hard to scale, so that the idea of micro-frontends is to allow the benefits of microservices in the frontend world.

EDM with Micro-Frontends

In this scenario, shown in figure 8, we see patterns emerge for decomposing frontend monoliths into smaller, simpler chunks that could be developed, tested, and deployed independently while still appearing to customers in a single cohesive product.

This technique is called the micro frontends. Simply, this is an architectural style where independently deliverable frontend applications are composed into a greater whole.

Benefits from Micro Frontends

  • More scalable organizations with decoupled, autonomous teams
  • The ability to upgrade, update or even rewrite parts of the frontend more incrementally than was previously possible

There are few frameworks. that use can use to ease off the development effort of Micro-frontend. Single SPA is one of the best example.

CTO @ ZorroSign | Seasoned Software Architect | Expertise in AI/ML , Blockchain , Distributed Systems and IoT | Lecturer | Speaker | Blogger

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store