Software Architecture

Software architecture is the underlying design of a software system. It defines its structure and associated behavior. Software engineers and architects build modern software by defining how the components interact with each other, along with the environment and principles dictating their behavior. Within this page, our in-house architects explain the software architecture approaches and patterns.
Consult me on software architecture

High-Level Architecture Designs

High-level architecture designs (HLAs) dictate how a system will be developed. It showcases how components interact with each other and the system’s interface. Our architects describe below the high-level architectural designs that they have used in their project experience:

Monolithic Architecture

It uses a unified approach to system design and building. Here, all the application components stay in a single codebase including the business logic, data access layers (handles interaction between components and data storage), and user interface.

This brings benefits such as tight integration, simplicity, easy management & initial setup. It is also cost-effective and provides high performance (direct access to the kernel) and security.

The key monolithic architecture features include:

  • Single codebase: Everything is developed, maintained, and deployed via a single codebase.
  • Centralized database: All the data is stored and accessed in a centralized database.
  • Integrated and interdependent: All components including the interface, database, and processes are coupled together and work efficiently.
  • Shared memory: In most cases, monolithic apps use single memory to ensure high performance.
  • Layered structure: Follows a layered structure such as data access layer, business logic, and presentation layer — each carrying out specific tasks.
  • Limited scalability: As everything is coupled, it is a challenge to scale monolith applications.

Monolith architecture is most suitable for high-performance applications. It is also an ideal pick for scenarios such as:

  • Building proof of concept
  • Small team working at the foundation stage
  • The app is not complex and doesn’t require advanced scalability

Microservices Architecture

Microservices architectures rely on breaking up a system into small independent parts, allowing them to operate alone without depending on others.

The independent services can communicate with each other to create a functioning application. It follows a completely opposite philosophy of monolithic architecture that relies on a single codebase. For example, for a user request, a microservice application may need to call internal microservices to complete the request.

The benefits of microservices architecture include:

  • Failure-proof due to isolation: if a component fails, other independent parts will still keep working).
  • Increased productivity: it enables team members ability to learn about the app architecture more easily, leading to faster project development. 
  • Improved scalability: Scale is easier due to small components and isolated architecture.
  • Excellent flexibility: Give developers the ability to choose the tools of their choice, be it a framework (such as Spring Boot) or a language that can make the most out of microservices architecture.

Microservices architecture key features include:

  • Service independence and autonomy: Businesses can deploy and manage microservices with the ability to work without depending on other tools, services, or services.
  • Utilizes APIs heavily: Microservices use REST APIs to communicate (synchronous or asynchronous) and share information between themselves. It makes it easy to integrate new services.
  • Built-in security: To facilitate a secure environment, microservices are built with security in mind. Additionally, teams must take extra care when using multiple microservices and how they deal with security when working together.

Microservices architecture is ideal for companies that want to deploy scalable applications. It also suites companies that deal with multiple devices and platforms. For example, Netflix uses microservices architecture (shifted from monolith to microservices in 2009) to seamlessly support different devices including TVs, mobile phones, tabs, and other display devices.

SOA Stands for Service-Oriented Architecture

Service-oriented architecture uses services-based components to create business applications. Each service-based component offers a useful capability for the business and is capable of communicating with other similar components across programming languages and platforms.

They are highly reusable and provide the right tools to handle complex tasks. For example, businesses can use the same user authentication service component to power different services that they provide. It helps create them to create a single authentication system without rewriting the code each time.

Service-oriented architecture brings multiple benefits including:

  • Adaptability: Encourages businesses to adapt technology advances with cost-effective and efficient modernization.
  • Faster time to market: Businesses that use SOA can time market faster as they re-use and integrate services rather than re-developing them from scratch.
  • Easy maintenance: Maintaining SOA applications is easy as each SOA has a smaller code base and can be modified without impacting other working SOAs.
  • Easy extension of business processes: SOA apps use SynQ (provides modular services) and warehouse (picking, putaway, and inventory management) to use services. These are commonly used services making it easy to integrate new services.

SOA architecture’s key features include:

  • Loose coupling: Services are loosely coupled with low or little dependency on other external resources or other services. 
  • Abstraction: SOA architecture provides an abstraction to services as businesses using them don’t know the underlying service code logic or how it is implemented.
  • Interoperability: Services can be run without depending on the client system’s underlying platform technology such as programming language.
  • Granularity: Offers one discrete business function per service with a clear scope.
  • Easier maintenance: As services are stateless, they don’t get impacted when modified as it doesn’t store any previous translation or session information.

Businesses can use SOA architecture to build large complex systems that use services. They provide excellent security and help standardize components. For example, militaries and air forces use SOA to implement situational awareness systems.

Cloud-Based Architecture

Cloud-based architecture is primarily used for building cloud computing environments. It integrates technologies such as virtual resources, storage devices, physical services, databases, software, and networking elements. It combines the EDA (Event Drive Architecture) and SOA (Service Oriented Architecture).

Businesses can modify the cloud-based architecture based on their requirement of deploying and running applications. The cloud architecture consists of the following components:

  • Frontend platform
  • Backend platform
  • Network (intercloud, intranet or internet)
  • Cloud-based delivery model

