Application Architecture Patterns by Joe Guadagno
9K views
Nov 6, 2023
Architecting an application can be challenging. What do you do to keep your application flexible to ever-constant requirement changes? How do you handle landscape changes (cloud, on-premises, databases)? How do you avoid over-engineering the application? How do I make sure my application plays well with other applications? In this session we’ll take a look at some well-understood and practiced Software Architecture patterns. We’ll cover these patterns at a high level to understand how to use these patterns in different scenarios. You’ll walk away with some knowledge, tips, and tricks that you’ll be able to use for new and existing applications.
View Video Transcript
0:00
Okay, so we'll be quick. My name is Joe Guadagno. I am what we call a Senior Director of Technology
0:07
I lead five teams of software developers here. A little bit about me
0:14
You can reach out to me many of these ways. J. Guadagno on Twitter, Joseph Guadagno Net on Facebook
0:21
Joseph Guadagno LinkedIn, my website jjg.me slash about jjg. And I used to stream. I don't stream much anymore, but you can at least go there and see some of the recordings
0:34
Enough about me. We're here to talk about patterns and practices with software architecture
0:43
The key to this talk or the key to this is really understanding that patterns exist all around us
0:54
Like Mahesh was mentioning, when you're architecting a building, there are certain patterns that are followed
1:00
The blueprints are done. Once the blueprint is there, there's generally a layout of the floor, layout of the walls
1:08
and inside the walls, the electrical, plumbing, et cetera, ventilation, and so on
1:15
These are patterns that exist in everything. When you build a car, a car generally has four wheels or two wheels
1:21
if it's a motorcycle, generally has windows, generally has a door, an engine, etc. You'll see
1:26
these patterns in software development a lot. I'm going to talk through some of them. Remember
1:32
patterns are there for one reason, so that you don't reinvent the wheel. And that's what this
1:39
talk is going to be about. I'm going to walk through and show you some patterns and practices
1:44
that I've seen over the years and that are pretty common. There's lots of books written on it
1:51
The most common one is known as the Gang of Four. Four software architects put together a list of the common patterns
2:00
You'll hear those scattered throughout. Now, as I talk about these patterns, these are things I've seen over time
2:09
No one is better than the other. They all have use cases where they shine, and some of them don't shine
2:18
So I'll talk to some of the pros and cons of each of them. And ultimately, it's up to you to decide what makes sense for your application
2:30
So let's talk about the first one, which is probably the most common that we've seen over time
2:35
And that's the layered multi-tier or commonly referred to back in the late 90s, early 2000s as the three-tiered application
2:48
Three-tiered application is basically separating out the responsibilities of the application into these three tiers
2:59
It could be more depending on how you architect the app, but the three tiers is the most common
3:05
You have your presentation tier, which could be your mobile application, your web application
3:11
It really depends on how you do it. but basically the presentation
3:16
This is what the user sees. And then there's the logic tier or service tier or manager tier
3:22
depending on the organization you're part of. And this is the intelligence on what to do
3:29
For a lot of these samples, I'm going to be talking about a fictitiously large company called Amazon
3:34
that does a lot of online orders. In this particular example, the logic tier
3:41
This is where you host things like how to place an order, how to ship an order, how to check the accounts, all that stuff, all that business intelligence
3:51
And then you have the data tier, and this is where you store it, your database back in that stores each of your clients or customers, all your orders, all your products
4:02
Now, the reason why you're doing this separation is so that one logic, one layer doesn't necessarily care about it
4:10
So if you're the web developer and you're building, let's say, Amazon.com, and you're looking for a list of products
4:18
you shouldn't have to care if the products are stored in a SQL database or an Oracle database or an AS400 or someone's floppy disk on someone's desk
4:32
hopefully it's not a floppy disk on someone's desk but uh either case you shouldn't care
4:40
and that's where the logic and the data tier comes in the logic says hey i want to list the products
4:46
that joe is going to be interested in logic layer says okay i know how to do that it goes and goes
4:54
down to the database tier and says hey give me a list of all these things and then it propagates
4:59
upwards in relationship to this diagram. Some of the advantages of this approach
5:06
You have a common thing that architects look to do, separation of concerns. Again
5:11
the presentation layer doesn't care about where the data is stored. You minimize the dependencies
5:16
I don't need to install a SQL client in my presentation here. I don't need to
5:21
care about how it's handled. Usually development is simpler because you can hire
5:30
a UI person for presentation. He doesn't necessarily need to know about database
5:36
a backend person for the logic tier. So he or she doesn't need to know about the UI
5:43
And it's reusable. This logic tier and database tier can be used over and over again. And the
5:48
mobile tier can just be written and customized for that one individual person. Some additions
5:56
or some disadvantages to this, the data model tends to move downward, meaning that
6:06
the presentation tier kind of dictates how the data is stored. If you're not doing this right
6:12
You end up just repeating the same stuff all the way throughout
6:18
Generally, more code is needed. And in a situation like Amazon.com, that makes sense because you want to have that separation and you have the different teams
6:28
But in a smaller app, it might not make sense for you to break out your app this way
6:35
But one of the things to keep in mind, your app might be small now. But as Mahesh was mentioning earlier, you want to plan for five to seven years
6:44
Let's say you build a small app just to keep track of, you know, the podcast you want
6:48
Because you are home by yourself for two years thanks to COVID. And you built a list to kind of cycle through all the podcasts
6:57
Oh, your friend heard about it. Your friend's friend heard about it. Your friend's friend heard about it
7:00
Now you have 1,000 users or 2,000 users. So you want to build for the future, but not over-architect things
7:10
So let's move on to the next layer, which is a common one, especially in the ASP world, the model view star
7:22
And the reason why there's a star here is there's slight variations of this
7:26
There is the model view controller, or MVC. That's a pattern that became popular in the .NET world
7:33
in the late 2000s, it's been popular in the Ruby world and pretty much every other software development
7:39
language world for a while. There's some variations like the model view presenter
7:44
or MVP or model view, view model model, which is MVVM in the old Silverlight days and WPF days
7:57
But essentially with this model, or with this pattern, you have the model that starts off in the upper part of this diagram
8:10
That model gets displayed to the view on the left-hand side or right-hand, depending on how the screen repeats
8:19
That view is responsible for showing the data, basically shows the model
8:24
That view is then presented to the user. The user interacts with that model and that view and then does something that goes to the controller
8:37
So in the case of the orders, let's just say we're displaying a list of orders
8:43
The user goes to Amazon.com. They want to see a list of products
8:49
The controller says here a list of the products It gives a list of models The view says okay I going to display these User gets a list and now I can go and add it to the cart
9:01
I click Add to Cart. It goes to the controller. It says, oh, this person wants to add it to the cart
9:07
I go and add it to the cart. I show a new cart or a new model with the cart information
9:13
which then goes to the view, and it's just this constant circle of back and forth and back and forth
9:18
So this has some advantages to it also, like, again, separation of concerns
9:24
You have your view. As long as there's a model design, you can have your UI handled by one set of people
9:31
Another set of people can handle the controller part of it. And then you have the user in between
9:39
with this model the presentation layer tends to be more usable because you can build components
9:48
for displaying a card or displaying a person or displaying a product that can be used in multiple
9:55
parts of the application and this allows for those specialized roles like you could have a
10:00
just someone that's good in the ui that doesn't really need any or a lot of programming experience
10:07
and someone that's good in the backend. This pattern doesn't work if you have full stack developers
10:18
you know, the person that knows how to do front end, back end and everything
10:23
because they tend to kind of blur everything together. Next part we're going to talk about is slightly more complicated
10:34
and that's the event driven. commonly referred to as event sourcing or the published subscribe model
10:44
So if we go back and look at that fictitional company called Amazon.com
10:51
when you go and place an order, there's a couple of things that happen
10:55
You have to charge the person's account, make sure that they can pay for it
11:00
You check the inventory to make sure it's there. Then you have to remove the inventory
11:04
Then you have to ship the package and update the order. Well, these things kind of sort of happen in parallel in some cases
11:13
In some cases, they're asynchronous. Fire off one, it does one thing while something else is happening
11:20
This is typically done through events. So if we look back at the previous example, person clicked, I want to order something
11:32
the website or the controller in this particular case says hey there is an order placed so now the
11:40
application has to go and fire this order place and says okay when an order is placed i know i
11:48
need to go and do this account charge i know i need to go the inventory check i know i know you
11:53
to deduct the inventory. Once all that's done, something else says, OK
12:00
this order is ready. And it fires off an event saying, hey, order is ready
12:05
Come look at it. And then there's something else that says, OK
12:09
I know what to do when there is an order ready. I'm going to ship the package
12:13
And then I'm going to update the order record. So this is, if you've been in the software development field
12:21
for a while, especially in the Microsoft field. This is very akin to Windows Forms development
12:28
If you've been building, you know, the old Battleship Gray Windows Form app
12:32
you drop the button on there, you double-click the button. That's an event
12:38
When someone clicks on that button, the button one underscore click event
12:42
that triggers an event. Windows itself is based on events. It looks for mouse moves
12:49
It looks for clicks. It looks for double clicks. It looks for key presses
12:54
It's a very common pattern, especially if your system is constantly changing and evolving
13:01
Let's say in my order place, I wanted to provide a discount for this person
13:10
Instead of updating the website, I can have something in the order place to say, hey
13:14
check this person's account to see if they ordered $1,000 worth of products
13:21
If they did, we're going to give them 10% off. So instead of updating the website with everything
13:26
you can update the order placed handler to be able to do that
13:33
There's lots of tools and frameworks that handle this for you. One of the most common ones now is Kafka
13:41
There's PAKA, A-K-K-A. There's Azure Event Grid. There's a lot of different event publish slash subscribe methods that allow you to do that
13:56
For Azure, you have Azure Messaging, Azure Service Bus, Azure Event Hubs
14:02
There's message queues, message topics in the AWS world. There's SNS, the Simple Notification Service, Simple Queue Service, and EventBridge
14:14
This one, it's commonly used for larger systems because you kind of fire it off and you let something else handle it
14:23
By the way, if there's any questions at any point, feel free to post them in the chat
14:28
As I go between slides, I'll try to answer them. The next pattern, which is CQRS, kind of delves into that a little bit more
14:41
It stands for Command, Query, Responsibility, and Segregation. It's a very long name, which is why you hear it as CQRS a lot
14:52
This builds upon the event-driven. So in this case, you basically have two sides
14:57
If you're looking at the graph, everything on the left side where it has command bus, command handler, the purple, blue, and event store, that's the command part
15:09
That's where the work happens. Like when you're ordering a product or shipping a product, that's handled there
15:19
The other side is the query responsibility section. And that's where, hey, I want to see my list of products
15:27
I want to see my list of orders. So in this scenario, you have something called commands
15:34
So similar to the MVC pattern, you say, hey, this person wants to order, this person wants to view the product
15:43
Those are considered commands a person or not necessarily a person. But a system will say, hey, I need to place an order
15:54
there's a command handler in there says oh i know how to handle orders let me go and take care of
16:01
that for you and then it goes and you know in the purple set section figures out domain models goes
16:07
to repository potentially saves off to the database and then throw stuff in this event bus which kind
16:13
of keeps uh allows for the querying to happen so the event bus will store things like hey
16:24
this order was there. And that allows you later on when you're going through, let's say
16:29
Amazon.com and checking on your orders to query that. It goes through a separate system that
16:34
has just the data part. So it doesn't, you don't have to worry about mixing your business part
16:41
which is on this side and your data part, which is on that side. Some of the advantages of this
16:49
pattern is that it handles complex systems very easily because you're just putting new command
17:00
handlers. Once you get the infrastructure set, you don't have to worry about it. You just add more
17:05
command handlers to it, and then everything else kind of takes care of itself
17:10
It could help with performance because you're separating your queries from your real-time orders or real-time user interaction, which could help speed up databases and so on
17:27
Security could be easier also because, again, you're separating those concerns out
17:33
Some of the disadvantages is it's kind of overkill for your basic cred app
17:41
So if you're just building like a contact example, first name, last name, et cetera
17:46
might be a bit overkill for that One of the other challenges with this one is your data can become stale at some point because there are so many steps involved
18:00
When you're putting in an order, it might not necessarily be available on the other side to query right away
18:08
Same thing with like if you're using Twitter or Facebook, when you go and like a post or heart a tweet
18:16
It doesn't update right away. You may see it on your machine in real time
18:23
but it has to go back and go over into the event bus
18:27
and then back up to the query system to be able to be there. Data is also a challenge or data synchronization
18:35
between the two different quote-unquote sides, but you can handle that, or there's lots of patterns to handle that
18:43
A common pattern or a common tool to help with this in the .NET world is EndService
18:51
It allows you to implement this pattern. Then there's a pattern that builds upon both of these, which is called the CQRS Plus Event Sourcing Pattern
19:04
Now, if you look at this one, it's very same, with the exception of I flipped the diagram for it
19:12
Instead of everything being on the top, it's now reversed. This pattern is very similar
19:18
The only difference is the top middle where you see an event bus and lots of command handlers
19:25
So this allows everything to come through one centralized area. and then depending on whether or not you're querying or commanding
19:36
or wanting to do extra stuff or non-query stuff, that gets handled by this cloud thing that kind of figures out where
19:48
And then there's an event bus in the middle that kind of does all the traffic navigation
19:53
between the different places to store data. And this is a rather complex system, so you don't see it too often in the while
20:04
But sometimes the event-driven and CQRS systems get combined. Next one up is the plugin model
20:18
So this you see in a lot of desktop applications. The plugin model basically allows you to build an ecosystem in your application that can inject or ingest other functionalities
20:36
So a common way to look at it is if you're using Visual Studio. Everything in Visual Studio is a plugin
20:45
Visual Studio itself is just an empty shell. But then you add in ASP.NET, and that adds in certain editors and certain build tasks
20:56
If you add in products like JetBrains Resharper, that gets added into the event
21:05
If you're using Microsoft Office or Microsoft Excel, those have plug-in models to allow you to generate WordArt or query a database
21:16
Those are all plug-ins. So the plug-in or microkernel allows you to do just that
21:24
If you look at the screenshot, you have your application in the middle
21:29
And I apologize for the scaling on my screen. Application and component is one word
21:39
The application in our example for Amazon has different plug-in components. So it knows that there is something that handles shipping, something that handles order, something that handles inventory and something that handles account
21:54
This is generally used for applications where you want flexibility or you don't understand the entire model or the entire user base that's going to be using the application
22:12
I've used this pattern in the past to build out things like a task scheduler saying, hey, I'm going to run a job
22:21
I'm going to build this scheduler that just looks for jobs to run
22:26
And then you can build these jobs as plugins to say, OK, at one o'clock, I want you to execute that
22:33
Windows task scheduler has something like that. or I want to run this TPS report at 4 55 PM every Friday
22:44
You can have, if you have a plugin architecture, you can just add that job as an item
22:52
It's not that useful in like the scenarios where we've been thinking about
22:57
the amazon.com, but it makes sense when you're doing it for long running jobs or something
23:06
that is relatively repeatable. Workflows are a good example of this. You want to add in additional
23:13
steps for a workflow or additional pieces to a workflow. Having a plugin architecture
23:19
is a good way of doing that. next one up is the buzzwords of
23:31
is uh oh actually before that i'll address mahesh's comment or comments joe cqrs events
23:41
how difficult is it to implement without a cloud service like azure very very difficult
23:48
in most cases for that you need something like Azure, AWS, or Google Cloud only because
23:57
they have the infrastructure in place for things like the event grid, event buses
24:05
and the ability. You don't want that or I mean you can but that's a lot harder to do in your own
24:11
infrastructure because of the resiliency that's needed as well as the just the cost of having the
24:20
number of service servers services available the uptime the guaranteed delivery all that stuff
24:28
it's very challenging to have on your own highly not recommended to do it by yourself but use other
24:38
services. Thanks for the question, Mahesh. Let's go back to the service-oriented slide, Simon
24:50
please. Thank you. Service-oriented or SOA or micro-services, the bane of many architects
25:00
existence for five or ten years in the early 2000s. This was everything. We have to take our
25:09
monoliths and break it down into a zillion different web services. And that's what the
25:14
common pattern was. Or that's what the common implementation was. Take a big app and break it
25:23
But that's not really the pattern for SOA or service-oriented architecture. The idea is to get away from this one big app of owning everything
25:34
So you can think, my hand. My hand does one function, but individually, there are lots of pieces
25:41
There's fingers to it. There's the palm. There's, you know, the muscles in there
25:47
Separate all those out into their own specialties. So we go with our Amazon.com example, and you have this main page, Amazon.com
25:58
Then there is a series of services behind it. There's the account service
26:03
There's the inventory service. There's the shipping service. There's the order service
26:07
So Amazon.com doesn't have all that logic inside of that page. If you source on it, you're not going to see how they go and handle accounts, how they go and handle inventories, how they go and handle shipping
26:21
You might see some URLs where they go back out to the account service to say, hey, who's this person
26:28
Goes out to the inventory service to check on this product. And then behind the scenes, when you're ordering, it's going to go and do the shipping and the order
26:37
So the idea is to take your applications and start separating out your concerns And you not just doing it to separate it out You doing it for two reasons or maybe three One is reusability Your account service inventory service shipping service
26:53
can be reused over in different places. Maybe you're going to white box your amazon.com and
27:02
you're going to provide the shipping service level because everyone knows Amazon's really good
27:06
at shipping, or at least in the U.S. they are. Maybe Amazon wants to make that a service so you
27:12
can use Amazon shipping services as opposed to UPS or FedEx, or you want them to be able to track
27:22
your inventory. As you start breaking those things down in services, you have that flexibility
27:28
some of the advantages you can break down not only you're breaking down your code but you're
27:37
breaking down your development into more i don't say siloed but more individual aspects
27:44
so you can have a whole team dedicated to inventory that can work with your team
27:51
with your business partners that handle the inventory. You can also work directly with your shipping services
28:01
So if you're building amazon.com and you have to work on the shipping piece
28:05
you don't have to know the details of UPS or local carriers or Federal Express or DHL
28:13
But you can have a team that specializes in that and they just work on that
28:21
Also allows for vendor diversity. So if we go back to that shipping service, I can add in one, two, 15 different shipping services
28:32
Let's say originally I'm only the post office, so I can write a shipping service that goes
28:39
to the post office. But then I start getting big enough and I realize, well, some people want next day
28:43
So maybe I need to look at Federal Express or FedEx. So I can incorporate that into my shipping service
28:52
And the Acme widgets doesn't care. It gets a list of who the service, which places I can ship it to
28:59
And the shipping service figures out how to do that. And it works well with agile delivery practices
29:09
So you have the, it's a lot easier, or I would say easier
29:12
But when you're separating out the development into these different services, you can have different teams working on it or different focuses to work on them
29:24
That's why you see this one common. Next one up is the microservice pattern, which is kind of a deviation of the service-oriented pattern
29:41
And this one's a little bit hard to see, but if you look at the slides, you can go to my website and get the slides for this
29:50
See, we have a lot of different patterns here. The ambassador anti-corruption, back-end for front-end, bulkhead, et cetera
29:57
These are all subsets. So if you take that general microservice, like the shipping service, this is how you can actually implement that microservice, not microservice
30:09
The ambassador pattern is used to offload common client tasks, such as monitoring, logging, debugging, et cetera
30:18
Let's see. Oops, I went too far back. Sorry. I was trying to see if I can highlight it
30:25
That's kind of like the first block in the gateway. The anti-corruption layer is used towards the back part of it
30:35
And this makes sure that you, if you're doing legacy systems, like if, let's say we had the shipping service and we had our own custom built one, but then we started integrating with the FedEx one
30:48
This makes sure that the data stays in between. The backends for frontends or BFFs, which doesn't stand for us forever for those of you who were born in the 80s like I was
31:00
this is basically a separate back end that's written just for the front end what i mean by that
31:10
is it deals with the translation between any of the services that you may be using and the website
31:20
So the bulkhead pattern, that handles all the interop stuff, so memory, databases, interops, networking
31:35
So that's basically if you're using something like Azure or AWS, the bulkhead pattern, they're handling all that for you
31:41
Three different gateway pieces. Aggregation kind of takes all the requests and response and eliminates the chattiness
31:53
So you get one request. You may have like four or five responses. It takes them all together and sends them back as one
32:00
The offloading kind of handles the load balancing between them. The routing handles the multiple requests
32:10
So if you say I want shipping, it knows to send it off to this one. If you want the order service, it knows to ship it off to that one
32:20
The sidecar pattern helps with or provides helper components for your container
32:29
so that it allows you to call other things that may not be available in the main client, so to speak
32:38
And last one, the strangler pattern, this is used, again, similar to the gateway pattern
32:47
This is used when you're in the process of migrating from, let's say, a legacy service to a new service
32:56
So if we go back to that shipping example, in the past, we're just using the U.S. Post Office for shipping
33:06
and now we started adding things like Federal Express, UPS, et cetera
33:12
the strangler pattern could be that in between they say, okay, for those that just used the UPS or our old legacy service
33:22
it's going to go there while new ones are going to go to the new server
33:28
So the strangler pattern kind of handles that. this pattern also lends itself to the common pattern the serverless pattern or the cloud or the
33:42
better yet not on my pc pattern so these are and the reason why this is a pattern and not
33:50
like software as a service because this is a chosen way to implement things like i was
33:57
mentioning with CQRS, you can choose to implement things yourself. You can also choose to use a
34:03
third party to implement them like Azure, AWS. For this example, we're using StreamYard. We're
34:10
using a service to broadcast this out on all the different channels because, you know, why bother
34:17
having all that infrastructure to do it when someone else can do it? That's kind of what the
34:22
serverless does allows you to host things like websites and notifications and databases so you
34:31
don't have to worry about all that work and you can focus on you know your business model
34:37
so all these things together kind of are oh that's not good it's weird that the
34:49
that picture was there. Basically, what I showed you is a toolbox of different tools
34:57
There's the whole, if you have a hammer, you tend to see every problem as a nail
35:05
Just because you know MVC or the CQRS pattern or the event-driven pattern doesn't mean everything
35:16
should fit in that. They all have their pros and cons. Some make sense for some software development patterns
35:23
Others make sense for others. So hopefully I've given you enough in this brief 40-some-odd minute presentation as to
35:33
which patterns to use. That being said, I'm going to open up the next five minutes for questions and see if
35:41
anyone has any
#Business & Industrial
#Data Management
#Distributed & Cloud Computing
#Programming
#Software
#Software Utilities