Skip to main content

Webinar recording

Change your architecture during deployment

“Every microservice needs to be independently deployable.”
Let’s verify if this is true and if we can bend or break the rules during deployment.

🔗Why attend?

Many systems start with diagrams of boxes and arrows and the promise of high consistency and low coupling. The boxes are supposed to be loosely coupled components, but each arrow often results in a highly coupled dependency at runtime. What if we can do something about it… during deployment?

In this webinar, we’ll identify design decisions that influence your system’s behavior both at design-time and run-time. We’ll observe how changing your design during deployment gives you many opportunities for making trade-offs to improve function and performance and gives you the information you need to shape your system architecture.

🔗In this webinar you’ll learn about:

  • Various architectural views
  • Composing a user interface with data from multiple services
  • How there are no solutions; only trade-offs
  • Data ownership of services

🔗Transcription

00:03 David Boike
Hello again everyone, and thanks for joining us for another particular live webinar. This is David Boike. Today I'm joined by my colleague and solution architect, Dennis van der Stelt, who's going to talk to us about how we can change our software architecture even during deployment. Just a quick note before we begin, please use the Q and A feature to ask any questions you may have during today's live webinar, and we'll be sure to address them at the end of the presentation. We'll follow up offline to answer all the questions we won't be able to answer live. We're also recording the webinar and everyone will receive a link to the recording via email. Let's talk about changing our architecture during deployment. Welcome, Dennis.
00:42 Dennis van der Stelt
Thank you very much, David. Well, I'm Dennis and I'm going to do this presentation about how to change your architecture during deployment and if that's possible at all, and what it means to do that.
00:58 Dennis van der Stelt
First, I am quite interested, and we're not going to do another poll, but who read this article from Amazon where Prime was using microservices and decided to move back to a monolith where they could scale infinitely and reduce the cost by 90%. You can imagine this article caused quite a stir on the internet, and I'll get back to the article a little bit later, but it's setting the tone of this presentation, especially the responses to it. Because some were even saying that Amazon itself, kneecap serverless and lambdas, and those aren't my words. It was one of the perspectives of one of the articles, and that's what I want to dive into more, the different perspectives because there are different ways of looking at solutions, at architecture, at different architectural styles.
01:57 Dennis van der Stelt
And just because one person is looking at it from one angle and possibly goes into conversation with someone else, doesn't mean that any of them is wrong. They might have different experiences, but they also might have a different way of looking at architecture. And I want to dive into that a little bit more. For example, when I was creating this presentation, I was reminded of something that happened quite some time ago when my oldest daughter was very young and she was starting to learn how to read. And she suddenly, when we were at the dinner table and there was milk on the dinner table, and suddenly she said like, "Oh, it's not milik, but milk because she could finally read milk and milek or melek in Dutch is how we pronounce it. Basically with, what is it, an accent or whatever you want to call it.
02:53 Dennis van der Stelt
And it was pretty surprising to us that she had this different view on language until she could finally read. And there are more examples of this. I went on a trip sometime ago to the beautiful Scotland and the capital of Scotland is on the map with the biggest font, the biggest characters, and I don't know if you know how to pronounce it, but to me, especially as being Dutch, I thought it was Edinburgh, but apparently you pronounce it like Edin-bra. Also, what they pour there, what they create and make there a lot is whiskey. And apparently there are difference on how you spell whiskey, how you drink whiskey, et cetera. So for example, whisky is often what it's called in Scotland and whiskey with an E is more like the American version of it. There's drinking it neat, there's drinking it on the rocks.
03:53 Dennis van der Stelt
Bourbon is apparently the American whiskey and scotch is, well, this scotch is whiskey. So you can see that there are just on a single drink, many different perspectives and I just wanted to use that as an example. Anyway, I had a lot of fun on the trip. So here you can see what I look like. If you didn't know yet. I had a great whiskey at the Aberfeldy Brewery at distillery cask strength. The thing is, I don't know if you know who Marcus Aurelius is, he was an emperor in the Roman Empire and he already said it. It's like everything we hear is an opinion and not a fact, and especially everything we see is perspective and not the truth. And the same goes for when we look at microservices for example, there are many people at presentations talking about microservices or talking about services and what are the difference between those and also implementing services in many different ways.
04:59 Dennis van der Stelt
And as we saw in the Amazon Prime example, they started out using microservices and serverless and eventually they thought it was a bad idea because they couldn't scale anymore and had additional issues. And there are two people in the slide here that both talk about services. One might mention services and the other microservices, but the size of services and microservices is also pretty important. And more so when we talk about logical services and for example, you see many different small blocks, those could be services or microservices. And you see the dotted lines, that could be basically the boundary of your services or your microservices, but oftentimes it's not really clear how small or large they are, and that's why we need to be a little bit more descriptive, et cetera. And a good example of an architecture is this picture which I got from the internet.
06:03 Dennis van der Stelt
And here you can see many different styles of arrows, quite a few technologies. And for example, over here it says that this is a bunch of APIs, this is as well a bunch of APIs, but here there's like a dotted line to an Azure key vault and a fixed line to Azure service bus. And even though this is a bunch of things that compose the API, on the left side, there's more, but here you can see URLs, which means something completely different. This isn't like a composed thing that makes up our API or APIs, but this is probably a single website. And you can see here that there are different technologies. You can see that this website apparently calls the API here, but the same arrows can be seen here. So it looks like the Azure DNS is calling the Azure CDN. And then the Azure CDN is calling those websites are something.
07:13 Dennis van der Stelt
And there's more, there's at the bottom, there's GitHub, which might fit somewhere in an architectural diagram, but this just contains so much and it's not clear here from this diagram. If one thing calls the other thing or if one thing has a dependency on another thing and how they're used, et cetera. So this is quite confusing and there are ways to present architectural and software diagrams in a different way. For example, the one by Simon Brown, he calls this the C4 model, and he basically says that you should start from a very high level. And as an example, I've added maps of the place where I live. I live in the Netherlands, and at the bottom you can see for example here, whoops, sorry, this picture that shows very high level components and that there's dependencies or communication between them. And then the next picture is more zoomed in.
08:24 Dennis van der Stelt
And you can see that the red block over here, and I'll change this into a laser point so it's clearer, is now split up into multiple other things. And in the next one we zoom in even further and then the thing on top here disappeared. But there's more detail in all the red blocks. And then finally, but you could say like we end up in street view, we end up with a UML diagram where it's much more descriptive about what our code looks like. This is the C4 model. I don't want to discuss this more, but it's good to know that it's there. And as an example of how we can visualize our software architecture and dive deeper into details, and no matter how many pictures you use, it's probably always wise and hopefully obvious that you also need some text to describe what you can see.
09:21 Dennis van der Stelt
Another one is a little bit older. It's from 1995 from Philip Kruchten who was working at Rational at the time from the rational unified process. He created a four plus one architectural view model where in the middle you can see scenarios, which is basically all the functionality you want to build. So use cases or in scrim, post-it notes or whatever. And then there's four views, four ways to look at your architecture. There's the logical view which explains more from a high level how the system is structured and the process view shows more about the dependencies and the communication between all the services or components. And then there's the development view. And you could say that this is a view of your Visual Studio or jet bearings rider or whatever tool you are using, possibly your source control repositories, but it's like a very technical view.
10:22 Dennis van der Stelt
And then there's the physical view, and this shows the stuff you created, how it's deployed. So looking at a little bit better at it, this could be an example of the logical view. So you see different services here, we have no idea how big these services are. We just know that there are a couple of services that have a dependency or communicate with each other. And the process view could be, for example, a state diagram or in this example I'm using a sequence diagram. There are multiple potential views or diagrams rather that you can use in each view, but this is just an example. And because this is a particular software, I wanted to include this. If you're doing messaging and using message SKUs, then for example, service insight can be very helpful inside this view where it can visualize literally the entire message flow between all your components or endpoints or whatever you call them.
11:29 Dennis van der Stelt
So you can see failed messages, you can see the entire order. And this is basically somewhat of a live view of the messages that went through your system. So it's very easy to see what's going on, how long things took, and for example, if something went wrong, like you expect some message to be sent out, but it's not. You can look at the payload and so on. The development view doesn't just include your favorite code, IDE, but also for example, more details about the fact that there's data storage where the data is stored. So for example, you can here go into detail on we're using a relational database or a SQL server. You can see for the blocks again, like orders and products and inventory and the fact that there's maybe a web API on top of it, or if you want to, you can include details about the gateway if you want to use that.
12:31 Dennis van der Stelt
But like I said, it could be that there are the source codes, the project structure or perhaps that there are git repositories, et cetera, stuff like that. And then the physical view is the last view, and that shows you how stuff is hosted. So for example, you could include, if you want to, a reversed proxy here or that there are three databases on a single SQL server instance and that the web server A and B has been load balanced and that are two instances of your website or running on two physical servers or wherever, that you're using Kubernetes, et cetera. So these are the possible views.
13:17 Dennis van der Stelt
And here you can see the logical and the physical view next to each other. So on the left we had those five components. And on the right you can see the physical view and this I want to do a few times more to see how we can compare the logical and the physical view because this is where basically you take the logical view and then create code, et cetera. And at some point deploy, and I want to use some examples there on how you can change your architecture basically from the logical to the physical view.
13:55 Dennis van der Stelt
And since everyone is still talking a lot about microservices, it's a good example to use microservices to see how they can change. I copied some random lists from a random website and modified it a little bit, but basically a lot of the websites say stuff like this. Now the first thing is a maximum of 30 lines of code. That's an interesting one because that was one of the first rules of microservices. They had to be small and how small they were was represented in number of lines of code. Now, pretty soon that constraint or a rule was basically dropped because people thought it wasn't useful at all. But now how big your microservices should be is still not very clear in a lot of cases. Another thing is highly maintainable and testable. I don't know who builds microservices and things. Now finally, my microservices are highly maintainable and testable, but I've always wanted this way before we started building microservices and just stating this as a rule doesn't mean microservices automatically become highly maintainable.
15:13 Dennis van der Stelt
So I think this is a bit weird. And I also wanted this with serverless, I want this with service oriented architecture or a layer architecture. And the same goes for loosely coupled. Just because it's stated here doesn't automatically mean your microservices are loosely coupled. And I'll get back to this a bit later. And this one is especially an interesting, a database per microservice. This is more concrete. This is something we can understand and I want to dive into this a little bit. So on the left we have our logical view again, and on the right, our physical view. And on the left I have these, what are they, purple pinkish things at the bottom, they are basically saying that there's an intent for a data store. So these components need to store some business data, some orders, products, et cetera that can be used in our website.
16:13 Dennis van der Stelt
But the logical view isn't saying anything about technical requirements yet. So we don't know if this will be Cosmos DB or SQL or some other no SQL database or maybe we can even theoretically store stuff in memory. Now in the physical view, we can see that we're hosting our components via docker containers. And although it doesn't say here, this icon or graphic is basically accepted as being a relational database. It can also be something else. But let's say there's a document that says this is stored inside SQL server. And this block could theoretically mean there's a single server and there's probably a SQL Server instance running on it.
17:05 Dennis van der Stelt
And the SQL server instance has three databases. The thing here at the bottom is basically just schema. And eventually there will be data obviously stored in it, but how the database is represented in the development and in the physical view is basically nothing more than schema and some data in it. So if that's just schema and some data in the schema, would it be possible to have everything inside a single database? So not three databases inside a single SQL server instance, but literally one SQL server database instance and have all the schema inside that single database.
18:09 Dennis van der Stelt
Does the logical view change? Because the data ownership of these logical things, it's not about how the data is hosted, but more about how we designed it initially. So for example, on the left, I tried to copy over the object explorer, and you could see here at the top that this is literally the SQL server and there are a couple of databases, the orders database, the product database and the inventory and each have their own tables. So this is the original view I started out with, but when I combine them, now I can have all tables inside a single database called Retail shop. And the question is, does this change our logical view because would now be the orders component suddenly be able to access information about products? Because literally if we are using DEPA or Entity Framework or whatever thing we're using to access our data via code, in code and in our logical view, there's no way that orders can access the products data.
19:29 Dennis van der Stelt
So even if we deployed everything together inside a single database, that doesn't mean that our logical view changed in any way. This is about data ownership and not about how we physically deploy stuff. Now, there's another part where a lot of people worry about we might query data over the different databases. This is the next view where orders suddenly has access to the products database. This is something entirely different. Like we could, for example, have some business intelligence environment where we can pull data from every single database and store it in data warehouse and in cubes, and then you can start building intelligence reports over it. That's something else. There's no one saying that if logical architecture or your logical view looks like this, that you can't do that with business intelligence. The problem is when suddenly your orders component can access the products database because then the physical view changed.
20:39 Dennis van der Stelt
But we should also change the logical view because if we make this possible, then in the logical view, orders can also access the products data store. And that's something we definitely don't want to do because then we share databases and we run into a whole lot of problems because then products can't change the schema over here and over here of the products database because then orders and inventory can possibly stop working because suddenly the data or the schema changed and it's no longer able to access this data. And that's when you start to introduce a lot of coupling. So this is definitely something we don't want.
21:28 Dennis van der Stelt
Obviously we're way smarter than that. Our services never share databases because we built a web API, and I draw it here for clarity at the bottom. Normally you would probably do that at the top and the arrows would go like this, but for clarity, I've did it here and now via some web API, we can still access the data, but we no longer share databases between those products. But did we actually change something? Does the logical architecture change if we do this? I think it does. I think we get the same result as we previously had when we shared databases because I don't think sharing the database itself is a problem. It's the fact that we have introduced coupling on data that's from another service.
22:23 Dennis van der Stelt
And so if we do that via web API abstraction, we have end up with the same result. So here we can see the physical view where we shared databases, and here the physical view where we didn't share database, but we still shared data via web APIs. And I hear a lot of the times that the left part is a bad practice and the right part is a good practice. I'm just saying that the logical view with the dependencies on the data and each other's data store and each other's information and business data is the same. In other words, a bad practice is to share data via SQL API, but a good practice is to share data via web API. And I don't really understand why a web API, which is just a different technology is different because our logical view is basically for both the same.
23:26 Dennis van der Stelt
We share the data and I don't know how that can ever improve that we use a different technology to retrieve the data, how that improves the data ownership. Now, if you want to learn more about this, I did another presentation and this one, it was amongst others recorded at NDC conference called Autonomous microservices, Don't share data. I advise you if you want to learn more about the data ownership and sharing data between services, you watch that. So as a result, because if you do share, I think you'll eventually look at your system or your software architecture like this. And in that presentation and many others, it's explained how you can try and prevent that. I'll get back to that a little bit later. So we talked about databases per microservices. How about independently deployable microservices? So remember, we have our logical development and physical view, and we just decided, and I hope you agree with me, but I'll probably hear that later in the questions, that we can deploy our schema and data inside a single database.
24:44 Dennis van der Stelt
The question is, can't we do the same for our containers? If we build components, orders, products and inventory, would it be possible to host all of them inside a single container? Would that change our logical view or even better includes the website and host everything inside a single container? Now, I know what some people are thinking. This will decrease the possibility to scale out horizontally because for example, if orders is a component or a service that's extremely busy, I want to separate that from products, inventory and the website. But that's still possible because our logical view says that it should be developed completely different. Now, we might have to make some changes into our code, maybe in our deployment thing where we suddenly package everything up inside a unique container, we might change something there, but the logical view doesn't really change. We only change how we package everything and how we deploy everything.
26:00 Dennis van der Stelt
But would it be possible to suddenly host our entire system inside a single container, just as an example? Well, if we look back at the article where they moved from microservices to a monolith, what they said was our initial solution was a distributed system with serverless components. And in theory, they thought they could scale each service independently. Exactly what I said. I hear that some people are saying, shouldn't we be able to scale each component independently? However, the Amazon Prime team hit a hard scaling limit at about 5% of what they needed, and then they moved everything, all components into a single process.
26:56 Dennis van der Stelt
Conceptually, they said the high level architecture remained the same. In other words, the logical view remained exactly the same, but they solved a scaling problem where Prime Video thought each individual microservice could scale independently and they ran into major issues. They combined everything and suddenly they were able to scale much, much, much better. So if we say microservices and independently deployable microservices allow us to scale better, that's not always the case. And Prime Video basically proved that. So why did Amazon Prime chains? There are some theories. There are some perspectives. Warner Vogels works at AWS. I don't know if you know him. He's quite a big name. They said they just evolved their software architecture. This is a strategy. You should revisit your architecture from time to time and look at it with an open mind. So not stick too much to a certain technology or architectural style, but revisit it from time to time.
28:11 Dennis van der Stelt
And that's exactly what Prime did. And this is Adrian Cockcroft. He also works at AWS and he also said microservices were oversold as a solution to everything, and then he said something that I found very interesting, by vendors who wanted to sell Kubernetes. I'm not going to state an opinion there, but take from that whatever you want. As an example, we have a particular software discussion forum, a discussion platform where people can all ask all kinds of questions, not just about end service, but also about other technologies. So someone asked a question, can someone explain Dapr and tell me what you see as the improvements and whatnot? And I tried to provide an answer and the person responded with, I think Dapr is much more than what I said in the response. And he said, Dapr is the way to go. And that basically cost me to include that remark in this presentation because I might have an opinion about Dapr.
29:23 Dennis van der Stelt
But you know what we said about opinions and facts? The thing is Dapr is the way to go is by default not true because there are no solutions, there are only trade-offs. And that's what you have to do if you are looking for the right technology, the right software, architectural style, et cetera, is see what are the trade-offs between option one, two, and three and then select the one where the trade-offs are the most acceptable. But every technology and every choice has pros and cons. So please have a look at those.
30:01 Dennis van der Stelt
But I want to dive a little bit deeper into data ownership in the user interface as I promised. So we looked at the difference between the logical and the physical view, yet, I wanted to represent it a little bit differently with co because I don't want people to get hung up on names and everything. Imagine there are just some APIs, some components, some services, whatever you want to call them. There's the blue, yellow and purple one. Here you can see the logical and here you can see, on the right, physical view, and I added a website here which isn't represented here. And I maybe show you later why not. But the website is not that important at the moment.
30:49 Dennis van der Stelt
The thing is, on the left, the boundaries are logical. So if you can want to decide that the yellow stuff can't communicate with the purple and the blue stuff, then the yellow stuff should never have a dependency on one of the others. You can never completely remove that. And we've written some articles on our web block about how to do this and how to minimize the coupling, but if you completely remove it, you don't have a system, you just have independent components that don't do anything with each other. But I won't go into how you minimize them to the max, but there's an article, Put Your Event On The Diet, for example, which is very interesting. On the right there are physical boundaries, so most of the image might look the same, but the boundary here could be a boundary where it says like, this is running inside a docker container or this is running on a VM and it can't just communicate with something else.
31:57 Dennis van der Stelt
It could even mean this is all running in process and the other stuff is running inside its own process. So it definitely needs some more explanation with words on what each boundary or each dotted line and everything means. But for the presentation, that doesn't mean. However, what we do and what is interesting is that if we minimize the sharing of data between those components, there are still some composition because we need to combine the data in the website to make it visible to the end user. If the blue thing has knowledge about some data and the yellow thing about something else, in the end, we need to bring it back into the user interface. And here's an example of something I made for the Amazon website. You can see here a great book by Martin Fowler, but you can imagine, and here I'm giving it names again, maybe I shouldn't have, but that the product catalog knows the information about the title and the cover of the book.
33:05 Dennis van der Stelt
And there are several other services that know about the rating of a book and how well it's received, another one about how many books there are in stock, another one, what the price is. And you can see that we compose the user interface and the data inside the user interface from all those cohort blocks. So if we go back to this, I represented that now over here, so each block is some HTML and some data belonging to the things below. And it's probably better to represent it like this because now you see that there are still these columns or vertical slices or whatever you want to call them, that here the boundary looks completely different because the data cannot cross over to the other side. But here you can see that there's a boundary where this is running inside one thing, and this is running inside one thing, but over here it's in the website and we compost everything together.
34:10 Dennis van der Stelt
And I'll represent that here as well for later. And sometimes we want to introduce a gateway. That could be for several reasons, for example, we might want to limit the launch about APIs in the backend from our website. We might need a gateway to not expose our full backend API to the outside world. We even could use a BFF, which doesn't mean what a lot of, well, what my kids think, but it's a backend for front end, which basically means if you have a website, if you have an API and you have a mobile app, these each could have their own gateway are their own backend for front end, which is optimized for it.
34:55 Dennis van der Stelt
In asp.net, we compose a view model and then the razor views map data from the view model onto the HTML or onto the razor views. And that's what I want to dive in a little bit because if we do that, if we introduce a gateway that knows how to compose the view mobile, knows how to compose the data so that the HTML and everything can be rendered and understand. If that gateway knows, I'm on this page where I need to show the shopping cart, then there's massive coupling because suddenly the gateway knows where to make calls into APIs in the blue, yellow and purple things.
35:45 Dennis van der Stelt
And we want to prevent that there's suddenly massive coupling over here, and that's what the composition gateway comes in or the view model composition gateway. And I want to show that quickly inside Visual Studio so that we can have some code. You can see here on the left that I created a project. This is basically a web API, and the only thing that's in here is the startup of CS, where I mark at view model composition, which sets up asp.net for the view model composition stuff. And here I say map composition handlers. And I'm not going to go into what everything does because that's taking up way too much time. But here you can see, for example, you could think of this as the blue thing, and this as the yellow thing, and here is an API, but this is just another API thing.
36:47 Dennis van der Stelt
So I have some controllers here which are executed on an HTTP gate, but these are the APIs that the gateway should call. So in a minute, I'm going to use Postman, a tool to make HTTP calls. And I'm not going to call the API over here and the API over here, but I'm going to call this composition gateway, but I'll show you what comes out of these APIs over here and here. But basically this thing is an API and it doesn't contain any codes to call shipping and sales because if all the codes that would have knowledge about when to call the shipping API and the sales API would be in the composition gateway, that would mean there's massive coupling over here. Instead, each of these cohort things that I showed on the slide have this thing, view model composition.
37:48 Dennis van der Stelt
There's one over here, and I want to have a look at the order details over here and here order details as well. So the idea is that when order details is called that the orders is retrieved. And you can see this is the URL where I'm going to call this thing in a minute, and it's exactly the same for this order details, fuel modal append in sales. It's the exact URL, except that this one uses the API from shipments specifically. And this thing is calling it from orders specifically. Now what happens is there's this interface, I composition request handler, and if we have a look at it, we can see there's a handle method where an HTTP request is coming in. And you can see here that I'm retrieving from the request, and this is what the composition gateway adds. We request the view model and we add the details, which we know inside our sales append, we add the order number and the items count.
39:06 Dennis van der Stelt
And over here we add the shipment status and who the courier is for this shipment. And we combine the data, put everything in the view model, and then the composition gateway basically scans all the classes that implement this thing. And then based on the URL, it'll execute this handle method. So I can build tons and tons of these handle methods for different URLs. Now, I'll show you what this looks like by running this. And yes, I've got it set to composition gateway. So there are three projects started. The shipping API, the sales API, and the composition gateway. You can see this is at 4457. Now, if I go to Postman, this is the sales API, and if I execute this, it'll just have knowledge about the order number and the items count. Shipping will just have knowledge about the order number, the courier and the status.
40:12 Dennis van der Stelt
But if I now execute 4457, that's literally the project in Jet Brains Rider or Visual Studio that had almost zero lines of code. It's just to set up the web API and to set up the composition. If I sent that over here, now it added everything into the output. So another example, here I request with page size and page index, an entire page. So there's a lot of data coming on from the sales side, and I won't show the shipping side because it's not that interesting. But if I now show the order list, you can see that suddenly the details for order number and the number of items that were ordered, the shipping status and shipping courier was also added. So if I go back to the composition gateway and stop this, I can go into my other demo, but I don't have the web API composition gateway, but this is all exactly the same, but I now moved it into a website.
41:24 Dennis van der Stelt
There's the same startup stuff except we now have to map some controllers. But here it's again, except the API is a little bit different for a website, it now says Enable composition over controllers as an option for the add view model composition. And here I say map the composition handlers. And if we now go look, the home controller is very, very simple. It just responds back this and the orders controller here, you can see that it's literally empty. So there's literally no code. But again, the assemblies from shipping and sales, so that's what I didn't tell yet. But these two projects, when you deploy your entire system, you could for example, create new gate packages for the view model composition from sales and view model composition for shipping, which contains all the knowledge, but still within this colored box. This can know everything about shipping data.
42:32 Dennis van der Stelt
And over here, everything here can know everything about sales data, but potentially not share it. We deploy this one and this one together with the website. And because I don't have a deployment pipeline, what I did here is I literally added references. So I know that the assemblies, the DLLs will be copied with the website, and then what will happen is because I entered this, then the view model composition gateway will scan assemblies in that folder, find this interface or all types that implement this interface and then know, based on the URL, which one to execute. So if I execute this and I showed you that the controllers were literally 100% empty, and then it should start up this thing. And I should probably do it like this, you can see that even though the controllers were completely empty, it's just the returning the laser views.
43:45 Dennis van der Stelt
However, we still know there are three orders, and if I click one of them, it says it's delivered and it was delivered by FedEx, the number of items. So the controllers don't retrieve the data, it's just the composition gateway. So what we changed is we don't have this gateway with massive coupling. Instead, we have a composition gateway, and I'll change here into a laser pointer again. We now have a composition gateway. The composition gateway is also part of our logical view. I just displayed it over here because I want to make sure that there's no, how do you say it, dependency between the composition gateway and any of these color blocks. And now I'm lying because the composition gateway defined the interface, and I already forgot what it was called. This thing I composition, the request handler is defined inside this thing. And here I showing the appenders and the appenders have a dependency on this interface, but that's it.
44:57 Dennis van der Stelt
The composition, that gateway has zero knowledge about any appenders, just about its own interface. And if we start deploying that over here, we can see that we deploy these appenders together with the composition gateway. And in the website, the laser views the appenders and the composition gateway, were all deployed together. It's just the APIs, the web APIs remained down here. The composition gateway in the logical view has no knowledge of the appenders, but it has knowledge about the interface. It starts scanning the appenders and based on the URL executes the appenders necessary. And the appender, because it's part of this logical boundary over here, knows everything about its own color. The things that are connected or highly cohesive within the blue color now knows everything that it can ask. And I removed the massive coupling or the massive dependencies of the composition gateway to know everything about every color basically, every colored thing.
46:13 Dennis van der Stelt
So that's why I tried to solve that. This is all in nougat. My colleague, Maro Savienty wrote a ton of blog posts about this, and I'll share some links at the end where you can find more information. Remember, these are logical boundaries where we try that yellow doesn't access purple and blue, and that goes for every single color. Here there are physical boundaries, apologies, where we try this, but we can deploy our components anywhere we want. We can deploy them in Azure serverless, in Azure functions, in AWS, in containers, in virtual machines, whatever. It's just that the dotted lines here show that something is, for example, ending on another machine or in another process or whatever. So if we continue, here, you can see the physical view, and I'll show something else also in the physical view on the right. Here, I took one slice basically out the physical view.
47:22 Dennis van der Stelt
Here you can see the appender and the appender calls the web API over here, and the web API knows how to access the database. Now these are two RPC requests. So you can imagine that if there are six or seven other cores that those are also all RPC requests. And an RPC request means remote procedure call over here, it happens over HTTP to a web API. But the API itself still has to access SQL server or whatever data store you're using to also do an RPC call. And this is usually not over HTTP, but more binary, et cetera to make it faster.
48:07 Dennis van der Stelt
Now, what if we want to remove another one of these RPC requests? As we've seen before, how we combine things, could we combine the API over here? Because that means that we only have one RPC request, but it means we have to suddenly deploy a connection string here, and that means that the composition gateway, if we have six colored things, now has access to six connection strings and does six databases. But the question goes back all the way to the original slides where I showed it that you could deploy your databases together and possibly also deploy all your components together. It doesn't change the logical architecture.
49:03 Dennis van der Stelt
What we do is the composition gateway in its logical view, and even in the development view doesn't have any access to the connection strings. It's only once we start deploying our composition gateway and all the appenders and APIs that belong with it, once we start deploying them, we start suddenly deploying, I don't know how many connection strings. That doesn't change that the composition gateway still can't actually access the database. It's just that previously in this example, the appender had access to the URL of this API because this was an HTTP request, so there was an HTTP URL known here in the appender and in this version of the physical view, we changed that into a connection stream. So I would say that this doesn't change the thing. Even if we combine everything like this, the logical view still doesn't change.
50:08 Dennis van der Stelt
So to summarize this, what did we learn? Remember, there are different views of your system architecture. The logical boundary is something completely different than a physical boundary. And also remember that when you are selecting technologies, that selecting a different technology might change somewhat the physical view, but keep track that it also doesn't change your logical view. Sharing data over services breaks data, ownership and autonomy. If you want to learn more, I'd be happy to share more details if you contact me. And I added the fourth one, it's risky, not risky, but that's probably a link joke. Anyway, like I said, if you want to learn more, go to the link go.particular.net/changearchitecture. There's more information there. There's links to my code, links to more details how to contact me. There's also an offer for a three 30 minute consultation. So if you want to have a call with me, feel free to contact me if I didn't answer something during this presentation. And let's open it up now for questions and Q and A, see if some questions came in.
51:29 David Boike
All right. There are already a couple questions and I imagine there will be more. That's how it usually works. The first one is from Stan and I'm going to summarize it a little bit. You're talking about Dennis taking multiple components from multiple services and throwing them together into the same runtime. So how do you manage or avoid version discrepancies on dependencies if libraries are loaded in that way? Say if you have one service that's using Newtons soft Jason with a different version than another service?
52:05 Dennis van der Stelt
That's a rather technical related question. And that differs, I guess, from technology to technology and it also depends on what you are doing a little bit. But one of the things that we use at particular, and this is always a problem, but there's a difference in net for example, between assembly version attribute and the assembly file version attribute. Because basically what's more important and the important part is that you're compatible with the interface basically. So if the interface doesn't change, then probably your version doesn't change because that's the thing, how you would call it, that's accessed. So the component that scans assemblies and dynamically loads them, et cetera, that looks at the interface.
53:07 Dennis van der Stelt
So that's what it's interested in. That will probably not change that much. If you want to make sure that you are properly versioning your assemblies, it's better to use the assembly file version and increase that continuously with minor versions, et cetera, so that you can demonstrate, for example, in your deployment pipeline that the new version was released and you want to release that version. Then net has less issues loading it and there's still an assembly version attributes that potentially you can increase. But that's an handy way to deal with the fact that net itself might have serious issues loading assemblies. And other than that, if you run into different problems, those are very technology specific and you should probably contact me offline with more details if you're interested in that. I hope I somewhat answered your question.
54:18 David Boike
All right, the next question is from Nick. He's being a bit contrarian, that's okay. He's asking what the value is added for using view model composition. He made the suggestion that it seems that a lot of developer complexity is added with minimal value if you could just call the API directly and I'm assuming for a single page that's pulling out of one database, that would be true. What are your thoughts on that, Dennis?
54:47 Dennis van der Stelt
I'm not sure I understand the single page thing, but if we look at-
54:52 David Boike
I was talking about the relative complexity of the application.
54:59 Dennis van der Stelt
So the complexity of the website in this example, the thing is, the complexity here, it kind of depends on how you look at it because we tried and Maro Savienty especially tried to get rid of the controllers, but those are so embedded into asp.net that it's really basically impossible to remove them. But there's like literally zero information here. But imagine that this controller would know a lot more about there are an X number of microservices or an X number of services and I need to retrieve data. You could think of it as that there would be several queries to an HTTP thing or binary or SQL or whatever all combined in into this thing. And what we now did instead was keep everything that's related to shipping inside this single thing. So this is related to a single page and it knows everything that's related to shipping for this specific page because you can imagine that the team that builds shipping also provides the HTML for the user interface.
56:24 Dennis van der Stelt
So the complexity is brought to much smaller chunks. So even though setting this up initially might be something new to learn, I think the overall complexity is brought back much further. And I would even dare to say that these or this entire class is potentially a microservice where it just does one thing. It's responsible for one thing only, namely retrieving data for a single page, and that's it. So the only thing is you get many more of those small chunks and you need to manage those. So I think that might be more complex, but if you're talking to a junior developer, you could say, "Hey, junior developer, create one the appender that does this, fix it." And after, I don't know, two, four hours, you could come back, look at the codes together, and he's working on a very isolated piece of code that doesn't have to do with anything else. So from that perspective, I think it's much less complex.
57:38 David Boike
All right. We have a question from Marta who asks, can this approach, and I assume we're talking about view model composition, work with a single page application front end?
57:51 Dennis van der Stelt
Yes, you would potentially solve the view model composition differently because what we did here in the view model composition gateway in asp.net, the one of the reasons we built it the way it was, and I say we, but it's mostly Maro Savienty who created the Nuca packages and everything, the way it's built up is because with asp.net and laser views, you are tied to the data binding from the view model onto the laser views, but you can't create six different view models. And that's what the view model composition gateway does here. But you could build something similar, for example, in JavaScript or J Query or whatever, and combine that all together in another pipeline. But those are much more complicated probably because first of all, I don't know how that works and you need NPM packages and I don't know what else. So it's possible, but the solution would theoretically look slightly different, maybe a lot even.
59:00 David Boike
All right, we are at the end of the hour, so I just wanted to mention before we go. Dennis will actually be speaking at the Kansas City Developer Conference in just a couple of weeks and I will be there too. And Udi is giving his advanced distributed systems design course in London in September. So go to particular.net/events and find a place where you can meet up with us. That's all the time we have for today. On behalf of Dennis van der Stelt, this is David Boike saying goodbye for now and see you on the next Particular live webinar.

About Dennis van der Stelt

Dennis is a Software Architect who loves building distributed systems and the challenges they bring. To always be better than the day before, he continuously searches for new ways to improve his knowledge on architecture and software development. He shares what he learns in numerous articles, presentations, and blog posts.

Additional resources