 Hello, and welcome, my name is Shannon Kemp and I'm the Executive Editor of DataVercity. We'd like to thank you for joining today's DataVercity webinar, Domain-Driven Data, sponsored by IBM. Just a couple of points to get us started. Due to the large number of people that attend these sessions, you will be muted during the webinar. For questions, we'll be collecting them by the Q&A section in the bottom right-hand corner of your screen. Or if you'd like to tweet, we encourage you to share how it's a question via Twitter using hashtag DataVercity. And if you'd like to chat with us and with each other, we certainly encourage you to do so. Just click the chat icon in the top right for that feature. And as always, we will send a follow-up email within two business days containing links, slides, the recording of the session, and any additional information requested throughout the webinar. Now let me introduce today our moderator, Anthony Abdullah, the portfolio marketing manager at IBM. Anthony has been building brands and launching successful products for over 10 years. Throughout his career, he has strived to partner with seller products in order to make them well-known and accessible. He joined IBM to continue doing just that. Anthony is from New England, currently lives in Topfield, Massachusetts with his family, and is an avid runner and aspiring oil painter. Now with that, I will turn it over to Anthony to introduce our speaker for today. And to get us started, hello and welcome. Oh, thank you very much, Shannon, and thank you everyone for joining us today. Hey, there, Shannon said, please don't hesitate to send along your questions. The goal today is to answer as many related questions as possible, so please don't be shy. And of course, we'll be sure to get back to any of that might not make it during the time. So on to some more important details. You know, today, Bradley Holtz, our steam developer advocate from IBM Cloud Data Services, will be instilling his knowledge to help you choose and apply the right data layer for your application. Bradley is a code of America brigade captain up in Burlington, Vermont, and has been the co-organizer of both the Vermont Code Camp and Northeast PHP Conference. Many of you might have already read some of Bradley's several publications on TouchDB, seen him talk at countless conferences and meetups, or heard him on webinars just like this one. He's also doing some really awesome stuff for an offline first development that I'm sure you'll be seeing more and more of. So with that, let's get things going. Bradley, the webinar is yours. Great, thank you very much, Anthony. Thank you everybody for joining us today. So this webinar is a topic that I really enjoy giving because it involves two different topics that I enjoy. One is polyglot persistence, and the other is domain-driven design. So I want to start out by talking about giving you sort of a brief history of data, so a little bit of background on the history of databases and data technologies. So I'm sure everybody here is very familiar with the relational database model, and the big idea is that you have tables with columns and rows, and tables have primary keys and foreign keys. So you can see, for example, here on the slide that I have up, you can see there's an order table, a customer table, a line-ed up table. The order table has an order ID primary key and a customer ID, which is a foreign key, which references the customer ID field over in the customer table. So that's how we get the relational aspect of relational databases. And relational databases have and continue to serve us very well. We've seen relational database around for over 40 years now. It was actually invented in, I believe, 1970 within IBM. And relational databases are a great choice, and they're still very valuable and very useful in developing our applications. One of the reasons why we like relational databases so much is they give us what's called ACID guarantees, or Atomicity, Consistency, Isolation, and Durability. And just to break these down real quick, Atomicity is the idea that transaction must be all or nothing. Consistency means that constraints, such as our foreign key constraints, are always going to be applied before writing data. Isolation means that the sequencing of our transactions will be guaranteed. And Durability means that committed transactions will survive power loss, database crashes, et cetera. And the basic idea here is that it's actually surprisingly difficult to write database technologies to actually create a system that durably and reliably gets our data written to disk. It's actually a very difficult challenge. A lot of us as application developers, we tend to take it for granted. But these ACID guarantees are kind of the building blocks and the basic guarantees that we count on from relational databases. And these ACID guarantees are very important for a specific class of application. And these are kind of our systems of record. So things traditionally would be like mainframe applications or we'll call big iron applications. And so, for example, let's say you had a financial database. Let's say it was a banking application. You want to make sure that if you have a deposit or you'll withdraw from your bank account, you want to make sure that is reliably recorded and stored in a reliable way. And those ACID guarantees are really important in that scenario. Now, something changed, though, with the introduction of the web. And we actually saw a whole new type of application emerge. And this type of application brought with it a whole new set of constraints that were different than the typical system of record constraints that we had seen before. And nowadays, this trend is continued with mobile apps. So we tend to classify these as systems of engagement. So the web and mobile apps and the sorts of applications that you interact with as a customer on a day-to-day basis. So what are some of these constraints that change with the introduction of the web and then also with mobile apps? So a couple of things changed. One was this need to always be on. So if you had, I gave the example earlier, of a banking application. A bank typically holds, has business hours, 9 to 5 Monday through Friday, let's say. And they can take their systems down for maintenance at certain times. They don't need to provide a system that's on all the time. They do need to be on and available during the hours that they're open, but they don't need to necessarily be available outside of those hours. They have options to take things down for maintenance. But web and mobile apps, we expect those to be available all the time. We expect to always be able to interact with them outside of business hours even. Big data. So just the size and the scale of the amount of data that we start to collect. We start talking about web and mobile applications and analytics and all that stuff. So this is a major change in the constraint as well. One way to reason about and think about these changing constraints is with what's called the CAP theorem. And this is just one model. This isn't the end all, the all answer. But it's one useful tool to help us think about these constraints and when we're trying to choose a database, help us pick a database that meets our particular needs. And the basic idea of the CAP theorem is that you can choose up to two of these three properties. Consistency, availability, and partition tolerance. So an example of the banking application, consistency is probably the most important thing. And then secondarily, they probably care about availability. But consistency and availability are the two things that they're likely going to prioritize. But when we start trying to create systems that are always on and that store large amounts of data, we actually need to start creating distributed systems. So we typically need to actually start storing our data across multiple nodes of a system. And as soon as you have multiple nodes, you have the possibility of there being a partition, meaning that two nodes, two or more nodes are not able to talk to each other because the network can't be 100% reliable and there's a possibility of nodes becoming disconnected. And so in that situation, we need to decide, do we give up availability or do we give up consistency? So oftentimes, a lot of applications will choose to give up consistency and to keep availability. So they can have a system, even if two nodes can't talk to each other, they'll still take reads and writes and then deal with conflicting updates later when the two nodes are able to communicate with each other. Instead, you might choose to prioritize consistency and partition tolerance. So in this scenario, when two nodes can't talk to each other, you actually stop accepting writes. That way you can guarantee that you have a consistent view of the data all the time. But that means if you are no longer accepting writes to the system, you are no longer available. So in this case, we are choosing consistency and partition tolerance. So again, this is just one model and one way to think about it. But choosing up to two of these three, consistency, availability, or partition tolerance. So I mentioned a few terms a moment ago. Now one of those terms is this idea of horizontal scaling. And this is the idea of adding additional nodes to our system through commodity hardware or scaling out through commodity hardware. Typically with a typical mainframe sort of application or like a typical business application before horizontal scaling was introduced, the primary way to scale was through vertical scaling. And vertical scaling just means that you're getting a larger and larger server, maybe more RAM or more hard drive space. But the problem with vertical scaling is that you're limited by the maximum server size available. There's an upper limit to how big a server you can actually buy. So horizontal scaling lets you add more and more nodes and get more and more capacity by adding those nodes. But of course then you have to deal with that possibility of there being a partition. So you need to deal with partition tolerance. And the goal of horizontal scaling is that each server that you add adds the same amount of capacity as the previous server. That's called linear scalability. So no system achieves true 100% linear scalability, but that's the overall goal with horizontal scaling. And I also mentioned the eventual consistency. So the basic idea of eventual consistency is that given no new updates, each node in a distributed system will eventually have a consistent view of the data. Now, this never typically happens. We don't ever actually stop updates, but it's a theoretical way to think about it and help us understand what we mean by eventual consistency. And the thing to keep in mind with eventual consistency is that eventual is relative. So eventual in some systems could mean within milliseconds or could mean hours. For example, in the case of domain name system, DNS, updates can take up to 48 hours often. So that's the example of an eventually consistent system. But eventual consistency could mean milliseconds. So don't assume that this means it's going to take a long time for updates to propagate. It just means that you need to account for the possibility that things are not going to be consistent within your system within some frame of time. So to address these changing constraints and to deal with this new type of application that we're calling the systems of engagement, that's where these NoSQL databases came into play. And I personally am not a huge fan of the term NoSQL. I prefer to think of NoSQL as meaning not only SQL. Because to me, I hear NoSQL as almost implying that there's something wrong with SQL databases, and there certainly isn't. But for me, NoSQL means let's consider other options. So given any particular problem that we have in front of us, let's not assume that a relational database is necessarily the right choice. But let's take a look at these other types of databases that exist and see if one of them might be a better fit for the problem that we're solving. So it's this idea of not only SQL or sometimes called polyglot persistence. And there are a whole bunch of different types of NoSQL databases out there. There's key value stores, document databases, graph databases, and there are other types too. I'm just going to mention a few of them here. But there are others available as well. So in the document database category, you'll see things like CouchDB and MongoDB. Those are two popular document databases. In the key value store area, you'll see Redis and React. Those are some open source key value stores. Graph databases, Neo4j, Apache TinkerPop. And then you get into things that aren't necessarily databases, but sometimes are used as databases or alongside the database. Things like Lucene Solar and Elasticsearch. They can provide free text search capabilities and things like faceted search. And then oftentimes you have the need to do analytics, either batch or streaming source of analytics on your data. And you'll see things like Hadoop and Spark into the mix. And these are just a small sampling of the open source technologies out there as far as database and data analytics tools. There's a huge number of them available today for you to pick from. So I just want to talk a little bit about each of those three types, the key value, starting with the key value store. The basic idea of the key value store is that you have opaque data accessed through a unique key. So you can get at a specific set of data, and the database doesn't care what that is. It could be some piece of binary. It could be text. It doesn't care what's in it. It just knows, okay, at this key, there's this data that's stored. And the cool thing about key value stores is they can offer very fast read, write, and access. So they're good for things like caching or for highly variable data. But the downside to a key value store is that you typically can't query against the values in the database. So you can only do range queries or query for a specific key. You typically can't dive in and actually query against the actual data stored underneath those keys. And that's where document databases are really helpful. So document databases are actually a variation of key value stores, but where the value is more strictly defined. So typically, in the case of, say, for example, CouchDB and MongoDB, we actually have JSON objects or how the documents are stored. In the case of MongoDB, it's actually binary JSON, but they're very similar. And the great thing about document databases is that not only can you do queries against the keys, like range queries or select for specific keys, which we call the primary index. We can actually create secondary indexes derived from the values. So we can actually reach into the data and query against the data stored in those documents. So they give us the ability to do that sort of queries, which is very helpful. So document databases tend to be a good fit for modern web and mobile apps, just because the document model tends to be a good fit for those sorts of applications. And then finally, graph databases. So this is based on graph theory, in which we have nodes and properties connected through edges. And these are things like a street map can be represented as a graph. So for example, driving directions. You could do product recommendations. So people that bought this product also bought this other product. Of course, social networks. So friend of a friend. If I know this person, do they also know this other person? How close do they are? Are they on my social network? Or six degrees of Kevin Bacon, for example. That's a graph database problem. So graph databases have a lot of uses as well. So now I want to switch gears a little bit. I'll talk a little bit about domain-driven design. And I think that there's a lot that we can learn from domain-driven design, that we can apply to polyglot persistence, and that we can apply to choosing and designing the databases and data technologies that we use in our data layer for our applications. So domain-driven design is a book. I believe it was written in 2003. It was written by Eric Evans. And for me, it was a really transformative book to read as a software engineer. Of course, I had understood object-oriented programming and design patterns and all those things. But for me, this book, domain-driven design, was really kind of brought all that together for me in a whole new way. So I would definitely recommend folks check it out if you haven't already. So a lot of talks about domain-driven design will focus on the technical aspects of domain-driven design, which I'm going to do here as well. And they'll focus on the design patterns and the architecture and those sorts of things. But I think it's important to step back and recognize that at the core of domain-driven design is this idea of collaborating between domain experts and software practitioners. So this is the most important aspect of domain-driven design, is to actually sit down and work collaboratively with domain experts. So these are the people who actually solve the business problems, who understand the business problems, the people that actually understand why your business exists and what your business does. And help them or work together collaboratively to actually create the software that addresses those domain needs. And one of the core concepts of domain-driven design is that complexity is in the domain, not in the technology. So as technologists, it's really easy to focus on technical complexity and the things that are complex about the technology that we're using to solve problems. But if we step back and we look at most business applications and most enterprise applications, we're actually solving complex business problems. And we really should be focusing on that complexity and how do we tackle that complexity, not the complexity that we're adding arbitrarily with the technology that we're using. Another concept is this idea of using models as tools to solve problems within the domain. So we create models. We work together with our domain experts to develop these models. And we think of these models as tools. And we exercise these models to see if they actually solve the problems that are within the domain for which we're building the software. And it's important, when we're thinking of models, to not confuse models with reality. In philosophy, there's this idea of map-territory relationship. And it's basically this idea that the map is not the territory, that when we create a map, we're not trying to replicate the entire territory. We're trying to create a model. We're trying to create a set of tools to solve problems within the domain. So here on the screen, you'll see a subway map. And with a subway map, they don't try to recreate the entire geography of the area. They put all the stops on a simple line. And they don't even necessarily put the stops relative distance even. Because as someone writing the subway, the problem you're trying to solve is, I'm trying to get from one stop to another. And I need to know, am I on the right line? How many stops is it from the subway stop that I started on, for example? So I'm trying to solve a specific problem, and this is a simplified model that helps me solve that problem. And I think this is especially difficult in software because I think when people learn object-oriented programming, if you think back to when you learned object-oriented programming, there were probably examples like animal or car. And we thought of these as we actually had one-to-one mapping with things that were in reality. And that's not really what we're trying to do here in domain driven design. We're trying to create models to solve problems. Okay, great. So now I want to dive into some of the architectural aspects of this. So there are some building blocks within domain driven design that help us practice domain driven design. And I want to look at a few of those building blocks. There's a lot more to domain driven design than I can get into in this session. But I'll try to hit on some of the key points that are important and relevant to choosing your domain layer. So one of the basic patterns is this idea of entities. So entities are defined by their identity. So for example, a person might be an entity in your domain. So if there's a clear way to identify it, it's probably an entity. And then we have value objects. So value objects are things like a number. So it actually has – it doesn't have an identity. Its identity is wrapped up in what it is. It describes something. And we want to treat value objects as immutable. So for example, if we have a number, we don't change the number. We get rid of the number and replace it with a new number. That way we can safely pass these value objects around the system and not worry about bugs being introduced by changing them. And then aggregates. So what we do with aggregates is we actually group related entities together. So we actually end up with a graph of entities that are related and then the value objects that are referenced from those entities as well. And we actually do this – we do this to minimize complexity. By grouping aggregates together, we can reason about – sorry, by grouping entities together into aggregates, we can reason about the aggregates versus trying to reason about every entity individually. And what we do is we actually designate one entity as the aggregate root. So whenever we update an entity, whenever we retrieve an entity from the database, whenever we're working with an entity, we actually get at that entity – sorry, whenever we're working with an aggregate, we get at the entire aggregate through the aggregate root, through one entity that we designate as the root of that aggregate. And then from a data point of view, we want to update our aggregates synchronously. So the entire aggregate should be updated together. In the case of a relational database, for example, that might be transactionally or it might not be transactional. If it's not a relational database, there might be another – you might not have to make everything transactional, but you want to think of it in terms of a synchronous update. And then repositories. So we use a repository to actually – the goal of a repository is actually to provide an in-memory illusion of an in-memory data store. So I mentioned the aggregate root. So we would pass in the entire aggregate starting with the aggregate root to a repository and say, store this in the database for me. And then it would provide the illusion of an in-memory data store. Even though it's actually storing it in a database, we have an API that looks like it's in-memory data store. And same thing when we're retrieving it. We say, give me this aggregate starting with this particular aggregate root entity, and that will get the entire aggregate out of the database for us. But as a programmer, the API looks like an in-memory – it appears to be an in-memory data store. So the cool thing about a repository is it gives us this nice abstraction, this nice abstraction from mapping – data mapping to our domain layer. So we can create a nice, clean domain model. There is, of course, a catch for this, which I'm going to get to in a little bit. But that's the goal, at least. So this next slide, I've got an example of an architectural diagram. So I want to spend a little bit of time on this and maybe pause if there are any pressing questions on this particular diagram. But I want to walk folks through this. So we'll see there's an order on the top left – order entity. And the order entity – the order is an entity within the order aggregate, and it is actually the aggregate root. So we're going to treat that as the aggregate root for the order aggregate. Customer is another entity. I don't fully show all the details of customer here, but that's another entity in this particular diagram. Date, line item, and money – those are value objects. Here you see there's a domain layer and an infrastructure layer on this chart. There's also – I'm not showing here – there's also an application layer and then a user interface layer above that. So there are actually four layers in total – this infrastructure layer, domain layer, application layer, and user interface layer. But for the purposes of what we're talking about here today, we just care about the domain layer and the infrastructure layer. And then you'll see the – on the right hand side, you'll see the order repository interface. So this is that in-memory illusion, this illusion of an in-memory repository, so we can actually insert orders, update orders, find orders by ID, get recent orders, et cetera. So notice that we're doing this through the aggregate route, through the order aggregate route, which will bring with it the customer and the line item and all these other things with it. An interesting thing to note here is that we put the order repository interface within the domain layer, but then we actually have an infrastructure layer in which we place the implementation for those repositories. And then we have an in-memory and a relational mapper order repository. And the benefit of the in-memory one is we can actually use the in-memory repository for unit testing. So we can actually – we don't actually have to have any database underlying this at all to begin with. We can explore a domain model, write unit tests, change code, update things, completely rework our models as we work without ever actually having to – needing to go to an actual on database. So we just create this in-memory order repository. But then at some point we create one to actually store in our database. In this case, there's a relational mapper order repository, which actually stores our data in a relational database. In this case, we're using a relational database for this particular example. And you still aren't using some sort of data mapper or object relational mapper or M to implement the repository, so that might not be all there is to it. But this is the basic idea. This is a simplified diagram. But I just wanted to pause here and add enough if we had any pressing questions at this point. No pressing questions at this point. Someone was just interested in your diagram on the aggregate slide, but someone had answered saying that it is actually an object-oriented design showing relationships between the classes in the domain. Yeah, that was actually just more an illustrative photo. I wasn't trying to communicate any particular architecture with that photo. It was really just to get at the concept of grouping things together into aggregates. Okay, so given all that, and you're thinking about this from a domain-driven design perspective, let's talk a little bit about how we might choose the right data layer for our particular application. So I remember I said a moment ago that the repository provides the illusion of an in-memory data store. So the problem is that that illusion is a little bit shaky, because we actually can't fully abstract away the constraints of our data store. So we can't just go, okay, well, it's a relational database, and we're going to swap it out with a graph database, or we're going to swap it out with a document database. It's not necessarily that simple because the actual underlying constraints, for example, I talked about the CAP theorem, does this database provide consistency and availability, or does it provide consistency and partition tolerance, or does it provide availability and partition tolerance? Those are very different databases, and we can't necessarily abstract all that away because it has implications for how we group our entities together and how we design our aggregates and how we design everything. So while we're trying to create a nice clean separation between our domain model and our data layer, it's actually not entirely possible, and we do need to think about the data layer, and that does ultimately have an impact on how we design our application. So we don't want to think of the repository as completely abstracting this for us. It's just one tool to help us stay focused on our domain layer while we're building our domain layer. So one example of a common problem that you'll see is the object relational impedance mismatch. This is because object-oriented languages use a very different model than relational databases. Those are two different models, and when we try to store our object data in a relational database, things don't always map so cleanly. So sometimes that sometimes becomes a problem, and things like ORMs and data mappers can help a lot with that, but we still see a little bit of a mismatch there, typically. So I really love this quote from Eric Evans. He's the author of the domain-driven design. He said, this is the world of no SQL to me. We can choose a tool that fits well with the problem we're trying to solve. So I think that we have this world of no SQL. We have all these options out there, and which one is going to work best for our particular application? So looking at another concept from domain-driven design is the idea of strategic design. So this is when we started thinking about teams and systems and how we actually have multiple models and we have these very complex systems and we need to really be strategic about how we design the overall system. And one tool that's really helpful in this is this idea of a bounded context. And what the bounded context does is it allows us to actually have different domain models within different contexts. So, for example, a person might not always mean exactly the same thing in different domains. One domain may mean one thing, and another domain might mean something slightly different or something completely different. What does a customer mean? Again, that could mean something different in a different domain. So bounded contexts give us a space in which we can have a clean model. We can say a person means this within this context. So they help us create this separation and give us this idea and this is the opportunity to actually have different models, which is likely going to be the case in a complex system. So one thing that I would recommend from a database point of view is to only have one data layer per bounded context. So basically you want to make sure that any database that's being used within a particular bounded context is not also being shared with code in another bounded context. So you don't want to be reaching into a different database that's written in code represented in a different bounded context. Because the point of a bounded context is that different models can mean different things. And if you have one database, that applies that you have a shared meaning, which violates the entire purpose of having a bounded context. And even if it does mean the same thing, even if a customer in one bounded context means the same thing as a customer in another bounded context, that might be true today, but that might not be true tomorrow. And as soon as you share that data together in one database, there are going to be problems as soon as those meanings start to vary and diverge. And I said the point of view is a data layer. And the reason why I said data layer and not database is that oftentimes these days, we actually don't just have one database underneath our system. We actually have entire data systems, which are multiple databases, potentially data analytics tools, and they can get quite complicated. So that's why I say data system and not a solid database. One way to really help crystallize this and make it a lot, bring it a little bit down to earth a little bit more, is to think about this in terms of microservices. So the idea here is that every bounded context is represented by at least one microservice, and there potentially might be multiple microservices within a bounded context. So each bounded context is written into code and deployed into your environment as either a single microservice or a cluster of microservices. So here's an example of a fictitious application. So here we have three different bounded contexts, a catalog, shopping cart, and orders. So a catalog could be a microservice or it might be a set of microservices. Shopping cart is a microservice or, again, could be a set of microservices. Same thing with orders. So at least three different bounded contexts, at least three different microservices. And underneath each of those bounded contexts, we're actually using multiple database technologies. So for example, underneath the catalog, we might be using a document database to store our product catalog. So what are all the different products we sell and we have to offer? We might be using a key value store to cache data to produce increased performance. We might be using a graph database as a product recommendation engine to say when someone's looking at a particular item to recommend other things that they might be interested in, because they're either related or because other people bought similar items. And then, of course, you might use some sort of full-text search engine to provide the ability for people to search the catalog. Then we go to the shopping cart. We might use a document database in the shopping cart to store things like a wish list. So if people want to store a wish list for later or to share with friends and family, we might use a key value store for the actual shopping cart. Then we get into orders. We might choose to still use a relational database for our underlying order system. And then we might do things like big data analytics using something like Apache Spark to do analysis on those orders and to look for trends and to try to see if we can do predictive analytics on when they expect certain orders or what sorts of things people will buy based on the time of the year. So this is, again, this is just one fictitious example here, but this idea of multiple-bounded contacts, multiple microservices, and then using a data layer made up of multiple database technologies within that data layer. And one thing I want to note before we wrap up is that IBM Cloud Data Services, we have this initiative we call Open for Data. And the basic idea is that we actually have many of these open source database technologies that I've mentioned today. We actually offer as fully managed data services. So things like IBM Analytics for Apache Spark, Cloud, which is a document database, a number of other technologies as well. So these are all managed, fully managed databases and data analytics tools as a service. If you want to add anything, Anthony? No, I think it sums up that previous example. I think perfectly giving that chance to merge open source databases easily with analytic tools and giving developers and data scientists a chance to work together or be one of the other. Exactly. Yep, great. Cool. So these are the image credits for the various photographs and such that were throughout the presentation. And at this point I think we want to open the floor to questions. Yeah, that sounds great. There's a couple in the chat and feel free to ask any more as we're going through these. One back to domain driven design. Is that something that is best when you're creating a new app or can you apply that to apps that are already existing? Great question. Great question. So it can be applied to either. So if you're dealing with an existing application, you really want to pay attention to the strategic design aspects of domain driven design. So strategic design, one of the things that starts with is actually doing it what's called a context map, where you actually look at, you actually don't try to design out what your boundary context should be. You actually look at what your boundary context effectively are based on your current situation. And then there are actually a bunch of patterns and approaches outlined in domain driven design as to how you can refactor it and move towards state that you'd prefer the application to be in. But that whole section on strategic design addresses the issue of existing applications. But certainly it's certainly applicable with new applications as well. All right, cool. And, Aron, in the same lines, how do you deal with foreign key constraints and the needs of those across domains? Okay, so the question, yeah, so about foreign key. So let's say, so I think the question is if you have a boundary context and you want to have a reference across those different boundary contexts. So if you have a foreign key constraint, that's because you want to have a consistent, you're trying to create a level of consistency in your data. So likely if you have a foreign key constraint, that's going to dictate that all those entities that are represented are probably going to be in the same aggregate. And they're certainly going to be in the same bounded context. Now, if you need to have references across contexts, you would not want to use a foreign key constraint. You wouldn't want to do at the database level because you don't want to share your databases across the boundary context. There are different strategies for how you can actually connect boundary contexts together. Those are also aligned in domain driven design. But there are things like customer supplier relationship, for example, is a pattern where you have an API and you say we're providing this API to this other team if they'd like to use that. So this is especially applicable in like a microservices context. So you might have like one microservice that provides the meaning of a customer and lets other microservices and different boundary contexts do lookups to it, and then you might want to translate what that customer means based on which boundary context you're in. But you wouldn't do that at the database level across boundary contexts is the short answer. All right. I hope that helps. This one goes back. It's kind of more of a statement, but let me see if I can make it more of a question. It goes back to your points regarding eventual consistency at the beginning. And I think it's more towards the point of the eventual consistency could mean milliseconds or days. But do you see a lot of preconceived notions in regards to that? People thinking it's not as common as it is when it's in reality it's a lot of industries like banking and airlines and things like that. Yeah, I think that people think they need consistency a lot more often than they actually need consistency. I think there are many applications where eventual consistency is just fine and that you don't really – you think you need the consistency. You think that things need to be always consistent state of things. But if you're building a web application, for example, you're already on the web and the web itself is an eventually consistent environment because of things like caching. So there are already eventual consistency issues outside of your control, outside of the control of your application. So trying to chase a 100% consistent system in that context doesn't necessarily make a lot of sense because things could be distributed and cached anyways for the end user. All right. And honestly that looks like the last 70 questions. Anybody else have anything else before we do wrap up? You're just so incredibly concise, Bradley. Do you see that customers as opposed to developers will be able to afford these types of applications beyond the initial cost of building the application? I'm not sure I totally fully understand the question. So the customer understand the customer affording it versus the business. I think in general what I would say – I think probably what the question is getting at is that this sort of technique, the domain-driven design approach is for complex systems. It's most valuable applied to what's called your core domain, which is the reason – core domain is basically the reason why your business exists. So it's in an area where there is an incredible amount or at least the largest amount of value in the first place. So it's worth the investment of the resources to apply this approach. If this is something that's not your core domain or something that's less critical to the existence of the reason why your business exists in the first place, these techniques might not make as much sense or might not make as much sense to invest as much resources into approaching things this way. Okay. Let's see. If we're using schema.org control vocabulary using JSON-LD syntax, where would we store the JSON-LD for sharing data specifications among data engineers? That's a great question. I don't have a good answer to that. I would say that something like CouchDB, which is what Cloud was based on, allows you to store JSON. So you could certainly store those schemas as documents within CouchDB or Cloudant as a starting point. That's one option, but other than that, I don't really have a great answer to that question. Okay. What recommendations do you have or how to document or model the data layer for various implementations? Conventional modeling tools aren't really up to the task. Yes. Modeling tools. For me, one of the things that I think that if you're practicing domain-driven design, you are working closely with a domain expert, and I think that one of the approaches in domain-driven design is to actually write unit tests as a way to explore code. Like I said before, you have the in-memory adapters. So you're actually writing code and you're writing it using what's called a ubiquitous language. So you actually have a shared language that you speak with a domain expert that you're collaborating with. So as you write code and you write unit tests and you exercise your models written in code, you can actually speak that language and speak that language to your domain expert. So actually, when you're collaborating with a domain expert, you don't want to share with them architectural diagrams or that sort of thing. I'm not that they're not valuable in that context, not necessarily the sort of approach you want to take. You really want to speak this ubiquitous language and really express concepts from the domain itself, when they want you're building the software. All right, cool. I've got a couple more coming in. Would bounded context apply to business units within a company, such as the sales marketing ordering? It very well might. I mean, there's certainly a lot of thought that needs to go into where the bounded context actually apply. I think one way to look at it, I think a lot of times it's looked at as a technical problem. But I think if you look at it from a team point of view, it makes a lot more sense. Like how are you breaking down your software development teams? So typically, your bounded context will actually follow the contours of your development teams. So if you have a separate software development team in marketing and a separate development team in a different department, then sure. But I'm guessing that's probably not how it breaks down. It's probably a little bit more nuanced than that. Okay, and back to consistency. Do you find that industries subject to government regulations like banking, finance, and marketing require a certain state of consistency over others? That's a great question. I would imagine that is probably true. I don't know that for sure, but I would assume that's probably the case. If not, there are certainly other constraints in place directly or indirectly in those environments. So I think that that's where that system of record versus system of engagement breakdown can be really helpful, because you can say, okay, system of record, we need to follow these constraints, and they need to be consistent and all that stuff, even if it doesn't really need to be, but there's a regulatory reason why it needs to be. But in your systems of engagement, do you need that? For example, if you're creating an app, a mobile app for users to engage with your company, does that need to be consistent, at least in the same way as your main regulated application? So I think there might be opportunities in the systems of engagement that you don't necessarily exist with the systems of record to not have to worry as much about consistency. Chris, and just another one, just clarifying the definition, what is meant by domain in domain-driven design. You know, related to the concept of domain in modeling, or I know you spoke about business domains. Yeah, so yeah, exactly. It's more of a business domain. It's like a sphere of influence. It's like a particular, like let's say you're a shipping company. Your domain might be shipping, because that's what you do. You ship stuff, and there's a whole of this complexity in how things move around through ports of entry and how things move around. Like, are they going on cargo ships? Are they going on train? And does the cargo need to go into containers and all those logistical complexities that go with being a shipping company? That's what we mean by domain is what kind of area, what are the actual activities and the specific things that your business does? And there's probably a lot of complexity. If you're at all mature business, you probably have a decent amount of complexity in the actual things that you do as a business. All right. Let's see, going back to one of the technical inconsistencies. How would you reconcile consistency of data layers across bounded contexts for specific application purposes, such as the need for global consistency in many cases for cross application analytics? So I think the thing is that if it absolutely needs to be consistent, and there is no margin and that is absolutely true that it needs to be consistent, then it can't be in a separate bounded context effectively. At least I don't know of any good way. Maybe I'm wrong, but I don't think that would be possible. So I think one approach might be to have a third bounded context, which is your analytics context. So let's say you have business analysts whose job it is to look at the data and make decisions based on the analytics. Those business analysts are actually, and that activity of business doing that analysis and analysts, sorry, I can't speak to the word, would in fact itself be a domain or a specific domain in which, and that could be represented by a bounded context. So within that bounded context, as the data flows into that that you're analyzing, it's going to be consistent as it flows into it. It might be eventually consistent across those bounded contexts, but within the context of the tools that the data analysts use, it could be consistent within that context. Okay. And it looks like that might be wrapping up our questions. Bradley and Shannon. Great. Well, thank you, Bradley, and thank you, Anthony, so much for this great presentation and Q&A section. And thanks, as always, to our attendees who engage in everything we do and for the great questions and just love to engage with their just reminder and to answer one of the more popular questions. I'll be sending a follow-up email within two business days to all the registrants with links to the slides, links to the recording of the session, and anything else to request that was requested throughout. And again, Bradley and Anthony, thank you so much. And thanks to IBM for sponsoring today's webinar. I hope everyone has a great day. Yes, thank you, everybody. I appreciate everyone participating today. And thank you, Shannon, and thank you, Anthony. Thank you, everybody. Take care.