DDD Today - Modeling Uncertainty • Vaughn Vernon • GOTO 2017

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] [Applause] well thank you very much thanks for taking your precious time to attend thank you to Aberhart for inviting me to speak and the go to conference very first class conference so thank you so what I'm going to talk about today is using DDD in our modern time so what is contemporary DDD like actually this talk is meant to underwhelm you a bit because remember I'm a champion of simplicity ok so whatever I'm going to say is is going to be the simplest thing that could possibly work ok and and what I'm going to do is is hopefully show you how to cut through a lot of the maybe misunderstandings or complexities accidental or even purposeful complexities that you may use as you develop so what is domain-driven design about today so actually domain driven design hasn't really changed since Eric Evans codified the patterns what is it now 14 years ago or something like that the essence of domain driven design is still modeling a ubiquitous language in a bounded context what probably has changed is the way that a bounded context is rendered into production these days if you look carefully at Eric's book and and you sort of maybe even a little bit read between the lines I think you can tell that Eric was not opposed at all to developing a monolith but a well structured a well modularized well-designed monolith so potentially you could actually have multiple bounded contacts within one single deployable unit of course I'm not trying to read as mind this is just my interpretation of of his expressions back you know adder before the year 2003 so bounded context ubiquitous language still the hallmark of domain-driven design but because we have a bounded context a boundary where we model a ubiquitous language we will always have multiple bounded contexts it's just because the scope of a bounded context should be quite limited the scope of your bounded context should be limited to just the language that your team speaks and develops and then is reflected in a domain model so yesterday I was asked the question where do you keep the model as opposed to the code and again a very important design philosophy of domain driven design is the fact that the model is the code so you don't draw UML diagrams as a model and then write code afterwards they they are one on the same and so you'll see this model reflected as I had here in a single bounded context maybe using objects you don't have to use objects you could use functional programming these could be records or structures that are being passed around to functions but since you have this kind of boundary around a context where you speak a specific ubiquitous language you're going to have multiple ubiquitous languages multiple bounded contexts and these days you will see the multiple bounded contexts rendered into multiple processes and if you will you know I I can't be any different than most the other speakers here we have to say something about micro-services so you could think of a bounded context as a micro service and I think that's a worthy approach not always but it can be especially if your language tends to be small it's at least a good first approach because you may have reasons to break a specific entity or aggregate out of a single deployment unit for scaling or whatever it may happen to be perhaps the rate of change is different than the rest of the bounded context and so you want the freedom to iterate on this more rapidly than the rest of the bounded context there may be various reasons to deploy differently but if you start with the idea that a bound of context is a micro service it's an excellent place to start and keep the bounded context small so when you consider the way that computing is going these days I'll tell you I must be next to something that's blocking my signal there we go what is this do you do it what is it okay you know actually it could be interpreted in a lot of different ways probably when you first look at it you say I'm looking at some sort of a galaxy you know the stars in a galaxy but actually could this possibly be the atoms in a human cell so when we zoom at powers of 10 things tend to to look like things at other levels and this can be true of you know is this all the systems light light points that are representing all the systems on the internet or is it a a light point of all the actors running in a single system it could have several interpretations but what this illustrates is that when we have so many things happening in our computing systems regardless of whether we're using monolith integrating with many bounded contexts or unbounded legacy systems whatever it happens to be we are dealing with uncertainty everywhere non determinism because we don't know when a ray of light will reach one place or the other and we don't know what order the ray of light will appear in one place or another there may be factors that we aren't anticipating so I wanted to clear something up about what Donald Knuth said I've never met Donald Knuth so I'm not you know like the Donald Knuth expert here or trying to speak for him but most people remember this statement by Donald Knuth right it says premature optimization is the root of all evil okay this is true but sometimes this is used against optimization do you know what Donald Knuth actually said if you look up the full quote this is what he said we should forget about small inefficiencies premature optimization is the root of all evil so there are some obvious optimizations that we should use and should take advantage of in our computing otherwise something else that Donald Knuth said will be true of us so for people who are more than casually interested in computers and writing software we must have some idea of the underlying hardware what we are developing for and the environment that we're developing in otherwise the programs we write will be pretty weird I love that statement you know it's it just says it all that we've we've tended you know over the years to move further and further away from a knowledge of the hardware I used to have to know a lot about micro processors a lot about the memory available in a small PC I started developing software when the IBM PC was brand-new dual floppies and the best we could do in those days was about 256 K of ram okay since then we've tended to just you know put layer upon layer upon layer and we don't know how things really work inside but I think that it's going to be necessary for developers to start really taking this seriously in the next few years and here's a good reason why so if you go all the way back to the Year 1973 and I'll mention in a moment why I'm using the the year 1973 you can see that the prediction was made even earlier by Moore's law or Moore's prediction if you will that micro processors would continue to just about you know double in speed every few years and that trend continued to happen and also that the transistors and micro processors would continue to grow year-over-year that second trend has continued but in about the year 2003 we reached a level where for various reasons micro processors could not perform in the same sort of doubling in speed growth or speed that they had in past years so what did change is the fact that cores and hyper threading started to be evident in processors now I know this isn't new news to you but how many software projects are really not used the cores and a micro processor to their best advantage if you are however welcome to uncertainty the reason that I mentioned the year 2003 it's when Carl Hewitt and some colleagues came up with the idea of actors as in actors as the primitive objects in computing the the the primitive elements or concepts within computing and actors an actor the actor model and actor systems became very you know way ahead of their time okay Carl Hewitt was was at least at least 10 years or 12 years ahead of his time because Joe Armstrong didn't sort of reinvent actors in industry without even knowing of the work of Carl Hewitt or not much about it anyway when he and and his team started to develop the Erlang language so when you start using tools like the actor model concurrency or at least a synchrony becomes a real thing and that is because multiple actors are operating in different time frames than other actors and they're acting based on the messages that they have in their mailbox and they're acting based on the slice of the processor or core that they get it in a given time basically a thread but regardless of how our individual bounded context or micro services are are implemented internally we still have a synchrony or concurrency and non determinism around the entire system because we are publishing domain events out of a bounded context most likely at least if you're using you know the most robust approach to integration and and collaboration within bounded context then you're using events and other bounded context are reacting to your events even if internally we still use a blocking metaphor for or a blocking paradigm I should say for processing the events internally so when you face this situation welcome to uncertainty right this is what our brains want this is what our brains want we want event one two and three to hit a disk in that order and we want to read those events out in the same order and we want to react to them exactly in that order that's just what we want our brains crave it now I think that there are probably some here who have already embraced the the ideas of of concurrency parallelism actor model and and so forth and and they're they're at least getting used to if not very experienced in this but this is not the way things happen sometimes it happens that way but anybody who tries to sell you exactly once delivery an exact ordered delivery is really not being completely forthright because it's impossible and if there is even the possibility a single possibility for this event or this event to arrive out of order you have to plan for it to always happen so you may as well plan in and design into your software that uncertainty in a distributed system is just a fact it's something that you're going to have to live with so I found this really great definition for uncertainty it's the state of being uncertain and well you know what that's saying okay I mr. obvious write or the or Webster's dictionary is is obvious but you know it does give us a hint about something uncertainty as a state ah okay we're used to dealing with state if we are in the state of uncertainty we can reason about that state and design around it so let's take it from there uncertainty has synonyms unpredictability unreliability riskiness chance eNOS precariousness change ability variability you know what all of these really this one synonym for all of these synonyms makes us uncomfortable right we're just like boof and you know I know what you're thinking right now especially if you live in Germany you're saying I face uncertainty every single morning I mean the first thing in the morning the German bathtub that sort of kind of acts like a shower but not entirely do you know you know the the difference the difference between the level of the floor and the level of the bottom of the bathtub and the height that you have to lift your leg into a slippery surface it's just crazy I don't know you know it's like it's like the bathtub the German bathtub designer said well okay you got to clean yourself so here you go you know but you know here's how I look at it I mean even this morning now don't picture this too carefully I lift my left leg and I start to step into this and I realize you know what this isn't like taking a shower at all this is like going on a hike you know in your bare feet on a slippery surface two of those things which I would almost certainly never choose to do on my own okay now you get into the bathtub and it's way too narrow there are angles on the side again it's slippery if you don't stay right in the center and kind of shimmy up to the water it could be complete disaster but finally finally now here's here's really the thing about the uncertainty of the German bathtub is when you're done right now it's the opposite now you have to lift your leg out and step onto a lower surface by propelling yourself forward which means this foot is going to slip this foots going to hit a towel that's on the tile right and I mean do I have to explain any further the real reason for Germany not having Davey's so I mean you got to call it the way it is so here's the thing Americans are addicted to flat showers with a lot of room in them I have to admit but does that mean that I can't that I won't take a shower in Germany no but it's sort of like our addiction we have an addiction to blocking right a client object not not at not another system I'm just talking about a Java object or whatever kind of object in some VM making a method invocation on another object let's call it a server because it provides some service and this is a blocking invocation and you know what we just feel awesome about that don't we we're like oh man I know nothing else in the whole world my whole universe is just comfortable right now because I know nothing else is going to happen until this server finishes and I have some kind of result and I'll deal with that in some way okay so we're addicted to that kind of thinking we're also addicted to - you know exactly once delivery and total ordering that's the way our brain wants to think we're addicted to storage that is completely transactional and not just transactional on a single data source a single schema or table or whatever it happens to be but we want transactional consistency every place all at once right X a global transaction two-phase commit whatever you'd like to call it now what I want to tell you is that being uncomfortable is ok and just like I have to figure out how to take a shower in Germany without killing myself we have to figure out how to use you know distributed systems in a non-destructive way in a way where even though we can't predict what's going to happen next we can still deal with it so don't be afraid of this feeling now here's something another way to compare this do you know that this is called an auto stereogram do you know what's in this auto stereogram so you see you see this sort of graphic that makes almost no sense there's maybe a little pattern here and there that you can trace but if you squint your eyes and sort of slightly cross one or both eyes there's a shark in there do does anyone here see it some people see it like okay the few some people just see it like I don't know you know I don't know why I have to try hard to see it but I can see it now I've trained myself to see it and after you train yourself to see the image that is carefully hidden in the auto audio stereogram or stare Auto stereogram then you know you can you can then start to readily see them and you can just pick them out because you you teach yourself you learn to be comfortable with the carefully concealed object and deal with it and I think that this sort of describes the situation that we're in with you know our processors these days carefully hidden in this processor is multiple cores they're available to us we should be using them and we should be using them intelligently to get our jobs done quicker we need to break up tasks and make them happen concurrently or in parallel and so what happens to us because we're addicted to certainty - - blocking - you know synchronous operations total ordering absolute guarantees right then we want to tend to build a fortress around our bounded context and this fortress can be rendered like this so that here we have a domain event wandering in at finding its way in to our bounded context and ultimately we want to do something in our domain model that that reflects or reacts to the this fact that we see coming in from the outside but before we let the domain model have it what we're going to do is build a fortress at our infrastructure layer and this fortress is going to guarantee that there are no duplicates of this particular event and that this event is received and dealt with well not received but dealt with in the exact ordering that it occurred okay that's what we want to do and so we build structures like this we create a D duplicators so that if we see event one coming in again to our bound that context we make certain that event one is only seen once and we also resequenced so that if event two is latent and it's finally received we're going to look we're gonna store away all of these events until two arrives and then once the ordered events have been fully seen in a block we're going to release them to the inside that's because we're trying to model for certainty we want to deal with things in that way do you know one of the major problems with this it's hard it's really hard to get this stuff right it takes a lot of storage to you know persist these things and when can we delete them when is it safe to delete the fact that we've finally seen event two in order when is it safe to delete you know in this case delete events one two and three from here because we've already seen them and we don't have to worry about seeing them ever again right is it after a day is it after a few days or a week I mean who can tell when this could possibly happen again and so when you find yourself in either one of these situations right it becomes hard and you know what we haven't solved any business problems yet right and that's what we're that's really what we should be doing is solving business problems so let go of all this you know overhead and learn how to model uncertainty otherwise you're going to be stuck in this situation right where you say stop everything right stop everything okay go ahead I'm ready now right we can't we can't continue to model software that way because there is no now there is no now there there's actually an urgent global bug it's an insidious bug that's universally infecting all systems this is it right so look out for that uncertainty then you know how do we deal with uncertainty distributed systems are here to stay I said that some months ago I didn't think it was that funny but people just laughed like crazy I said just distributed systems are here to stay if you don't like it change careers you know like maybe open a restaurant if you open a restaurant you're only going to be using distributed systems you won't be developing them anymore okay so modeling uncertainty matters it matters because cores matter the cloud matters we're we're deploying in the cloud things are coming and going dynamically things crash things get re restored you know it's there it's a real thing microservices matter it matters to be able to change your cadence on any given micro service or or the rate of change or the scalability latency matters because networks are everywhere and not not only networks but networks of things right Internet of Things and all of these things are cheap they're all cheap and therefore they're happening they're a fact if you want to interview for another job you know a year or two from now you're probably going to have to know a lot about this if you don't already okay so what do we do about it one thing that Alan Kay said and I got to tell you I'm a big fan of Alan Kay being a an old small talker you know Alan Kay to me just has so many brilliant things to say except for where we disagree but you know one thing that he says that I heartily agree with is that the interesting thing about objects is not the implementation of the internal object it's the messages between the objects so the names of the objects as in the roles that they play and the messages that are exchanged between them are the interesting things and Alan Kay refers to this as the MA okay the mom this is a Japanese term that I may not be saying completely correctly but MA basically means what exists between and so he says this is what he really felt was the the important thing about the object idea now a lot of us have spent a decade or two decades or more thinking about the inside of these things primarily right solid I'm not I'm not disrespecting solid it you know it's a good design principle but we can take that too far because imagine that this thing is potentially a messy machine internally it's an actor right it receives an asynchronous message you know is it really super important that I am obeying the open-closed principle in this very case right what really matters is is that I have a design that is good enough to handle this incoming message specifically and what's interesting is the names and the roles of the two objects and the name of the message the intent that is meant to occur is our ubiquitous language that's what DDD emphasizes is the ubiquitous language and so here is the real thing about a synchronicity concurrency parallelism along with object design think about the messages in between and we're developing reactive systems so we have to think about the messages in between other little machines micro-services so here's the state of being uncertain Pat Helen have you read his paper life beyond distributed transactions who here has read that not enough I'm telling you you have to go read this paper it actually agrees with DDD but entirely you know and I I don't know what Pat Helen knows about DDD but this is what Pat Helen said in this paper which has even been updated life beyond distributed transactions he says that in a system where you can't count on distributed transactions the management of uncertainty must be implemented in the business logic okay it has to be and Pat Helen recognizes this now Pat Helland discusses this idea of an activity it's a partner activity so two entities regardless of where they're you know which bounded context they're in one might be in orders the other one might be in fulfilment whatever but they exchange messages and the the receipt of a message is called a partner activity the sending of a message is called a partner activity and Pat Helen says that here's an idea that you can use for dealing with the - you're modeling uncertainty now Pat Helen doesn't go deep into how you would actually perform this but when I read his paper this is just kind of the idea that I get I get the idea that you know an activity it can be modeled as partner activities where we're going to record an activity so we have a partner which is basically an entity somewhere right that's our partner and the activity that they are telling us to perform that this becomes a pair and this pair is going to be maintained internally in our entity in our local entity because that's our partner and we have to know if we've seen that before now you could model uncertainty in this way it can take a lot of extra storage though it can it can take a lot of overhead to reload these over time if activities if partner activities continue on and on over a long period of time and even Pat Helen says you know you've got to think about this because there can be an enormous amount of in memory you know RAM used or in process RAM used and a lot in in persistence and so forth so I want to take this further I you know where should we actually put this I think it needs to be in the heart of the software right let's model this because we are in the business of using distributed computing it's a matter of fact we can't escape the fact that distributed computing is an absolute necessity from now and moving forward it's just the way it's going to be and so it's part of our business it's part of the business model and we embrace it and so we accept the fact that we have uncertainty and it's actually less complex right it's it's less complex and I'm going to prove that it's less complex to model it this way so we need an explicit model right we have our actors or our aggregates entities whatever you want to call them you know events are flowing all around these are the orange little objects and the blue objects are commands and they're they're going everywhere and some of them are are being you know sort of filtered into a bounded context and being acted on and and others are being ignored and events are being emitted and and we just keep doing this so we have to identify our core domain and let me just you know say if you're working in this environment which is a p2p you know a peer-to-peer economy where clients are proposing short jobs that meet need to be done it could be anything from my I need someone to walk my dog to I have a broken window please come and fix my window and then some worker somewhere is going to say I'll do that job and I agree with your pricing and so forth right and you might look at this and say yeah the front end this is so important we want this to be an engaging user interface for them for the matching between clients and workers but where do you think the real core domain is where do you really make money in this situation you know it's actually probably in pricing because we have to make certain that we know the kind of job that's being done in a specific demographic neighborhood whatever it happens to be and we have to know that that that job is being fairly priced by the client and the worker is accepting a fair price and so forth and and what if it what if it's scheduled on a holiday we want to make sure that that the worker makes more money because it's a holiday we want to make sure that we make more money because we are managing this on a holiday you know we're trying to find out where do we want to put our investment in knowledge and I'm going to say it's probably not mostly here it's probably in pricing so you have to you have to choose your core domain carefully so from matching when a when a client proposes a job a client job proposal will omit a proposal submitted event this proposal submitted event will be seen in pricing and it will be seen in a scheduling and then each of these bounded contexts will do some kind of you know business logic that will say that the pricing is denied or the pricing is approved for example where the scheduling is denied and the scheduling is approved okay a fairly simple use case but it is a distributed use case so how do we deal with these kinds of situations when they happen in duplicate when they happen out of order so here's a situation where we might receive the same event multiple times which means we're going to translate that event into the to the same command multiple times and it's going to be received by some entity multiple times actually the the simple solution to this is keep a simple state that allows you to determine have I seen this command already okay so what this means is it doesn't matter how many times that you've seen this event and translated the command the entity is going to only modify its value once this particular relationship or Association and it's going to emit a single event there's that was the commutative one the non commutative operation is you know you you still receive multiple events translated to multiple commands but we need to have some kind of identity again sort of like that partner activity that allows us to look back and say have I seen this particular activity from this particular partner right and and so we not only keep a state but we keep an ID associated with that state but still it can be a definite part of our model we can do similar things with a sequence that's an order what if we receive event two out of order and we process you know event one and and three and they become command you know corresponding to one and three and now we have some uncertainty here because step one has occurred step three has occurred but step two hasn't occurred yet what do you do you just wait for step three to occur and then you do something about it you emit an event that says this little mini process has completed right and you're using the same kind of look back or state you know machine here that says step one two and three has completed and you know what you're modeling the business this is the way the business work now works now it's non-deterministic we can't tell we don't even know if this will actually eventually happen but I'll talk about timing in a few minutes okay what if we want to want to model the closest fulfillment center right okay we simply look for some kind of indication that a fulfillment center has replied to us through an event and it's telling us the distance and the time frame for example that they can operate in and so we choose the closest when we have multiple choice we might choose the first or the fastest so in this case even though 1.3 may not be the closest it was the fastest responder and still we're going to choose that that responder and when the other finally arrived what do we do we can note that they arrive but we aren't going to emit a new event because we've already chosen the first and sometimes it's necessary to model a process manager now again don't be afraid of this it looks kind of like you know this crazy spider that you you know he has poison and you're afraid of it but actually really it's just some aggregates or entities that are emitting events very similar to what we just walked through and the process manager is a central location to track that and then the process manager emits commands to get other work done as it sees this workflow occur and of course we have to deal with timing because timing is you know what if there what if we never receive that second or third event or fourth or fifth or whatever it happens to be well we need some way to look back and find out where this you know where this event could be but it's also good to know what we have already seen you know if you're using a D duplicator or a resequenced out in the fortress you don't know where your business process stands right now right because you're not modeling the business you're trying to prevent uncertainty so we let the uncertainty through and now we allow the business state to reflect the stage that we have already achieved and where we might have recognized a failure condition or at least some kind of severe latency so here's some modeling heuristics that you can go by in this uncertain world that we're now dealing with first of all you don't own the time frame as a developer you need to engage with the business not only for the ubiquitous language but for determining what time frame is acceptable to the business for when these kinds of situations timeout or reach some kind of a warning zone you have to engage with the business to do that and here's the thing I'm just trying to protect you because if the CEO of a start-up says well let's make it five minutes and it and it ends up causing problems with customers then the CEO can say well you know maybe it should be ten minutes if you say it should be five minutes and it causes cut problems for the customer that's a far different thing right so it doesn't belong to you the second one is be uncomfortable but make decisions so go and bother the business right okay when should how should this work what is the actual ordering what is the full process that we should be capturing here and when does it time out or when does it become a dangerous situation tell the business okay look we don't know the answer but we have to take a good guess right so be uncomfortable but try something and allow empirical data to prove that you should move this time frame or whatever it happens to be the design of the process in one direction or another another heuristic is of course start with what you know so this comes in with how do you model the events in the first place where do you start well we start with the customer facing you know the matching bounded context and we say okay look we know that we need a proposal for two individuals to agree on a client and a worker and because we need them to have some agreement and the agreement is going to be over pricing and scheduling and maybe location and and so forth well we start with that we we take what we know and we model the domain events around that and then we figure out who's going to see those events what events will be emitted out of those other bounded contexts and a lot of that can be discovered through a technique called event storming right you could figure this out in a matter of hours okay what I want to do now is I'm just gonna switch gears a little bit here and show you some code and I'm I think I have at least five minutes or I probably won't take five minutes but okay so in this source code I have some Java code that that can everybody could kind of see this No okay okay I'm gonna fail if I try to do something about that right now but it feel free to move up if you you know if you can't see I'm sorry so I'm sort of short on time so here's what happens we have a ubiquitous language part of that language is a proposal it's a job proposal a client has written this proposal so we have the concept of our own proposal identity we have a we have a client and we have some expectations of the client and we have a progress right so we've modeled the idea that there will be progress made on the approval of this proposal so that it can ultimately be accepted or you know taken by a worker to get the job done so we have a static method proposal dot submit for client expectations right see how fluent it reads okay and then we have another one for proposal changed with so this is this is actually see where I have proposal model fm this is just a little separation to show that this can be modeled in sort of a functional way so this is this is actually an immutable entity in that the state of the entity is not directly mutated right here see all of its properties are final right so any operation that I perform has to render a new proposal instance right it's still the same proposal but how do we do that so let's say that we're going to deny pricing we get an event from the pricing bounded context that says pricing denied ultimately this is going to be turned into a command and our bound it in the match bounded context and we're going to tell the proposal deny pricing and here's the suggested pricing okay so we we deny the pricing but we're going to check to see have we already seen this right now if Michael feathers is here he's going to say there's an if in this code so I apologize but I don't think that Java has quite the tooling it needs yet to be completely conditional Asst but maybe I'll be set straight in any event if it does if if we've already seen that pricing denied we're simply going to return a tuple two of the same proposal with no domain events okay so that's sort of telling the outside world nothing changed right ignore that in essence and now we simple simply if we're not in that situation we need to have a new progress with pricing denied we have a new expectations with adjust its suggested price right and we have the domain events with or a pricing denied domain event from our own bounded context and then we're going to return the tuple of a proposal changed with new expectations new progress and we're going to omit the event if completed which in fact we are completed now because we've already hit a an error situation and denied so we're going to give the the user the client the opportunity to rewind here and come up with a different price I also have an example of doing this with event sourcing it's just a different approach but you know you're going to apply some domain event that comes from the process that we're that we're supplying and then we're going to transition our internal state based on when the pricing is denied we're going to save away our new expectations in our new progress so I hope that this code has under underwhelmed you that this whole presentation has said this stuff isn't complicated model the uncertainty in the domain because that's where you're going to make progress with within the business and it's going to save you a world of hurt so thank you for attending yeah thanks a lot so maybe a few short questions so how do you think events should be named by convention containing verbs yeah so name your events generally maybe like the name of the entity that's emitting them such as proposal followed by a verb and past tense other times it may just be natural to say pricing denied but because it's within a specific namespace or you know package of of a given bounded context you know what this context means by this by this capturing of fact so yeah but use use verb and past tense and don't use the word event okay don't model your aggregates as proposal aggregate it's a proposal aggregate is not part of the ubiquitous language right an event is not part well you may have an event in your ubiquitous language but we don't we don't use the naming of technical terms in our business model okay and other critics Amplatz available send me an email okay if I find the question I think I do have actually an email address yeah I did send you something that so there you go and find the question would you sign my ddd book absolutely yes be happy to okay that's actually that's an actually a question that came in through the app and I think we know who's sent it in okay thanks a lot for the roark thank you you [Applause]
Info
Channel: GOTO Conferences
Views: 21,983
Rating: 4.7834759 out of 5
Keywords: GOTO, GOTOcon, GOTO Conference, GOTO (Software Conference), Videos for Developers, Computer Science, GOTOber, GOTO Berlin, Vaughn Vernon, DDD, Domain-Driven Design, Eric Evans, Software Architecture
Id: 8Y-XPlXOWoA
Channel Id: undefined
Length: 51min 59sec (3119 seconds)
Published: Thu Mar 08 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.