Software Architecture Patterns by Mark Richards
modified 20/04/2024 22:46What follows are my crude notes on the paper Software Architecture Patterns by Mark Richards
High-level overview
- not your regular paper i guess, more like a short blog/tutorial in the format of a paper, as it doesn’t seem to include any references to other papers
- author is a software architect
- author proposes 5 most often used software architectures, analises flaws and advantages over a specific set of criteria, which makes it easy to figure out use-cases of each, as well as providing a short but comprehensive overview of each, in order to choose and be able to justify the choice of a specific architecture
- paper assumes some knowledge about software architecture and knowledge of basic concepts like scalability, orchestration, loose coupling, so reading soemthing like Designing Data-intensive Applications will make understanding this paper easier. It is not, however, an official requirement, just something I’ve noticed.
Analysis criteria and their meaning
ease of change :
ease of deployment :
testability :
performance :
scalability :
ease of developement :
Layered Architecture
- the de-facto architecture for most software projects
Main Idea
- app is split into multiple isolated layers, each with a specific role, and performing some atomic, abstract piece of work, specific only to that layer (displays stuff, performs database operations, performs business logic); request data is passed and received from layer to layer, but can’t generally go through layers;
- suppose there’s 4 layers: presentation -> business -> persisence -> database; each layer ideally is closed – message passing happens, from the highest layer to the lowest: if user requries access to the persistance layer, it has to pass all other layers (presentation -> business -> persistance);
- this ensures that changes in one layer don’t affect other layers: migrating to another UI framework won’t change the underlying business logic, for example.
- suppose there’s 4 layers: presentation -> business -> persisence -> database; each layer ideally is closed – message passing happens, from the highest layer to the lowest: if user requries access to the persistance layer, it has to pass all other layers (presentation -> business -> persistance);
Advantages
- separation of concerns
- each layer can be treated as a separate piece, and can thus be developed and tested independently of other layers (data specific to other layers can be mocked and so on) == easy to test and develop
Flaws
- tied to monolithic applications, as it’s quite difficult to split the layers into separate deployable units (though i guess you could maybe split the interface from the rest, and then deploy one as the front-end and the other as an api, that’s not quite it) == dificult to deploy, scale (since monolithic), and change
- not extremely performant, since requests have to pass through mulitple layers to perform stuff
TODO find examples of software that uses this and see how it’s organized
write a bit about it. or write a separate post
Event-Driven Architecture
- distributed asynchronous architecture for highly-scalable apps
Mediator Topology
- complex event processing flow
- 4 components: queue (message queues, api w/e), mediator (spring integration, apache camel, mule esb), channel (topics), processor (what performs the business-logic task)
- flow: client -> queue -> mediator -> channels -> processors
- mediator creates events, processors only process them
Broker Topology
- simple event processing flow
- no mediator, instead each event-processor component both, processes and publishes other new events => chain of events
Advantages
- easy to change because every component is single-purpose and isolated (you don’t have to think about what else you’re going to affect)
- easy to deploy since every component is separate
- high performance since async
- easy to scale – just create more processors/queues/channels
Flaws
- hard to implement because it’s asynchronous which brings a lot of problems: hard to test, hard to develop
- lack of atomic transactions because everything is asynchronous => need to think about what tasks depend on which tasks
TODO find examples of software that uses this and see how it’s organized
write a bit about it. or write a separate post
Microkernel Architecture
- use this for product-type apps (not sure what this means exaclty)
- maybe it refers to code that is not an api or library, but is instead a app with gui and all of that?
- app logic is divided into core functionality, that provides minimal functionality and plug-in modules that provide additional functionality, as required
- core system: minimal functionality to make the system operational and allow adding and keeping track of current plug-ins; generally requires some sort of repository to be able to manage plug-ins
- plug-in modules: independent components that connect to the core system to add new features and extend the core system; shouldn’t comunicate/depend on other plugins (ideally)
- author writes: type of connection you use depends on type of application your are building… – i wonder what this means? what type is used for what needs? and why? figure this out
Examples
- VSCode/neovim: base functionality of code editing, but only when you start adding plugins you get to see the true power of it; maybe emacs too, but i think emacs has more stuff out of the box, and you can comfortably use emacs even without adding anything.
- obisidan: another good exapmle; has nice ootb features but shines when used with plugins.
- web browsers: not as microkernel as previous example, but still has the possibility to add plugins, which enhace the browsing experience. But web browsers generally provide a bigger core, so you can use them without any plugins too.
- conclusion is: you can use it on it’s own, or embed it into another layer to create the possiblity of having a plugin system
Advantages
- easy to change
- core is completely isolated from plugins == if core doens’t work, fix core, if plugin doesn’t work, fix plugin
- easy to deploy
- only deploy core, and add plug-ins dynamically
- high performance
- you add only what you need, so resources don’t gets wasted on stuff you won’t use
Flaws
- hard to develop
- needs a lot of thinking to create a good core contract, because if you change it after that, all plugins that depend on it will die
TODO this part should be completed after i learn more about what scaling means
- hard to scale
- not a lot of things you can do
TODO what OSGi is
Plug-in modules can be connected to the core system through a variety of ways, including OSGi (open service gateway initiative), messaging, web services, or even direct point-to-point binding (i.e., object instantiation).
TODO what is SOAP
It might also contain a WSDL (Web Services Definition Language) if the plug-in is accessed through SOAP.
TODO what is a WSDL, why it’s used
quote: It might also contain a WSDL (Web Services Definition Language) if the plug-in is accessed through SOAP.
TODO what is a contract and contract versioning
quote: When creating standard contracts (usually implemented through XML or a Java Map), it is important to remember to create a versioning strategy right from the start.
TODO what is scaling in software terms?
my guess is that it’s the ability to handle a growing user-base, and how to do it (buy more metal? deploy more clusters? this i guess is a bit more complex, and related more to ddi)
Microservices Architecture
- main alternative to monolithic apps
- all components are decoupled from each other and are deployed separately
- two main concepts:
- separately deployed unit: components of the architecture are deployed separately
- service component: modules with a single-purpose function; setting the right purpose is the hard part.
- developed to solve 2 problmes that come with previous patterns:
- Monolithic apps are made from tightly-coupled components, which mean that adding something new to a compoment could break the entire app and entire app would have to be re-deployed after fixing. Microservices are decoupled, so if something breaks, only that component is affected, not the entire app.
- Service-Oriented Architecture is really complex, micro-services simplify notion of a service
- need to read more about SOA
REST API toplogy
- services are accessed via a common api (deployed separately), that makes requests to the other components using REST interfaces
Application REST topology
- same as REST API but requests are made not through another API but through a UI
Centralized messaging topology
- same as Application REST but the requests to the other compnents are made through a message broker instead of REST
- more scalable, easy ot monitor and easier to handle errors thanks to the message broker
Questions and stuff to check out
- author says “If you find you need to orchestrate your service components from within the user interface or API layer of the application, then chances are your service components are too fine-grained.” – not sure i get what “fine-grained” means, and what “orchestration at the user interface level” means, or what orchestration means, and what level should orchestration be at.
TODO what is the difference between service and product in software?
author says: The microservices architecture pattern is quickly gaining ground in the industry as a viable alternative to monolithic applications and service-oriented architectures.
TODO what is continuous delivery
TODO what is a monolithic app
TODO search for examples of this pattern and provide examples
TODO find examples of software that uses this and see how it’s organized
Advantages
- easy to change and easy to test, since components are de-coupled and separated
- easy to develop: (making changes to a component shouldn’t break the entire app);
- easy to scale: just add more resources to the service that requires that
- seems there’s a mistake in the Ease of deployment. In the paper, it refers, I believe, to the Event-Driven Architecture
Flaws
- lower performance because you need to make requests to other services
Space-Based (Cloud) Architecture
- used to solve the “triangle” scaling problem: scaling web server is easiest, application is hard, db is hardest that generally appears in extremely large concurrent user load
- esentially, there’s no central database and everything is kept in memory
- distributed shared memory; application data is kept in memory and ditstributed across processingu units depending on load
- actual app; what actually does the work
- various different grids used by the processing units:
- messging grid: assigns processing units to requests
- data grid: most important part; handles data replication
- processing grid: manages distributed process handling when there’s multiple processing units available
- deployment manager: manages startup and shutdown of processing units as load decreses and increases