Joy Clark: Hello, everyone, and welcome to a new conversation about software engineering. This is Joy Clark, and today on the CaSE Podcast I'm going to be talking to Vaughn Vernon about domain-driven design. Welcome to the show!
Vaughn Vernon: Thank you, Joy. Thank you for setting this up.
Joy Clark: My first question is kind of a broad question - what is domain-driven design?
Vaughn Vernon: Well, that's a broad question... Domain-driven design is an approach to software development that emphasizes strategic design. Of course, there is also the means to use tactical design, but think of strategic design more as like the broad-brush strokes of a thick brush with a lot of paint on it maybe, and tactical design as using a very fine brush for the details inside.
Vaughn Vernon: Strategic design is looking at what is a core initiative, software initiative for the organization and how you can leverage software design to, in essence, do the most important thing for the organization, or one of the most important things, and to really get into the model to the extent that everyone involved in the project has a better understanding and the means of learning more as they sort of dissect and learn more about the domain. Then actually they're achieving a better result than any one person could imagine in their mind.
Joy Clark: And a personal question - what was your journey to domain-driven design? Why did you become interested in it?
Vaughn Vernon: I suppose it depends on who you ask, but I kind of got into domain-driven design I suppose before it had a name. I'm not claiming to be in any way the inventor or author of DDD (that's clearly Eric Evans), but I was doing a lot of things that were very DDD-like since the early 1990's. I'm not going to say that my journey was anything like Eric's; I know that we were working in different domains, but we were both Smalltalk programmers, and I think that a lot of this pattern thinking came out of Smalltalk, and a lot of the kinds of problems that were being solved were being solved with the ideas that were being used in Smalltalk.
Vaughn Vernon: That's probably one reason, but the other is that as team that I was working with, we were very keen to drawing out the mental model of domain experts. We were working with them and we were very concerned with naming, so we were using CRC cards...
Joy Clark: What are CRC cards?
Vaughn Vernon: It's class responsibility collaboration (or collaborator), where you basically just use an index card and you write the name of a class on it, what is the responsibility of this class and what are the other classes that I can collaborate with. So you end up having sort of a map on a table that might even remind you of user story mapping, or maybe even a little bit of event storming - not really, but in other words, you've got these cards spread all over a table and you're saying, "Okay, I can pick up a card and play the role of this class that's written on a card, and I can have a conversation with someone else who's playing a role in this card."
Vaughn Vernon: It was like a means to understand the model better. This is something that Rebecca Wirfs-Brock was using. I think I learned about it because of the work that Ward Cunningham and Kent Beck were doing; I think that's where it originated. I was doing things like that, so when I finally got to the point where I was reading Eric's book, I was just thinking, "Man, this is it!" And even better, it's not even what I knew about, but it now gave me a way to talk about it to other people. Because I would have conversations, and frankly, the way software development was going in the new millennium (2000-2001), I felt that software development was just going completely in the wrong direction, and I would have these conversations with people that led nowhere because they look at you like you don't have a clue... Because things were all moving CRUD, anemic model. People just believed that this was the way to go, and there was this movement around no design, and so no design led to really bad design...
Joy Clark: So no design is not a thing?
Vaughn Vernon: I guess I'm rambling a bit, but that's sort of what led me to it.
Joy Clark: So you wrote the two books, Implementing Domain-Driven Design and Domain-Driven Design Distilled, and you wrote some other books as well, but did you have a specific goal in mind when writing those books, to fill a gap that was in there?
Vaughn Vernon: People love Eric's book; I love Eric's book. It's a marvelous book, I think, and it's extremely well-written. I always say that Eric would be the most likely to be a New York Times bestseller under a pseudonym. I think he's a very great writer, but for whatever reason, depending I guess on the maturity level of the developer who's reading this book, they don't necessarily really get how to put it into practice.
Vaughn Vernon: So my goal was to say, "Okay, if this is what I want to do and this is what I want other people to do, then I need to teach them how to do that", and that's really just the goal that I had - to make DDD approachable. Frankly, the Distilled book came along after the red book because I read some reviews on the red book and they say "You're too long-winded", "You could have done without these explanations", "We didn't like the cowboy jokes" or whatever it happened to be... And I said, "Okay", so instead of taking that as sour lemons, I just make lemonade; or in German I would say Lemon in Hefeweizen.
Vaughn Vernon: So that's what I did. I said, "Okay, there's another product there that needs to be developed to help people to step up to DDD at a much quicker pace", so that's why Distilled is there.
Joy Clark: What I like about domain-driven design - and I haven't been doing it for that long; I've kind of just been getting into it in the past year or so...But what I really like about it is that it focuses on the business -- it focuses on the actual problem that's trying to be solved, and not so much on the technologies behind it; that's secondary. But one thing that I found a bit difficult at the beginning was all of these weird words that people used all the time, like "bounded context", and I was like "What...?" They would just say in conversations "Yeah, it's a bounded context" and I'd be like, "What is that?" Could you maybe briefly explain the main words that are always used in domain-driven design?
Vaughn Vernon: First of all, I started learning about software patterns in the early to mid '90s, and patterns were important. I think the most outstanding work that occurred, even though there were more before it, was the Gang of Four book "Design Patterns." So I just really tried to think in patterns as much as I could, so patterns were a natural way of thinking for me and I found that it was good to have conversations with other developers based on patterns and pattern languages. So the way I view DDD, maybe somewhat incorrectly, but to me it's a pattern language. It's a pattern language that drives from a strategic level and the different tools that you have (or patterns) at a strategic level, and then which dive down clear into the tactical level.
Vaughn Vernon: Eric probably has a different way of explaining those these days. I think I've had a conversation with him where he said, "Well, probably back then I may have called them patterns, but maybe today..." -- I don't remember exactly, but to me if I think about them as patterns, then it helps me to grasp what is the direction, what is the packaging of this technique or this approach.
Vaughn Vernon: So then, again, you have a pattern language that is around strategic design and tactical design, and now you're going to have names for each of the patterns in the language. Some of those names are bounded context, context mapping, and even within context mapping (or context maps) there are different kinds of context mapping tools, such as partnership, and customer-supplier, and conformist, and open host service, and anti-corruption layer, published language, and so forth.
Vaughn Vernon: So you've got these different patterns in there, and what bounded context means by its name is that there is a boundary, and within this boundary there's a team that is working on a language, and this language is spoken, it's used in writing scenarios like BDD scenarios, or TDD scenarios that you can then develop your model from and acceptance test your model to make sure that they align with the mental model of the team. And this team is comprised of at least one domain expert, so some might call that person a subject matter expert... But it's not really a title in terms of a job position, but it's a role that they play because they have a lot of expertise in a particular very important area of the business.
Vaughn Vernon: Then along with that one or more persons playing that role, you have software developers, and together they're working on developing a language... And there's no mystery to the language, it's simply a language that describes the behaviors of the software that you're developing and the data that you're working with. This can be rendered in a lot of different ways. The most popular way has been object-oriented programming, so you create an object model, but it could be records in Clojure - one of your favorites - and using functions... So you can develop a model that way.
Vaughn Vernon: You'd hopefully probably be interested in interviewing Eric in his experience with Clojure and domain-driven design... He's been working with that. That's a boundary. And since you have a boundary, it means you're gonna have multiple boundaries, because we're not developing an all-purpose model that solves every problem in the business; we're focused on a model that solves a very specialized purpose in the business, which means then that we're going to have other models that solve other problems, but part of the problem that they solve are problems that we in our model need to have solved, so we're gonna integrate with them.
Vaughn Vernon: From there, you use context maps. That's a mapping -- really, just think about drawing a line between two different bounded contexts, and when you look at the line, that line always represents a team relationship. So your team will have a relationship with the other team in the sense of "What are your communication channels? How much do you communicate? What kind of software features can you ask for or request? Do you need to say "please" versus "When will you have this done?" kind of thing?"
Vaughn Vernon: Then there's also the actual integration techniques or style that we're using technically to exchange data and in essence model objects between, and how potentially we're translating one concept from one model or bounded context to a concept in another bounded context... Because if you're developing languages, then two different bounded contexts speak different languages, which means we need a translator between them. That's quite a bit what strategic design is about, but then really focusing on what is the core domain, and that's another pattern - "What is core, so we're not going to give an investment and a lot of attention to models, even though they're important and essential, but that aren't core? We're gonna put our eggs in the core domain basket; that's where we're going to invest and put our more experienced developers in there, and the right domain experts." That's just a way to think about strategic design and the pattern names. Does that make sense?
Joy Clark: Yeah, I think so. That was a good explanation. One thing that I always have a question about when I hear modeling, I always wonder what does the model actually look like? Is it just in my head? Do I have a UML diagram somewhere, and like a wiki page that I have to keep updating? That's the thing... I think, okay, there's the modeling step and there's the programming step. How do I insure, for instance, that my code matches the model that I created?
Vaughn Vernon: I see. Ultimately, with domain-driven design you want to have the goal that the code is the model, and the model is the code.
Joy Clark: Oh, so you update them simultaneously.
Vaughn Vernon: Yes, so they are one and the same. Now, you have other tools, like scenarios, like BDD, unit test tools or specification test tools and so forth that you can use to write acceptance tests around the model, but ultimately the model is in the code. There's nothing wrong with drawing diagrams, maybe even UML diagrams or diagrams that even misuse UML, but that make sense to the team. Maybe you'll put those on a wiki or whatever, but don't confuse that with the model; that's not really the model. That is a modeling step that you're taking, but ultimately with the purpose of implementing code.
Joy Clark: Taking my last question a little bit further, you talked about bounded context and then the context mapping to kind of relate the different contexts, so maybe you can clarify - is a bounded context one software project, and another bounded context another one?
Vaughn Vernon: I'm not going to set a hard and fast rule here, because actually DDD is much about not setting rules, but just to make sense to people who are listening, if you're using Eclipse for example, I would say that one bounded context is an Eclipse workspace, and inside that workspace you may have one or more projects, but all those projects are related to one bounded context, one model. Each project may be used for a different layer in the software. I don't find that it's necessary to have multiple projects, but I would have -- for example, let's just use a name like pricing. We have a pricing bounded context, so we would have a workspace named "pricing" or "pricing context", then inside we would have one project called "pricing" or "pricing context", and in that I would use packaging what DDD calls modules to separate the different layers, and then actually I would just have all my layers represented in a single project.
Vaughn Vernon: I find that if you're using .NET, we could make an equivalent comparison (or roughly equivalent) where the solution, the Visual Studio solution represents a bounded context... But I find that .NET developers very much like separate projects to create each sort of layer in. So you might have a project that is used for the UI or the controllers, the messaging for infrastructure, and another one for the model, and another one for application services and the like. That's just one way of looking at it.
Vaughn Vernon: Then you have a Git repository for each of those, and then one team that's working on it. Now, one team can develop a single bounded context (or SHOULD develop a single bounded context) and one team can manage and develop multiple bounded contexts, but you should really never have two teams or more than two teams - more than one team, I should say - working on a single bounded context... Because when the effort is to have a well-defined, well-understood language within a bounded context, then having multiple teams in there you would tend to have conflation around different terminology and so forth, because each of the teams would tend to interpret modeling concepts differently. That's kind of how it would work.
Joy Clark: I think that's a good explanation to kind of get an idea of what it looks like in code... But one thing I'm still not so clear about is as far as the context mapping goes, how do you actually visualize the context map? Because you're talking then about cross-boundary interactions. Is it like a physical picture you draw out, or...?
Joy Clark: Vaughn Vernon:[00:21:15.24] Well, it starts that way. You would draw a map on a whiteboard or a large sheet of paper; you draw the ovals or ellipses or whatever as your bounded context, to represent the bounded context in your problem space, and then you draw lines between those bounded contexts, however they are associated. Then you can name the team relationship such as "Are we in a customer-supplier relationship with the team that's developing this other bounded context, or are we in a different relationship? Are we using their open host service in a published language? Are we conformists to their model? If we're conformists, what does that mean to our model?"
Joy Clark: So you can start having discussions about that, versus "Are we translating from their model to our model?", which is not a conformist, but probably more like an anti-corruption layer where you're not allowing the other model to corrupt your model with language that you don't accept.
Joy Clark: But then I would assume that that could change over time if new things come into play, so how do you make sure that everyone retains an understanding about the system?
Vaughn Vernon: In the sense of...
Joy Clark: The context mapping.
Vaughn Vernon: So the next step though, after you draw this map, is that you're going to implement in code this relationship or association between the two bounded contexts, and if you need to integrate with another bounded context in time, then you're going to have that integration. There's certainly nothing wrong with putting those strategic models up into a wiki, or keeping them somewhere that the team can have a visual on them and refer back to them on a regular basis, but it's all about communication.
Vaughn Vernon: Ultimately, everybody on the team probably doesn't need to look at the context map continually, because they're going to have well in mind the integrations that they have - or they probably should - and the map might be more useful to new team members who arrive later.
Joy Clark: One question I have often in my head about domain-driven design is whether it's descriptive or prescriptive... In the sense of "Am I starting from zero and I get to design my own product, and then I decide to make domain-driven design and I basically start from scratch with domain-driven design?" or is it more like "I already have a huge legacy system and I need to work with that, so I do domain-driven design with that and try to figure out what the model within the system is."
Vaughn Vernon: You have to identify your problem space. The first idea that you start with is this germination of "What is strategic to our company?" Someone has named this - before the project begins, someone at the C level or someone who's driving business vision in the organization has seen the need for something very strategic that software is going to support. Sometimes that actually happens because of a consultation; maybe sometimes the company says "We don't even know exactly what's core. Where should we start?" Other start from, "Wow, we really wanna kill this monolith" or "We really wanna kill these thousand monoliths. And when we kill these thousand monoliths, how do we go about it?" So it can start at various levels, but identify your problem space.
Vaughn Vernon: Let's just take the example of somewhere along the line, some strategic vision has been developed that says "This is where we want to focus, because this is going to distinguish us from our competitors. This is how we're going to find -- we're gonna be the sweetheart of the industry" and all this stuff, right? So you take that vision and you say "Okay, if we want to ultimately finish with that core domain and implement it, what do we have to integrate with? How do we make that happen? If we have users, who are our users? Where do we get them? Do we have a sense in our organization of where the users are? If we do, if we have some sort of identity management system or subsystem, we're gonna have to integrate with that, if it has the users or if we're going to put those users in that context... So we'll have to integrate there. What about for this or that...?"
Vaughn Vernon: If it's an e-commerce service, maybe correct pricing at a given time of a year becomes super important - or at any time of the year, for any given demographic - so maybe pricing is the thing, which may not need users at all; the users are simply going to make purchases based on what analytics says the pricing should be at this point in time, and it's going to tend to drive better sales. So the core would be pricing, but then where do we get the historical data for knowing what have been our past successes in sales? What have been our sales trends? How many of these products have been returned over time from dissatisfaction?
Vaughn Vernon: We're going to have to take these streams of data and analyze them, and that is where we'll draw our pricing model from, and maybe some other inputs. So we have to identify what do we have to integrate with in any way, shape or form, and that's where you kind of start. Sometimes it's a clear, separate model that you can develop, and other times it may be sort of a specialized tweak on an existing legacy system, so it really depends. But ultimately, the goal is to focus your attention on a single bounded context per team. That is very important. And again, that means different things for different organizations, with different maturity levels, different stages in their lifecycle.
Joy Clark: One phrase I find very vivid in domain-driven design is the big ball of mud... I think we all understand what that is in our software experience, but how can we keep -- we might be doing really well at the beginning, we map out our model, we start developing our model, and then how can we ensure that over time it doesn't become a big ball of mud because some manager comes and says "I want this feature now!" ?
Vaughn Vernon: How do we prevent it from becoming a big ball of mud?
Joy Clark: Yes.
Vaughn Vernon: That's part of what the boundary is for. With the bounded context, you're saying that if it doesn't belong to our language, we're kicking it out; we're not only kicking it out, we're not letting it in in the first place. So we keep that boundary very distinct, and it could be that that model needs to grow somewhat over time in terms of new concepts, but that's only because those concepts fit into that particular language... But we're also forcing everything out, and that's why we'll have multiple bounded contexts.
Vaughn Vernon: So to prevent the big ball of mud, you use bounded contexts. And that's something that organizations can leverage. Even where they have a few core domains, they can still always use bounded context to make sure that the monolith - or worse, the big ball of mud out of the monolith doesn't happen.
Joy Clark: Could a big ball of mud occur when you're dealing with microservices?
Vaughn Vernon: Oh, no doubt. I mean, sure.
Joy Clark: Because you said "Monolith, or worse...", that's why I was asking.
Vaughn Vernon: What I'm saying is there are monoliths that can be very well designed, very modularized, literally where you have no coupling between multiple models in a single monolith. You have only these loosely integrated models, just like you would if you were in separate processes. But what I'm saying is without that, then you will have strong coupling across multiple models in a single monolith; that's where you get your big ball of mud, right? That's where everything depends on everything else, and you touch something over here and that cascades into an error over here.
Joy Clark: You get like a gopher that comes up and you're playing Whack-A-Mole.
Vaughn Vernon: Exactly, exactly. But from the microservice standpoint, how can a monolith occur? Just share the database. Share databases across microservices and you'll have a big ball of mud, for certain.
Joy Clark: Those are mainly the questions I had about strategic design. You've also done a lot of work with event sourcing, so I wanted to ask you some questions about that.
Vaughn Vernon: Okay.
Joy Clark: I've heard the term domain event - what is a domain event?
Vaughn Vernon: A domain event captures an occurrence. It's a fact that we have an immutable reference to. So we create an object that represents a happening. We usually state that as a noun followed by a verb in the past tense, for example... "Price generated", out of our pricing microservice. So this "price generated" will capture the fact that for some product, at this point in time, we developed this price, or we came up with this price based on maybe these other factors, maybe just IDE's to things that had some sort of influence on this price that we derived, so that's an idea of an event. It's a statement of fact with some data in it. Most of the times you wanna limit the amount of data that it holds, but not always.
Joy Clark: So technically, you save these events in your system?
Vaughn Vernon: Yes, and then you'll persist this event. Now, I want to distinguish between event sourcing and non-event sourcing; you don't need to use event sourcing in order to use domain events.
Joy Clark: Okay. So what's event sourcing then?
Vaughn Vernon: Event sourcing is where you use domain events to represent the state of your whole system, but that state is then sort of divided up into the state of entities, or what DDD calls aggregates, and these aggregates have a state that is derived from their past events, things that have happened to that aggregate over time, and now we can, in essence, left-fold, right? That's a term you get... You can left-fold your events, from your first event to your last event that has occurred, and that renders the state of that aggregate.
Vaughn Vernon: Now we perform another operation on that aggregate, it emits another event, and that event gets saved in the stream of events for that aggregate by its id, in the order in which it occurred, and then we can derive our next state from that the next time that aggregate is used. That's basically it. Again, like I said, you don't have to use event sourcing to use domain events, but you still need to make sure that your domain events are transactionally consistent with the state of your aggregate, because you don't want an event to be captured and not that state transition, and you don't want the state transition to be captured and not the domain event associated with it. In essence, event sourcing takes care of both of those things in one.
Joy Clark: That's true. So is that only within one context, or can you use event sourcing or events to integrate multiple contexts?
Joy Clark: Vaughn Vernon:[00:35:58.11] One way that you might look a the published language pattern from strategic design is that we're going to publish our domain events, and our domain events are a language. Now, if you're using event sourcing, you probably don't want to emit every domain event, because you will have some domain events that are only locally important, they're only important to this aggregate in this bounded context, because they represent a persistent state... Whereas there are other events that will then have an impact on other bounded contexts, so you can put those on a topic, on an exchange, on a Kafka topic, whatever it happens to be. To some extent, I find those mechanisms unimportant or somewhat uninteresting, in that they should simply meet your service-level agreements, your non-functional requirements for getting these things delivered reliably, and if they do that in an expedient matter, it doesn't really matter which one you use.
Joy Clark: How big is the event? I don't know how to really picture it in my head, what's actually saved in an event...?
Vaughn Vernon: Think of a command that is an action on an aggregate, and whatever data is associated with that command to make the command acceptable and valid and occur, we would wanna capture all the data that was part of that command - or probably all of it; maybe not in every single case, but most of the time you would capture all the data from that in the event that in essence if you were to need to execute that command again sometime, you could by deriving the command from the event.
Vaughn Vernon: If you can't derive the command from an event that occurred from it, then you probably haven't represented the event correctly. Now, I'm not saying you should do that, but if you thought in terms of "If I had to make this command occur again, I would want it to have enough data to make it valid, to make it happen again, so I would need to capture that in the event."
Vaughn Vernon: You may decide, for some reasons, to enrich the event, and it's a whole other topic "If I enrich my event, how much should I enrich my event?" One argument says that you should only put very limited information in your event and make clients query back into a read model or a query model to find out what's the additional data associated with this, or it might have to read an entire bounded context level event stream to get a richer idea of what happened or what happened after that in order to get all the data.
Vaughn Vernon: Then there's another mindset that says that you can actually package a lot of data in a domain event because in this way consumers of the domain event need to see the state transfer of that aggregate or entity in their own bounded context, because they don't want to keep a partial state over time and collect upstate; they wanna know at any given point in time what exactly was the state of this aggregate when this event occurred.
Vaughn Vernon: I can see a use for each of those, but I would caution against the second one, because if you do consume events in that way, don't get the idea that you own the data that they're carrying, that they're transferring. Because if you do, then you're in essence sort of causing a power play on who owns the data, and you really should just have one clear authority of that data.
Joy Clark: So I can kind of picture that in my head as long as it's all synchronous, and... One question I have is if you're basing your whole application on a stream of events, what happens if we have concurrency (or something like concurrency) and the events aren't in the right order?
Vaughn Vernon: Well, Joy, you need to attend my talk tomorrow. It's what I call "Modeling Uncertainty."
Joy Clark: Oh, okay. Well, we will link -- I think it will be online by the time this podcast goes live, so we will link that in the show notes for any more interested listeners...
Vaughn Vernon: That would be cool, yes.
Joy Clark: But could you give like a teaser?
Vaughn Vernon: Okay, so let me say this - a lot of the mindset today is... You know, most developers who have been developing software even for 10 or 15 years (or like me, closer to 35), we all grew up pretty much with a synchronous blocking mindset, right? "Call this function" in C, or "invoke this method" in Smalltalk, or... Actually, I got that wrong - "send the message to an object" in Smalltalk, which eventually causes a method invocation inside the object. Or invoking a method in Java or in C# or whatever... And we know that as a client, we're blocking. Oh, doesn't that feel comfortable?
Joy Clark: It's so nice. It's like I have certainty for...
Vaughn Vernon: Yes, I have a certainty; I know that by the time this finishes, the whole world will just be aligned, the stars are all aligned for me, and everything just feels so comfortable... But the world of software development is moving away from that certainty, because as soon as you introduce two bounded contexts - just two - as soon as you start using DDD... I mean, unless you're running in some huge VM, in a single VM, with multiple bounded contexts and everything actually can be synchronous, but you're going to have other problems from that, you're gonna have uncertainty. Things will just happen in ways that distributed computing guarantees will happen, which is actually the completely unexpected, right?
Vaughn Vernon: So in essence, you start building robustness into your software, but what happens -- okay, let me rewind a little bit... So the problem is because all these developers are used to this synchronous life and certainty everywhere, they want to create that in a microservices or a DDD environment.
Joy Clark: Well, it's so much easier to conceptually think about...
Vaughn Vernon: It's so much easier, right? But what you're going to find is you're going to go to a lot of effort, a lot of technical effort to reorder events that you see out of order, or deduplicate events that have already occurred, and once you go to all that effort, you haven't yet solved a business problem. You're just solving a technical problem.
Vaughn Vernon: What I say is embrace the uncertainty and model it. There is actually a business case for saying "We are in a distributed environment. Let's model the uncertainty as part of the business", and what's even better about it is when you model the uncertainty, it's not difficult, and you are accomplishing the core reason for developing the software in the first place, which is your model, right? This is why we have the bounded context, so why not just solve that problem right there at the core of the software of the bounded context, and we're good. I hope that's...
Joy Clark: I think it was a good teaser...
Vaughn Vernon: A little trailer, yes.
Joy Clark: Hopefully the talk will be online, so everyone can listen to that talk after they are done with this podcast. My last question as a wrap-up is what you would suggest for getting started with DDD - resources, or...
Vaughn Vernon: There are a lot of resources out there. Well, a lot more than there was five or six years ago. You have, of course, Eric's book, which is the definitive guide to what DDD is meant to be, but my red book is available - Implementing Domain-Driven Design; Domain-Design Distilled... Okay, you can read Domain-Driven Design Distilled in like -- people who are even half as smart as you, Joy, can read Distilled in like a half a day, okay? So you could read it in a quarter day, I'm sure, and in German, too.
Joy Clark: It is in German now.
Vaughn Vernon: Yes, it is. So that's a resource. I have a video on Safari Books Online. I think you can also buy the video through InformIT.com, and there are other books that have been written now on DDD... And come to a conference where DDD is taught. I teach a three-day workshop, I teach a two-day workshop on introducing technical teams, developers to DDD, and then I have a one-day workshop for paring up with domain experts, business people. Those are some options. Read my blogs...
Joy Clark: Was there any question that I should have asked you that I didn't ask you? Probably...
Vaughn Vernon: I can't think of any, but yeah.
Joy Clark: Okay. Well, thank you so much for letting me ask you all of my questions.
Vaughn Vernon: Sure. I appreciate you inviting me.
Joy Clark: And to all our listeners, until next time.