The benefits of cloud-based architecture include:

  • Faster time to market: Cloud computing infrastructure such as Amazon Azure, Google Cloud Platform, etc., are readily available and hence don’t require you to configure one. With a simple cloud setup, developers can start developing their cloud app/service instantly.
  • Cost-effective: A willingly available cloud platform with dynamic pricing and a pay-as-you-use model, making cloud architecture cost-effective.
  • Scalability: Developers can add/remove cloud resources to adjust their demands. Many vendors offer auto-scaling to ensure operational efficiency during traffic spikes.
  • Security: Cloud services are highly secure, and proactively protect business services/apps from malware or DDoS attacks.

Serverless Architecture

Serverless architecture focuses on providing abstraction by allowing developers to build and manage apps without the need to manage the underlying architecture. The service provider takes care of scaling, provisioning, and managing. They provide automatic scalability and are highly secure.

The benefits of serverless architecture include:

  • Scalability: The serverless architecture can scale up and down automatically based on traffic (incoming and outgoing).
  • Automation: Helps automate tasks and remove managing services.
  • Productivity: Improves developer’s productivity by reorientation focus from server management, to writing business logic code from the onset.

Behind the scenes, serverless architecture works by hosting application code as a function on container technology such as Kubernetes. When a user requests, the function is triggered and the cloud provider spins a new instance to handle the requests. The serverless functions can also get triggered via database change, HTTP requests, mouse clicks, and so on.

Serverless architecture is best suited for various use cases, including building RESTful APIs, asynchronous processing, developing trigger-based tasks, and Continous Integration (CI) & Continuous Delivery (CD). It is also useful for stream processing, ETL pipelines, cron jobs, and microservices.

Multi-Tier Architecture (OR multi-layer)

Multi-tier architecture (also known as multi-layer) uses multiple layers to achieve different functionalities such as presentation, business layer, data management, and application processing. There can be 1-tier, 2-tier, 3-tier, and even n-tier architecture depending on the requirements.

The benefits of multi-tier architecture include:

  • Faster query response time
  • Scalability
  • Better data quality
  • Reusability
  • Modularity

Multi-tier architecture key features include:

  • Separate layers: Each layer handles different tasks ensuring clear separation such as the database layer carrying out database functions, the presentation layer dealing directly with the end user, and the business layer handling the business logic.
  • Flexibility: Provides businesses flexibility with scalability and efficiency due to separate layers.
  • Scalability: The system can handle users with easy scalability options.

Multi-tier architecture is best suited for eCommerce, social media platforms, and healthcare information systems.

Low-level and Middle-level Architecture Approaches

Not all the above software architecture patterns solve software design challenges. That’s where low-level and middle-level architecture comes in. In this section, our software architects give a closer look at creational patterns, structural patterns, and behavioral patterns.

Creational Patterns

Creational patterns resolve design/complexity problems with basic object creation when dealing with object creation mechanisms. Below are the types of creational patterns commonly used in software development.

  • Abstract Factory: An Abstract Factory pattern deals with related objects’ family creation without the need to create their classes.
  • Builder: Helps in creating complex objects with a multi-step approach. It is useful when objects cannot be created in a single step. For example, complex object deserialization. Its advantages include better construction process control, object internal representation change, and having a clear difference between object representation and construction.
  • Factory method: It is an abstract class or interface where subclasses decide which class to instantiate. It allows loose coupling and eliminates the need for application-specific classes.
  • Prototype: Prototype Pattern allows copying existing objects with customization. It removes the need to create a new object every time the need arises. Its benefits include inexpensive object creation, reduced complexity and add or remove objects during runtime.
  • Singleton: The pattern is useful for defining a class with only one instance. It has a global access point and can be initiated early (at load time) or Lazy (when required). Its benefits include memory optimization due to only single instance usage with use-cases including multi-threading, caching, etc.

Structural Patterns

Structural Patterns give developers the ability to create larger structures by assembling objects and classes. It uses inheritance to its advantage while ensuring flexibility efficiency and system designs. Below are some of the Structural Pattern types:

  • Adapter: The adapter (also known as a wrapper) enables connecting objects to incompatible interfaces. Its benefits include reusability. For example, a stock market monitoring app can use an adapter to collect stock data from multiple sources and display them in graphs.
  • Bridge: Bridge allows class decoupling with one class containing two separate but related classes, each with its own abstraction and implementation. It brings benefits such as extensibility and hiding implementation details from clients.
  • Composite: Composite Patterns let software architects compose objects into tree structures without impacting their individuality. Architects must only use Composite patterns if a tree representation of the objects is possible. It helps in showcasing class hierarchies, adds new components easily, and ensures structural flexibility.
  • Decorator: The decorator enables adding wrapper objects to existing objects with new behaviors. It is similar to adding more functionality to an object dynamically with advantages such as better flexibility compared to static inheritance.
  • Facade: A simplified and unified interface to an already-existing framework, library, or set of classes. It gives developers a simple interface to complex subsystems and promotes loose coupling between clients and subsystems.
  • Flyweight: A flyweight design pattern allows more similar objects into available memory by sharing common states between them. It improves memory utilization.
  • Proxy: Proxy pattern allows an object to represent another already-existing object. It proxy object controls access to the object. It allows hiding original object information and on-demand loading by performing early before the original object receives the request.

