Mauro Servienti - Talk Session: All Our Aggregates Are Wrong

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] good morning everyone and welcome to all our aggregate are wrong so my name is Mauro 17 and the last name is pretty complex for Italian as well so and you see as you may guess by my accent I'm Italian so sorry about that up to you to decide if you want to be sorry because of my accent or because I'm Italian so my goal for the next 45 minutes is to try to picture you a different way of defining context or boundaries if you will and so a different way to design your classes when we want to transition from the design and a high level architecture to code so I'm a remote worker I fully promote a remote I work remotely 100 percent of my time but a flat where we live is pretty small so I cannot really work from home so I rented a small office and I used to bike ride to the office every single morning and my favorite snack are bananas so the problem with bike riding a backpack and bananas is that a banana is not really happy to be in a backpack while bike riding so the after failing a couple of times and you can foresee what failing means in this case I decided to buy a banana protector so I had it amazon.com searched for the thing and picked up the one with the best reviews I haven't looked at reviews at all I don't want to know anything about what a review about the Virata protector could be so I added it to the shopping cart and I immediately stopped here and the architecting myself popped up saying how such a thing could be designed so I try to understand what the backhand the Amazon back-end in this case could have been to satisfy such a UI because that's the finger was looking at and the first thing they said to myself as this one sounds like a nice looking aggregate so we could say that the shopping cart we could is an aggregate what about saying that it is a list of items so items added to the cart where every single item is identified by an item ID there's a price there's a quantity that we need to get the total amount for every single item and then the total amount of the cart we need to have the inventory because we want to display on the shopping cart how many items are left and obviously you need name descriptions and many other things to display things and it's very easy to fall into the trap of saying we have data and we have behaviors as well so what we can do when we have an item in the shopping cart we can delete it from the shopping cart we can save it for later and we can change quantity so it seems that it fits the aggregate definition it has data and behavior and it's a sort of transactional boundary for things that you can do in a shopping cart but if we look deeper and we put ourselves in the position of a business stakeholder and try to define business requirements for a shopping cart things are not as simple as they seem so that's what let's start from the straightforward one a businessman would say we don't want the price to transparently change Italians used to say under the feet of the user so without telling anything to the user and this seems to be pretty straightforward so what we can do is that the price is owned by something we could we can call sales and as soon as an item is moved from the catalog to the shopping cart we can copy the price over there and now we're not relying any more rooms of some on some sort of relational integrity to get the price to the UI fine we'll get to bed we'll get back to this later the second requirement could be look we want to be able to display fake or not doesn't matter we want to be able to display to users how many items are left in stock for a specific item in the shopping cart it might be fake because we want to try to push users to buy it but anyway it's an information where to display on the shopping cart and doesn't really seems to be a big deal hmm so that information is on my warehouse probably so inventories over there and whenever we add an item to the cart we copy the inventory value over there however availability changes over time so time goes by and other people buy banana protectors or hopefully other things and we end up in such a scenario so we end up in me in the need of saying whenever something changes in warehouse we're forced to go to the shopping cart ask - shopping cart do you have any any item in all your cart identified by ID XYZ if yes please update the inventory value to this new value a third requirement could be if the price of an item changes we want to tell to the user display a warning on the shopping cart page telling the user look an item in your shopping cart changed price from whatever it was to something else it could be higher could be lower doesn t matter we want to show the two different prices it means that the information we stored in that cart so far it's not good anymore so we need something more in order to satisfy this new requirement so pricing on its own is not enough we need to introduce a new property and you attribute in the shopping cart and change the previous one so let's say that we now we need something like that is current price and last price for every single item and we're in a very similar situation like the warehouse inventory type of scenario so every single time an item changes price in sales we need to go to the shopping cart ask is there anything in your shopping cart that matches this item and if yes please swap prices and update the current one to the new one and then the shopping cart UI hopefully we'll take care of showing the warning because the two prices don't match anymore hopefully but there's a little bit of complication here there is from the regulation perspective we're not allowed to change the price and leave the item in the shopping cart because the warning might not be enough and we don't want users to buy stuff that now cost something different to what which was when they put it in the shopping cart so sales that is responsible for this behavior needs to tell to the shopping cart move this item into the saver for later type of bucket and I highlighted this in red because this is pretty problematic so we have two different contexts and the red Haro identify a command that is basically crossing a boundary and the in the service-oriented architecture world this is probably the biggest evil you can decide to implement in your scenario because this is basically telling to someone you have no control over to do something for you and that shouldn't happen should never happen and obviously as we said this goes on for every single change that happens in sales the big picture at this point is even messier so if we take into account marketing we need to copy information from marketing to the shopping cart and let's say that we have shipping as well so shipping want to display in the shopping cart estimated delivery times but ID information belong to shipping and now we have shipping the needs to query the shopping cart in order to say is there something here yes now please change the estimated delivery in the shopping cart what's the problem with all these our O's is that autonomy is basically gone so we have a huge huge amount of coupling and if this was a distributed system we basically have a distributed model it it's very you can pitch in your mind that in a in a large system having such a scenario basically means that you can change anything there's no way to change anything without affecting affecting something else so it's very hard to respect one of the SOA tenets that is services or boundaries or contacts depending on the lingo should be autonomous where autonomous means that they should be free to evolve without affecting anyone else in the same system the reality is that the shopping cart doesn't doesn't exist it's very similar to the spoon of the famous movie so why the shopping cart doesn't exist because every single context has its own view of the shopping cart concept so we we should be able to say that sales owns a subset of the shopping cart so sales need to say the only thing I need to know is about prices and quantity because I need to be able to tell someone charge the credit card of the user by this amount that's it shipping estimates are not really my business at all so sales could say well my view of the shopping cart is just the list of items with a current price last price and quantity that's it and warehouse can do the same thing there's a cart identifier item identify ur quantity and the current inventory for that item shipping can busily do the same thing cart identifier item identifier quantity and estimated delivery probably we could say that quantity is redundant for shipping probably we just don't know really did what the business is about so quantity might affect the delivery time might not I started from the assumption that it could marketing doesn't really care about the shopping cart in a real scenario marketing is super stable so the only change that might happen to a name a description is for typos we're not really going to reuse a product in a catalog so if something changes that a product needs to be completely redesigned with this contain that product and we create a new one we're not going to change the name from banana protector to bike wheel that doesn't work that way so do we need a shopping cart at this point so all the contacts or all the boundaries or all the services if you will now they all have all the information they need to do their own little piece of work and satisfy all the requirements that we described so far so we could say that if we move the cart identifier ID concept to sales saying that conceptually sales is the owner of the shopping cart concept in the system not of all the data but of the concept on its own the shopping cart grain boxes in the middle are basically useless what we did is that that we just follow the coupling so zero coupling in a system is you topic there's no way to have zero coupling so the only way to have zero coupling is to have no behavior in the system this coupling we need to accept that coupling that this coupling and we need to follow the coupling aggregating things in the same boundary based on coupling so things that change together or that needs to be changed together order that they a change of something effects something else should be in the same context and that's what we did so far what's the problem now is that the information structure doesn't read fit users so can we display a shopping cart now not really so if we leave things as is the only thing we can do is basically build three pages well four because we need name and description and say thanks to the user well please try to remind the shopping cart identifier that's probably easy that probably is a gue ID and go from page to page and try to understand what's in your cart that doesn't really work at this point is very very tempting to use a technical solution to solve a non-technical problem so it's very easy to say let's build the red model to satisfy the user requirement that it is view the shopping cart page so what we could do is that we can have multiple contexts or boundaries or services or micro-services if you prefer that push information into a central storage that can be some sort of elastic search kind of thing where we build this view model concept that is the shopping cart we should be honest with ourselves that's a cache it's not really of your model so we can give you the fancy name and decide that well yeah we have models now with projections it's a cache and it's a cache with a few issues there's no ownership so we have multiple things owned by different contexts that now flow into one single bucket where no one knows nothing so if someone comes up and say well can we invalidate the price faster than the name in the description not really sorry mm-hmm so we end up adding technical solutions and technical solutions to solve words but they are not technical problems and with with such a cache in an Amazon like scenario we have things that we cannot really cache so in that page there's a warning that says this item cannot be shaped to iterate because that item is then from amazon.com so I intentionally went to amazon.com because I know that there are items that cannot be shipped so I logged in with my Amazon dot ID account and on most pages so all the things that are not shipped by Amazon basically does this warning meaning that that that warning cannot really be cached so it depend on the currently connected user so we need to be able to evaluate that information on the fly based on the current user what we might have noticed is that all these boxes bandura's they are basically sharing identifiers so we have the item ID that is a concept that everyone else we have the cart ID that is a concept that all the cart views in every single context help so can we use those identifiers to compose a view model on the fly we can use view model composition techniques to basically say let's imagine that we have a browser that is trying to hit a URL slash product / one if one is the primary key of a product and probably is much more complex on amazon.com but for the sake of the sample one is good enough and that identifier is shared across multiple services we could have some sort of infrastructure that intercepts the HTTP request and allows services to participate in the response saying let's build the view model on the fly and return that view model to the UI so how can such a page be built we have information coming from sales the price we have information coming from marketing probably we have information coming from shipping where information coming from her house and so on so all information all the information on this page are owned by service let's focus our attention on sales for example what if the infrastructure allows us to define a class such as this one something called enhancer something that can handle an incoming HTTP request if you're not familiar with dotnet don't focus on the code I'm just using dock tonight as well because it's the only thing I can write basically the first thing such a class should be able to do is to say I wanna participate in a specific request handling that is based on the current URL so the infrastructure scans all these classes and says is there anyone that matches this URL and this class says well if it is a get request and the controller is named the product and there's an identifier on the route then yes I'm interested at this point for all the instances that replied yes to the matching request the infrastructure will called please hand this request and what's happening is that we're basically extracting the identifiers from the URL we're setting up another HTTP request but can be whatever we want we can go on this quit and go to a cache we can go directly to a database it doesn't really matter at this point we're issuing that this request to our own back-end at the sales one and then we're finally composing the response into that dynamic view model a dynamic thing for non dotnet people is basically as an object age a dictionary an asset something that can be where we can inject things that are identified by a key Waller's so we're now able to say if someone is asking for slash product slash one all the services sales marketing shipping or house whatever can now participate in the response but the problem is what about right so what happens when we want to add an item to the cart we're now able to display the banana protector page but there's a button there are the two cart with a quantity we can apply the same technique in Reverse that's called the view model decomposition at this point the thing is that the important thing is that all the free services they all need the quantity for different purposes so it happens to be the same value but from their own perspective is something they trade completely differently can we apply the same technique saying let's say that this browser or whatever at post time to post slash shopping cart slash we're posting that little JSON object that is basically an ID and the quantity the infrastructure intercept the post request and allows all the interested parties to inspect the post requests extra the values they are interested in and post those values to their own backhand since they share it in tea fires now basically the the incoming item ID is enough for all of them to understand what we're talking about and from the code perspective you can basically do exactly the same thing so we now have a shopping cart ad post and ler that is still ni handle requests type of thing there's another interface keep in mind that this thing can handle errors and we'll try to understand later what does it mean we have the same matching logic this time we're matching just post requests so there will be multiple instances of this thing coming from different services they will say is the shopping cart request yes the shopping cart in URL is the post yes so I want to handle it and at handle time we are doing something little slightly differently so we're extracting things from the incoming post request we're grabbing the item identified from the URL will grab bean we're grabbing the quantity from the HTTP POST form and we're grabbing the cart identifier from cookies that can be whatever you want obviously depending on your context and instead of talking to our backends through another HTTP request we're sending a message through a queueing system we want to be as safe as we can so obviously imagine that you have an incoming HTTP request and you have three actors trying to handle that request in some way simultaneously if they all issue another h-2b request what could possibly go wrong so it's very risk that something goes badly is very very high we want to be able to reduce this risk at the minimum since we cannot really have transactions bound to an HTTP request what we're doing is basically saying say that there's an incoming HTTP request all the actors well they could do whatever they want but in this case the suggested action is send a message on cue so we still have a problem we have three actors or three components trying to talk to the queuing system there's no transaction keeping them together so if the second one fails because the rabbitmq broker is not available anymore so does in network a outage we have a message that is gone from the first one the second one fails and oops now we have basically data corruption on the backend because one of the services will have this concept of I have something in the cart and all the others knows nothing about that in the best case one of these services is one of the children's service so if it were in our scenario it could be warehouse or shipping where it's conceptually child item so that item is basically an orphan item it will just waste space on the database and book health we could say but if that's sales now sales as a master and the detail a piece of a detail and there's no other children on in all the other services so we have a problem now however one thing you might not have noticed is that at the handle time we're passing in a request identifier and we are passing that request identify er along to backends so now backends have the concept of correlation ID so they can correlate some data at the back-end level with a specific incoming request if something goes badly the infrastructure will call on request error passing in the same request identifier and all the actors all the components that participate in that incoming web request will send a message to their own back and saying please compensate the previous request do whatever you want I just don't care that can be deleted data try to go to the credit card system and say please please don't charge Mario's credit card whatever it's not really the problem of the federal structure what to do what's the easiest way to handle such a thing at the back end is a sort of event source the type of infrastructure in reality is much simpler so with just appending actions in our storage so the the cart at the back end won't be just a single item with a quantity whenever we add an item to the cart even if it is the same product ID we're adding a new row and the new row and the new row and each row is basically they are all sharing the cart identify ER and the product identifier but they are identified by request IDs so basically whenever something fails we can send a message to the can saying please undo or again compensate that request ID and what the backend could do is simply delete that row and now we're back in a scenario where everything is behaving as expected the important thing at this point is that there's no orchestration at all so there's no one that knows what's going on into that type of infrastructure you can imagine that one the simplest solution to build such a composition the composition type of thing is to code that in order to build that page I need to talk to warehouse shipping sales marketing whatever and your code will instruct in an orchestration type of approach services to do something that's coupling once again whenever we need to add something new to the UI or remove something from that UI we need to go to that central place with where everything is coupled and change the code there what we want to be able to do is simply drop a dll in a bin directory restart the service just because dotnet requires our to rest thing in order to pick up something new and go on so handlers or request handlers should be able to be transparently the order to the system without telling to infrastructure nothing that's very important bit what we were able to build so far is basically that we have full vertical slices each one handling a specific business capability or a specific business requirement and now they are able also to participate in the UI so they are level they own their own view model composition decomposition piece that is capable of participating in an HTTP request or response or both but we're not done yet so these services in some way needs to communicate with each other so there's a couple of more requirements in the Amazon shopping cart I want to have a look at we want to be able to notify users if the shopping cart hasn't been touched for a week so we put stuff my wife is very good at that so from your perspective and it's interesting because most people I know do that does the wish list on Amazon my wife doesn't use wishlist she puts stuff in the shopping cart and move things from save for later to the shopping cart let's say that's her type of usage of the shopping cart so she receives a ton of notifications from Amazon saying you've stuff in the shopping cart you been bought yet and that's very works very well she buys a lot of stuff anyway we want to be able to notify users if they haven't touched their cart and there's something in for a week and if they do nothing we want to wipe cards after a month so we want to just to save space on servers probably but that's a requirement now we have an interesting problem that if information are scattered around multi or systems or services or bond whereas if ul now we want to be able we're not going to be sure that they communicate with each other in some way so let's say that the one owning these two requirements is again sales say this is the the one that owns the concept of the Carter so say this is the one that can say I want to notify I want to annoy I want to wipe since it's not the one responsible to send the email though the sales knows nothing about email templates what do we want to tell to the user and stuff like that so whenever we add an item to the Carter that is the action that the user is doing what basically says does is that it sets a timeout for itself from separate self saying well send me back or call me back within a week because I need to check if something in this specific Carter has changed or no one touched this card for during the last week and set the timeout for itself saying well do the same thing in one month because I want to be able to wipe that card in within a month after a week what happens is that an event is triggered that event goes to the bus and is received by marketing in this in this case that is the one interested in knowing we have one week stale card and what marketing does is create the email talk to the notification system sends the email to the user a month later if nothing changed sales there is an event again in this case we have two subscribers so both shipping and warehouse are interested in this because they have a view of the shopping cart so they are owning a piece of the shopping cart so if something needs to be wiped the day needs to do the same thing so what they will receive the event and they will wipe their own view of the cart at this point given that sales already wiped there its view of the Carter this eventual consistency is not a problem at all so in the worst scenario we house can receive the message a week later it's just a waste of space on disk no one will see those items as orphan items so they're just often attempt since saves already deleted the master of the shopping cart given that we have vertical slices what's the important side effect in quotes of this that events can be as thin as name and identifiers we do not need to share anything across services other than super stable things if you need any fire changes we have a much larger problem so coupling is not the problem at this point it means that there's basically zero coupling across services because the only information that events carrying along is just the type of the event that it didn't identify something that happened in the past and the bunch of it is that are stable in this case we have full vertical slices super autonomous that can there are free to evolve without affecting each other and the final big picture is that we have behavior and data and from my perspective behavior is much more important that data data and behavior sounds better but behavior is the important part of things not data data is a side effect since we have behavior we have data there needs to be there but behavior is the thing that we should look at the boss is the the thing that is gluing all these actors at the back end and all these actors or components or services or aggregates he will have this view model composition component that allows them to participate in the UI composition and decomposition actions I have a huge demo to demo this but obviously in 45 minutes is impossible so the demos available here it's a dotnet demo to represent what we just described there's a 38 project so it's a bit complex that's why 45 minutes are not enough at all if you have any problem running the demo just drop me a message on Twitter email whatever raise an issue in the github repo and we'll fix that we have Oded on copy talking about service boundaries a little bit so a few note from moody about service boundaries that is the main topic of today basically and before letting go a couple of takeaways so bond worries are the key to success if you fail finding your boundaries coupling will basically kill you in the long term because we will drive you into the distributed monolith type of system that is basically the worst of both worlds so we said that the monolith is super better distributed distributing ammonal it can only be worse so the other thing is that every single time you're faced with we need more technology to solve this problem go back to the whiteboard you might find that you define your service boundaries in the wrong way so another thing that I realized during this last 15 years is that we used to say try to model the user mental model that's probably the worst thing we can do or it's probably the worst thing we can do when we transition from the result of the chat and discussion with domain experts to code because at that point it's very easy to so users business analysts and domain experts tend to think and present data in terms of data presentation what they expect to see on a screen and they describe things based on that and the interaction based on those views so it's very easy for them to say we have a shopping cart and we can you can change the quantity of the item in the shopping cart but that things happens in warehouse shipping and sales they're not telling this thing to us so it's very easy to end up designing a shopping cart that we don't really need the other thing is do not name things prematurely so if the typical sample is you're talking to a domain expert and they tell you we have the concept of a customer and customers can be premium gold in dough yesterday was saying silver platinum executive platinum that image immediately transitions in our mind in public class customer public property first name last name status and then we have already defined a boundary unfortunately the next requirement will be if the customer is premium then the price should be this so we now have the customer bounded context that needs to be able to participate in the price definition and then this is one of those arrows that cross a boundary okay so we just defined coupling so naming things prematurely it's basically evil it drives you and it might drive you in the wrong direction what we need to follow as basically the coupling so following the behavior of the system we should group data that change together so the customer status and the price should be in the same place does it have a name not really it's we cannot redefine the customer end price class it doesn't make sense at all it's in the sales context probably that owns the price thing one of the interesting way to achieve this is to use ante requirements technique so it's basically to ask stupid questions there will ever be a scenario in which based on the customers last name we're going to apply this count probably not in which case it's very easy to say the last name should not be in the same place as the price and obviously follow the coupling once we have defined the boundaries we can then apply view model composition and decomposition techniques in order to avoid more technology and more problems and present data to the user once we have done all of this we probably escaped the monolith and the distributed model it one of these sad things of Pisa is that it's very easy and you should expect to fail at least the first time so it's very hard to get this right at the first at the very first attempt and it takes a long time to understand boundaries to get them right so do not failure has to be expected and we should learn from failures that's it thank you very much if you have any question just raise your hand otherwise enjoy the rest of the day [Applause] in an example you add the sales boundary firing an event for an expired cart and then the marketing service needs to then compose an email that gets sent out so that seems like there's another view model composition in there somewhere that's not in a browser that's gonna be back in server side so who owns that part who composes the data from all those to generate yeah so the expand a little bit on the question the scenario is marketing needs to send an email probably the email needs to tell something about the cart so marketing can only simply say well you have an expired card somewhere we need to show something about the car probably cart items give a link to the cart and stuff like that so we again have information coming from different services an interesting approach to that is again view model composition type of thing so an email is pretty easy to achieve so in a real world scenario what could happen is that marketing talks to a notification service that is an infrastructure type of facility in the system and says please send this email using this template to this address the only thing that marketing owns is the destination address because marketing is the one interested in talking to the users so the they own the email address of the recipient what the template does is basically that the template is very similar to an HTML page so the template they write the template rendering engine will load the template start the filling process of the template there will be appenders or request handlers very similar to what we saw in the code that can participate in the template rendering process when the template is rendered that HTML is shipped to an email and that the very same thing can be done with the PDF so we could say that we need to generate an invoice and that invoice must be a PDF we can do exactly the same thing probably the only difference is that with an email we will redo the same process every single time we need we need to send it a very the same email even if it's exactly the same with an invoice we render that once and then we store it it's much simpler probably and then we also satisfy legal requirements that we need to be sure that the invoice doesn't change over time let's dance at the question going once twice so how does this so this focused on the the view model and I am in my head I imagined different teams you know a team working on in sales a team working on the warehouse so there are other things that the warehouse team might care about so they might want to know you know oh there's not enough banana holders in stock to ship this that has nothing to do with the view model from sales perspective so how does this situation change at all to handle that it probably doesn't so the defect at warehouse has the information about the quantity in shopping carts allows you allows to apply some sort of machine learning type of approach saying well I can predict that half 50% of the shopping cart will be checked out within the next week so it means that I'll go I will go up I don't know I do not know to say it in English or negative stocks negative inventory very quickly so let me refill my warehouse and that type of behavior is completely independent from other services so the interesting thing of vertical slices is that now we can change requirements in a single place without affecting anyone else so another interesting requirements in this scenario could be sales might say if it is a platinum customer and the the difference in price change is less than one percent don't tell anything to the customer select the old price so we're going to lose money but we just don't care because they are platinum customers so shipping doesn't really care about this warehouse doesn't really care about this it's just a something that can change and should change only in the sales context so now we can we are free to evolve different boundaries without telling anything to anyone and if something needs to be told we have events fin events we can start publishing a new event and someone else can start subscribing to this new event and do something else so it sounds like the the view model in that in the example you gave the view model is that owned by sales that's a very good question no in in large complex systems the view model or to be precise the template so the HTML HTML CSS JavaScript as well so common java scripts as well are owned by a service called branding so there will be a third-party service so someone else that owns that Monell it because that's them monolid in that case in which case definitely in scenarios like the Amazon one the booking.com one so user facing type of things where we have where we want to have full control over the user experience that the users have it means that we do not really want to allow a single vertical slice that probably knows nothing about all the others to affect how something is rendered on the UI in which case we want to have in order to have to have coherent display of things there's a fourth fifth whatever six service branding that owns the thing on the complete other side of the spectrum there's a systems like Salesforce SharePoint type of things so things that by design they do nothing and from the the business requirement perspective of the customer and the the business requirement is built by the customer into the system that is there to for power users to build up things in such a scenario services they probably own also the HTML fragment so we can instead of having in the in the vertical slice instead of having in this vertical slice only the view model composition parter we'll also have in the slice the HTML the CSS and the JavaScript the side effect is this magic happening in the UI in order to glue things together and as there is that sales does something that breaks someone else so guaranteeing consistency is much more complex and then there's the problem that you cannot really apply this thing transparently to the technology stack of choice at the UI level so if your if you choose in reactor you have to do things in a certain way if you picked up angularjs you have to do things in a certain way if it's WPF you have to do things in another way so the UI technology of choice affects the way you're going to change that last break in the vertical slice oh we're all the time thank you very much every day I'll be around the entire day [Applause]
Info
Channel: Explore DDD
Views: 17,311
Rating: 4.9047618 out of 5
Keywords: ddd, domain-driven design, software design, technology
Id: KkzvQSuYd5I
Channel Id: undefined
Length: 50min 13sec (3013 seconds)
Published: Wed Oct 24 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.