Implementing DDD with the Spring Ecosystem by Michael Plöd @ Spring I/O 2018

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] Wow this conference has grown quite a bit I must say very welcome to my talk today and warm welcome as well to the spring i/o conference from my side I will talk about a topic that I would say quite popular nowadays in terms of micro services and stuff like that everybody is always talking about domain driven design and I assume that most of you are aware that the main driven design contains not just technical stuff but also some organizational stuff and I would say political project culture stuff this is not what I'm going to talk about today today I want to focus about the implementation aspects of domain driven design I mean there are a couple of things to consider when you want to adopt domain driven design in your project and some of those things may come in handy for you others may you may have a gut feeling that they may not be as suitable for you and I will guide you through a couple of those questions and I will show you a couple of slides with theory and I will mix that up with code all the time so there's also a project on github that reflects the stuff that I'm talking about in this talk today and yeah a general disclaimer from my side I can highly recommend to everyone the books by Eric Evans and one Wernham and have to give them all the credits they deserve for those fantastic books so a lot of those ideas originate from those books like the bounded context the aggregate and stuff like that here and there I'll add my own grain of salt to the mix and this is the most important disclaimer I think it was shown last year already at the spring i/o conference by my good friend llamada from Germany please be aware that those this stuff that I'm talking today is highly popular but unfortunately what I see in many prod is that a couple for instance the internal building blocks of TDT get forced upon problems that they are not suitable for so please make up your mind and make up an decision if the stuff that I show you today is suitable for your problem or if it's not nothing of this stuff is a silver bullet nor is DDD nor spring and stuff like that as much as we all love the spring ecosystem of obviously now I will talk about in this talk first of all I'll start with the pounding context Dave already mentioned this term in his keynote right before my talk and obviously if you go for micro services thinking and modeling with bounded context is obviously good idea so I'll lead you through that a little bit and we will look at internal building blocks like the aggregates the entities the value objects also domain events and we will mix up that with stuff that the spring ecosystem helps you with I mean there are many fantastic technologies stuff like spring data spring cloud stream spring boot and so on but also and I really want to mention that this one good go practice so a general a good practice in terms of object oriented development now let's start with the boundary context especially when you want to work with micro services one of the a major term that we often hear is model your micro services along business capabilities now when you want to break work with spring boot based micro services leveraging technologies from the spring cloud portfolio maybe you still that that's the technological side but if your micro services are highly coupled on a business level all the fancy technology won't help you you're still screwed so please keep that in mind and this is where the strategic design part of DDD helps us so most important the bounded context and the context I will not talk about the context map in any detail today because it would be too time-consuming and not in the scope of this talk but let's start with the boundary context first of all so basically every sophisticated business domain consists of what all some some boundaries those can be linguistic boundaries that let's say an account we have a bank account and we have a user account they both called account for instance we have a rating that can be a rating from an credit agency that can be a rating from an internal scoring process for instance now those things are a little bit different I would say and each of those boundary contexts contains a domain model that we have to implement and this is the most important sentence about that topic it's the boundary around the meaning of a model now let me show you a quick example this example is about all of you in the audience so you are here at the fantastic spring i/o conference in beautiful Barcelona and Sergey and his amazing team they they set up this conference they ramped it up they organized it so obviously they needed to know how many people are coming is it going to sell out yes it sold out which is fantastic so who's coming did everyone pay their fees and stuff like that then we need to manage the event we have a couple of different venues here we have like this big room over there we have a couple of smaller rooms and so on now who is going to do a presentation in which room which speakers are extremely popular which topics are extremely popular and finally you all have your badges with you so those are those things over there we all have them and now this is where we all come into place so that's the spring I of is it obviously a software developer CD pop more beer on the shirt and how do we model the customer in the typical service-oriented architecture world we would say we need one customer service but that's the big fat app service that everybody needs to integrate with everybody needs to work with the model and obviously this reservations context would have a a sort of a model that can be suitable in this case now the event management part mmm has more a numeric model we don't care if let's say you in the first row want to go to the DDD talk or to some other talk that's running in parallel it we don't care if you in the first row are a vegetarian or a meat-eater it doesn't matter it's just like occupied seats so we just think about numbers and returns of the batches we can consider having replicated or shared data replicated or shared behavior obviously the micro services will wants to go for replicating so not sharing a lot of the stuff so basically the bounded context is the boundary around the meaning so first thing first inside of our boundary context I want to stick to the good old mantra don't repeat yourself inside of a boundary context but outside or between wider context I may consider explicitly repeating myself for the sake of decoupling now that's about the boundary context that's more I would say a logical kind of thing a way of thinking about architectures and I have mentioned the term microservices quite often but this doesn't only apply to micro services you this also applies to monolithic applications as well because you want to have an evolvable system so I could have and I actually think I should have written systems should be evolvable and DDD offers us one set of patterns the so-called internal building blocks from the tactical design part of domain driven design now this is where our aggregates live where our entities live where the value objects are located at and the factories the repositories and the services and stuff this is like the classical DDT kind of approach now I will go through that and we will see how we can implement those things first on a January side then we will add a little bit of spring here in there but please be aware and I will come back to that later on not every bounded context may be suitable for those patterns I will come to alternatives later on now I will mention them first because they are like the classic DDD patterns now let's start with the entities entity these are your core business objects so please think about business and not data objects here over domain they have a constant identifier which isn't necessarily or hopefully your database primary key you want to think about business keys in this case and they have their own life cycle as well on the other hand we have value objects in terms of the value objects we usually don't think about like real identifiers stuff we think about the identity derives from a combination of various attributes of a thing let's say this presenter costs 80 euros so this monetary amount the 80 euros we just care about 80 and the currency euros we don't care which 80 euros those are so that's a typical value object and eventually someone has spotted the buck or the not-so buck in my slides I mentioned the customer twice we have the customer here and we have the customer over there as well now what's the customer is it an entity or own value object the answer to that question is the best answer you can always give as in software architect it depends and it depends on the context on the boundary context you will have some boundary context where the customer is an entity and it is rightfully so an entity but you have other bounded context where the customer may not be an entity which is care about a couple of values and we're good to go about that now one thing that I see very often in code reviews that gets mixed up quite a bit yes we have the entity in JPA as well don't we so if you look at the Jaypee a specification about entities and if you look at the DDD box into the chapter of entities you find a parallel yeah each JPA entity must be annotated with an @ ID for instance it has an own life cycle it's a part for most of the operations on the entity manager so and it's called entity as well but as I said we can apply the concept of boundary context to that as well different context one is a data entity the other one is a business entity so as a general rule of thumb please don't go ahead and mix up your DDD and your JPA entities those are two different kinds of things one is behavior logic and the and so on the other one is data now in order to group all those things together there is another pattern in DDD called the aggregate and I am a big big fan of the aggregate I think aggregates are really amazing because they group entities and value objects together and if you look at the literature in terms of TDD you see that there is a little bit of an evolvement over the time I mean TDD is nothing new and fancy I think Eric's book came out 15 years ago as far as I know so 15 years that's an eternity in terms of IT so think back where the springboard was 15 years ago quite impressive and both stayed relevant so we're talking about two old and classic things today basically nowadays most of the people I talk to and I I go with that opinion they prefer rather smaller aggregates and it's totally okay to have one aggregate just referencing value object and it should just be most of all be a boundary around things and there are a couple of rules you may have seen there is a new thing here the root entity here this one over there now what is that root entity that root entity can be a life cycle over right over other entities but it is also the entry point into an aggregate so you wouldn't be allowed to enter this loan application form aggregate through the loan for instance you would always have to go through the loan application form for that and there are a couple of rules of thumbs and best practices for aggregates the first one is keep them small reference them by identity so don't please don't go ahead and and and build big reference graphs between aggregates I will come back to that with an example in in two minutes or something I will we see that very explicitly and make them a consistency boundary make them ideally you should have one transaction over changes on one aggregate this leads you to a very high degree of decoupling and this comes in extremely handy handy when you want to build monolithic applications I mean microservices are a great thing but there are a couple of use cases out there or a couple of organizations where micro services may not be the best use case that would be better off with a monolithic application I mean al monolith per se is nothing bad only badly messed up monolith is something from the gates of hell in order to maintain but this can lead you to maintainable code two very robust code now let's take a look at some implementation aspects I want to start with an example first on a battery of an electric car so we have a charger in there we have a couple of cells cell blocks we have some projections on it status some general information and so on now one of the classic practices which I don't like quite a bit in in in the Java world nowadays would be to go ahead and make everything of these things private and expose public getters and setters I call that the shortcut from hell and those getters and setters are public very easy nowadays with some with Lombok with shortcuts in IDE s really easy to do that stuff but basically this is against information hiding you're not doing information hiding in this case you are exposing everything to the outside and think about what the external access really needs to be what you really want to do with that and the code that I'm going to lead you through now I will switch now to the code example to the code part isn't github it's a work in progress it's not perfect yet I'm aware of that but I think it sketches out the ideas pretty well so if you if you want to follow that project if you want to contribute to it be my guest it's Apache 2 license so easygoing for everyone and let me show you the application as it is right now so basically this application consists of three spring boot applications basically it's a credit application implemented by this park over there and we can fill out and let's start with doing that let's start an application while we can fill out a loan application form for mortgage loans so obviously we have one bounded context a credit sales funnel now think about a credit sales funnel what the most important things of this beast are it's about capturing data writing down stuff and doing things yeah it's filling the stuff out right now somehow it's a little bit slow I don't know for which reason that's a lot no no it's speeding up very nice and the stuff that you want to do over there is you just want to capture data now would the aggregates be a suitable model for this one I'm not so sure about that but there is another context that might be very interesting the scoring so this application contains a rather sophisticated scoring engine and the scoring engine runs as soon as we have submitted an application now let's add some more things and say 1978 and we started working at the first first of 2017 and now we can submit this thing I'm not going to do that now the scoring part is basically structured like that it contains four aggregates and I will show you them in code right now now one thing is they are all I would say the applicant and the financial situation they come obviously from this application form to a certain degree and then we have another aggregate the agency result over there that's that's this thing over here and this comes from a third application from an external credit agency which delivers us some information about the credit worthiness of customers now the interesting part is this credit agency does know nothing about our application about the application form about the number of the application the business key of the application so it only thinks in person's first name last name street postcode city eventually birthday and that's the thing over there so one way that we could hook up the applicant with the agency result would be that the agency reef result references an applicant or that the applicant references an agency result that's one way of dealing with things but we would hook up those things quite closely together another way is adding a new value of check to it a person ID which is only suitable in in this scoring bounded context impose reference this person ID and then we finally have the application number which is the application and this hooks up into all of those things and brings them together now one hint from my side in terms of implementing you can go either on an implementation level to go directly for a route entity or for an explicit aggregate class in my example I will stick to the explicit aggregate class but there is also another way of doing it and I will mention that now the first thing in terms of spring is keep your aggregates spring free don't build anything regarding spring into your aggregates this should be plain old Java let's go to the code so this project consists as I mentioned of three sub projects the credit agency the credit sales funnel and the scoring engine now the scoring part contains one module called aggregate I will come back to the other ones later on now those aggregates the they are all all the four aggregates are placed into separate packages please do so really do so and why because I like to work heavily with package visibility in terms of information hiding when I work with aggregates now I will show you a UML diagram of the financial situation for instance okay then it's one day after the financial situation that's an a hand start a bit sure that we see everything yes and I want to have the relationships and let's clean it up a bit and now let's zoom in there a little bit so the first thing that I have over there is my financial situation aggregate and this contains a root entity which is my financial situation root entity there are options where you could also toss away the aggregate and work with the root identity directly this is also a very popular option so I don't think there is a better or worse between the two make up an educated decision what you want to have I want to have the aggregate semantics encapsulated in an extra class but you could also do that on the root entity as well what the financial situation aggregate then refers to is the root entity with outgoings and incomings so there's rent there is some cost of living there's some celery and we have a buildup I think the Builder aggregate the Builder pattern goes very well hand-in-hand as a substitute to the factory of DDD especially when you work with aggregates now one interesting thing about this diagram is that's the complete internal view now from a public point of view let's see what's publicly visible you see outgoings are not visibly public on a public level incomings are not visible on a public level the financial situation root entity are not visible on a public level they are hidden how do I do that yeah not every class has to be publicly visible you can work with package protections on a class level so no one from the outside of that package can mess around with these things the same applies to the financial situation root entity I'm even hiding the root entity the only public visible is in my aggregate class over there and do you see any spring import there no no no incomings no nothing this is plain Java but it's a way from the Get Set semantics now what I have done here and the same applies to the applicant let's take a look at the applicant root entity and so on and so forth now think about that now what about testability this code is easily unit testable just place the unit test in the same package as the aggregate and you can test out all of the details you don't need a at spring boot test in order to unit test that I mean you should always write your components that you only need the spring boot test for more sophisticated integration testing but this is perfectly unit testable code and it hides a lot of the outside now what I have added to my applicant aggregate over there is an annotation aggregate and an annotation aggregate builder and I put them into the microarchitecture module of this bounded context this only exists in there why because I want to have an architecture a code quality management in place that checks if aggregates are publicly visible and that other classes that are not aggregate are packaged protected now a quick quick question in the round who ever heard of a tool called arc unit yeah quite a few hands this is your new favorite tool our unit is awesome art unit is a unit test tool for software architectures and it contains a really amazing fluent API now let's take that aggregate annotation root classes that have name matching with aggregate should be annotated with aggregate classes that are annotated with aggregate should have name matching with aggregate so the same rule vice-versa another thing is classes that are annotated with aggregate should be public classes that are annotated with aggregate should exist classes that have name matching root entity so the aggregate may only reference the root entity and this is something you can easily run as a unit test and I highly recommend you if you've want to follow that path in terms of the aggregates that you use a tool like that so that nobody cheats around so let's go ahead and just remove the applicant aggregate let's remove that annotation and let's rerun the test boom aggregate annotation rule classes should be annotated with aggregate was violated and one thing applicant aggregate is not annotated with aggregate isn't that the amazing it's called arc unit highly recommend that tool especially for stuff like that now if we move on we need to work a little bit with the aggregate when we've worked with the aggregates and they are obviously part of the core domain inside our so-called hexagonal architecture onion architecture this is an architecture that is not highly proposed in the TDD books but well one mentioned mentioned it quite a bit in his books but not so much Eric so but this is an architectural approach that goes in hand-in-hand very often with with this way of thinking now so far we only have our aggregates and now let's take a look how we bring them to life I mean we need to persist a little bit of that stuff from the aggregates obviously we need to orchestrate them somehow so so far we only have the aggregates and we need to have some kind of a communication from this credit sales funnel kind of thing to the aggregates now let's first of all start with looking at applications services so in my project I have a class called scoring application service and this application service orchestrates through quite a few of the applique a great so let's take a look at the at this one score the agency results so somehow an agency rating from the external agency comes comes to us and we need to ramp up a new aggregate just for that what I do with that is I use the Builder pattern and each aggregate that I implement has and bilder so we ramped up for a person with first name last name street postcode city with some points with some rating points so the rating agency gives us a few points on the rating and finally I built the result aggregate now going back to our slides onto this one we see that the agency result contains ko criteria warning messages and stuff like that let's see what's publicly visible calculate scoring points is acceptable and please give me the person ID this aggregate contains behavior it scores itself itself it has the scoring rules built directly into it and that's all that I can do with this one now let's go to another aggregate in there let's see where we score let's score the the financial situation you remember the financial situation aggregate cost of living other income R and celery build and you remember we had the in comings somewhere conceal why package visibility so it's all hidden and basically the drop of the application services is to orchestrate certain operations over various aggregates and you see we we work with the financial situation aggregate we were we work with the applicant aggregate over there so and they are both after the application has been submitted we can score them both and I'll talk about it even publisher later on now one one interesting thing is we need to work with repositories somewhere now in spring data we have the spring data repository now the thing with the spring data repository if you use it directly is it runs if we let's just assume we work with JP a because I think most of the people in this room do that who virtually spring data JP a yeah yeah quite a few people so what do you put into your spring data repository JP a entities you remember that shouldn't be your DDT entity so we need to do something different and a couple of folks who have also ramped up a very interesting project on github on DDT examples came up with an idea that looks a little bit like that I'll show you that example later on so we have a an interface for the repository for the agency result and I just store projections I just stored the results away after they get calculated then I have a data access object which is basically then the spring data JPA repository and I have an implementation of that so basically I'm working with just another repository class there that encapsulate and encapsulates the spring data repository but the interesting thing is mind the package it's in the same package but in a different module on my maven build then the aggregate itself so it can still get into the Eternals because the repository very often does need to get into the internals but only the repository is also in the same package but I want to put it into another into another module for the sake of encapsulation and stuff like that now we need to communicate a little bit and what one thing before I come to the communication is the hexagonal architecture is not your only option so this is the option and I have just shown you but if you take a closer look at the for instance the credit sales funnel micro service then I have in my application that's just crap you know we just need to capture the form write it to a database and send it somewhere and that's it we're good to go if you have that maybe spring data rest or heavily a context that doesn't run on business entities or aggregates may be totally suitable and another kind of flavor that I often see is very driven query based contexts you I'm sure quite a few of you remember some some some functionality where all the logic all the knowledge all the wisdom is in very sophisticated queries and this is where the music takes or not in Java code or something like that and this can also you should reflect that and I always say don't just stick through to one thing and and and and force it upon everything else go along other options as well because in the end and that's a quote from one of the TDD books the domain should be the heart of the system if your domain doesn't fit into an hexagonal architecture structure don't squeeze it in there now let's talk about communication between boundary contexts now obviously we have a couple of options in terms of Orcas of communication between boundary context same human wrote that down really nicely in his building microservices book on riley he differentiated between orchestration and choreography I mean orchestration is mostly synchronous cause going somewhere and that's one part but the DDD community nowadays is all about events I mean domain events are the hot stuff right now in the DDT community and everybody talks about event sourcing event storming event-driven architectures and choreography just turns around the call flow a little bit so the crea plication submits and credit application submitted event and for instance the scoring component reacts on that event so basically those event-driven applications are an interesting idea and you with that approach you model your activity as a flow of discrete events it's something that happened in the past and you can work on the implementation side with various options now on the event payload you can put the full thing into an event I'm going to do that with the credit application submitted event I just put the whole credit application the whole thing that we have filled out in there and work with it but you could also go ahead and put restful URLs to rest resources for the event not your spring data arrest repository please because events should always be immutable you could have them empty so that you work with a polling mechanism or you can mix things up now in terms of infrastructure what I see nowadays very often is like the first thing that comes around is let's use Apache Kafka but please make up your mind Kafka or message brokers are not your only option and you can work with in terms of those things in my eyes you can work with a broker with HTTP feeds which are really interesting who has implemented event-driven education with HTTP feeds atom RSS stuff no one okay I'll show that to you in a second or you can work with in an internal event bus and in terms of the spring ecosystem you can work with spring cloud stream in terms of Apache Kafka or rabbit you can leverage spring and we see quartz or Rome and in combination to implement HTTP feeds or you can work with spring application events now let's quickly take a look at all of those options because they are all in the case study now I will switch over to the credit sales funnel application and what I have here is I have a credit sales web controller and that offers me as we can see over there this fancy button submit application form and when I do that let's see where do I have it there we go that's it submit application so that's a post mapping and it talks in the end to a credit sales funnel channel so what you need to do in in order to leverage that in in combination with rabbit in my case is you enable a binding spring cloud stream for RabbitMQ and this channels thing here which is just an output channel for things and add a little bit of configuration for that as well so basically you bind we bind that to a topic and we tell the application please serialize the stuff to Jason on the other hand for instance the scoring has an input adapter and it also has a configuration for that it has a binding for the application process channels which takes the applications submitted in and then on the incoming side no it's in the messaging I have an incoming message listener where I just annotate the class with extreme listener so when I click Submit the the sales funnel sends me an domain event with that a new application has been submitted over RabbitMQ and the scoring consumes it the same is applicable to the credit agency now that's one thing that's working with brokers now one thing that the credit agency offers me is a so called HTTP feed if we look at that that we have an HTTP feed with all new credit agency ratings and as you can see in Firefox this looks like the good old RSS world and basically it is an attempt eat where I put in some data and the scoring pulls that feed every couple of seconds I think it's every 30 seconds right now and we can easily see that also in the in the source code in the run dashboard you see this select max stuff down there that's exactly the fee polling that's happening from the scoring context now on an implementation side this is basically an very easy combination of spring MVC the Rome library which is there in order to create RSS or atom feeds and basically its rest with atom combined so just a brief look into this credit agency goes ahead and we have the web the person rating controller that offers the feed in the application atom XML style we set a last modified header based on the last updated rating and we go for an rest at M feet view which basically is Rome coding a hint from I side just copy-paste that take it over and modify it as you want now on the other side on the on the on the scoring side as an incoming thing we have the feed Paula the credit agency Paula which goes to that feet and polls every 30 seconds but it leverages all the HTTP features that we have with the headers and stuff like that and we pull in all the time and now let's submit this application form okay and let's see No hello Network program could not come on okay it should have an updated one okay I'll get back to that later on I think it's with the Wi-Fi right now that messed something up but one last thing in order to decouple across various aggregates or various components in an application we can also work JVM internally so we don't go for a remote communication between the things we go for an JVM internal thing and there is a nice feature for that in basically built into spring the spring application events and so what I have here take a look at the application service over there when I score the yeah that's the application event publisher we publish an event a scoring has been performed with a certain application number and then there is in this application another component listening to that thing because we have two parts of scoring we have the credit agency scoring and we have the scoring of the application we need to get them both together in order to see that the scoring is finalized because we need both parts and I did that with the spring application events so basically the scoring performed event extends from the spring application event I put in a little bit of a pay a payload and it's also very easy to implement a listener on that that's basically you you write a spring class which implements application listener you type it on a given event and then then you can do something on application event and we can go back to the scoring application service and ramp up the final scoring and put that together this is extremely handy when you want to build monolithic applications that are highly decoupled you don't need to leave the JVM for that or your deployment unit this is a very powerful feature of course it's not as decoupled as the Springfield stream stuff but it's better than direct references right now there is another project on the web which I definitely want to recommend I didn't contribute to this one but I took out a quite a bit of an inspiration from that it's github.com slash DDT by examples and they have a couple of different DDT examples I mean we could do a two day workshop just on the implementation stuff I just wanted to get you give you a couple of ideas and input on these things that's very useful and ramp it up I'm currently writing a book on the main room design it proceeds waste slower than I expected it to do but I'm writing so if you're interested on that you can subscribe on that and so [Applause]
Info
Channel: Spring I/O
Views: 14,690
Rating: 4.8967743 out of 5
Keywords: springio18, microservices, DDD, springboot
Id: a9dF7fnArq0
Channel Id: undefined
Length: 48min 3sec (2883 seconds)
Published: Tue Jun 05 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.