Behavioral Patterns

Behavioral patterns deal with object responsibilities and their interaction with other objects. 

  • Chain of responsibility: Here, pass requests are managed by a chain of objects that use handlers to pass the request. Each handler decides if the request needs to be processed or passed to the next handler.
  • Command: A behavioral design pattern that transforms a request into a stand-alone object containing all the requested information. 
  • Interpreter: It defines given language grammar for interpreting sentences in the said language. 
  • Iterator: Allows to go through collection elements without making its underlying representation public.
  • Mediator: Help reduce dependencies among objects via mediator object.
  • Memento: Restore an object’s previous state without revealing its implementation details.
  • Observer: Provides a subscription method for any changes done to the observing object and notifies them to other subscribed objects.
  • State: Gives object the ability to change its behavior if internal state changes. This gives the impression of class change to the object.
  • Strategy: Let developers define a family of algorithms by putting them in a separate class. The created objects are interchangeable.
  • Template Method: Enables subclasses to override algorithm-specific steps without the need to change the superclass algorithmic skeleton.
  • Visitor: Ensure that operated objects get separated from objects from algorithms.

Concurrency Patterns

Concurrency patterns give developers the ability to handle multi-thread programming, allowing processes to work in parallel These patterns include:

  • Active object: Allows separation of method invocation and execution for objects residing in their own control thread. It uses asynchronous method invocation with a scheduler (for handling requests).
  • Balking: Executes object action when it is in a particular state.
  • Binding properties: Synchronizes different objects’ properties to coordinate via multiple observers.
  • Double-checked locking: reduces lock overhead by testing before acquiring the lock.
  • Event-based asynchronous: A design pattern where the call site waits for the called code to finish. Here, the calling code gets notified with a reply.
  • Guarded suspension: Ideal for operations where a precondition and lock need to be acquired before execution.
  • Join: Uses message passing to write parallel, concurrent, and distributed computer programs.
  • Lock: Prevents state from being accessed by multiple threads or modified during execution.
  • Monitor: It is a synchronization construct that stops threads from concurrently accessing a shared object’s state.
  • Proactor: makes sure that long-running activities run in asynchronous part.
  • Reactor: Concurrently handle multiple service requests for event handling strategy.
  • Read-write lock: solves reader-writers problem with RW lock allowing concurrent access for read-only operations and write operations allowed exclusively.
  • Scheduler: Assign resources to perform tasks such as data flows, processes, or threads.
  • Scheduled-task pattern: Aimed to be used with real-time systems with determined time execution.
  • Semaphore: a variable type that allows multiple threads to access the common resources without issues.
  • Thread pool: Focuses on allowing concurrency execution in computer programs.
  • Thread-local storage: a memory management method that utilizes global or static memory locally.

Other Architectural Patterns

Architectural patterns aim to solve different software solution architecture engineering issues such as hardware performance limitations. These architectural patterns are categorized into distributed and monolithic.

  • Front controller: handles all requests of a web application such as a website. It offers flexibility and reuse.
  • Interceptor: Offers the ability to change frameworks/software systems’ usual processing cycle. 
  • MVC (MVP – MVVM): MVC stands for model-view-controller. It is a popular way to create web applications where each layer handles certain aspects of the application. For example, the model handles information representation, the view is the interface to the user, and the controller links both the model and the view.
  • ADR: ADR stands for Action-Domain-Responder refines the MVC model with the improvement of HTTP request-response flow closely matching MVC.
  • ECS: ECS stands for Entity-component-system. It is used for video game development with a focus on game world objects.
  • N-tier: It is a client-server architecture with separate layers for data management, presentation, and processing. For example, three-tier architecture such as MVC and ADR.
  • Specification: This pattern allows the developers to use boolean logic to combine business rules in a chain of rules. Specification pattern is ideal for domain-driven design.
  • Publish-subscribe: Here, publishers categorize the messages into classes. Once done, it sends it to the subscribers.
  • Naked objects: An architectural pattern with three principles: domain objects must be used to encapsulate business logic, and the user interface should directly represent the domain objects and must be created using domain object definitions.
  • Service locator: Uses an abstraction layer to encapsulate processes that obtain services.
  • Active record: Active record pattern deals with in-memory object data where the object interface must confirm functions such as Update, Insert, and Delete. It helps data access.
  • Identity map: Improves database performance with more in-memory and context-specific cache. It solves duplicate data retrieval.
  • Data access object: The DAO pattern allows architects to create an abstract interface to a persistence mechanism or database.
  • Data transfer object: The DTO pattern takes care of data transfer between processes via object.
  • Inversion of control: IoC pattern allows the flow of control of a computer program from an external source.
  • Model 2:  Separates the logic from display in Java-based web applications, ideal for enterprise software architecture. 
  • Broker: The Broker pattern helps structure distributed software product architecture with decoupled components.
Request Consulting from Software Architects for Your Project