Skip to main content

Finding service boundaries, illustrated in healthcare

Udi Dahan shows a case study from the healthcare domain resulting in services so autonomous they almost don’t have to share any data with each other.

🔗Transcription

00:05:28 Udi Dahan
I thought they were just going to let that song play and play, and play all the way through. One of those songs just keeps looping and looping, and looping. A great song though. Good morning everybody, welcome. My name is Udi Dahan, and today we're going to be talking about how to find service boundaries when you're doing service-oriented architecture. I'm going to start with more of a broad element of what service-oriented architecture is, what it isn't, how to do it, how not to do it. And then towards the end, I'm going to give some more concrete examples from the domain of healthcare because it serves as a nice contrast to a lot of the traditional examples that I've given in the past about retail where a lot of us are familiar with.
00:06:15 Udi Dahan
It serves as a nice counterpoint for people that when going to do service-oriented architecture, you can't always just use the same solutions that you might've seen presenters like me talk about onstage. So for those of you who are on Twitter, please feel free to ask questions @UdiDahan. And after the talk, I'll try to get to them. Also, if you're interested in more information about his topic of finding service boundaries and service-oriented architecture, I have some video access cards over here, so come up to see me at the end. There are two days worth of videos that you can get access to that talk a lot more in depth about these sorts of topics. So if you want that, come up and see me after the talk.
00:07:01 Udi Dahan
So what are we going to be talking about? AT the beginning, service-oriented architecture, those three little letters that have drove everybody crazy for roughly the past 10 years until we got over it. And now there's this new micro services thing, which is bringing SOA way back to the forefront again. So if you are interested in hearing about microservices, there's a guy called Sam Newman who's going to be giving some talks about microservices later on today, recommend you take a look at that stuff. So after going through the highlights of SOA, we're going to be talking about the problem domain of healthcare, what's special about it, what's different about it, things that hopefully you have never experienced firsthand. I hope and wish you all the best of health, but sometimes we do need to get involved in that. So cover some of the elements of the healthcare domain just so that you can understand some of the challenges in finding service boundaries over there. And in what ways it's different from say the more general SOA stuff that I'm going to be talking about at the beginning.
00:08:09 Udi Dahan
And at the end, I'm going to round it off with some pointers to solutions and things that are different about applying SOA to different domains. Hopefully we'll be able to take away and use on your systems. So let's jump right into the stuff that you've probably all heard a million times before, the tenants of service orientation, services being autonomous, having explicit boundaries, et cetera, et cetera. You've probably seen that kind of stuff before. The thing about services is the word itself is actually meaningless, and that's what confuses people. Because the word service implies that there is this thing that is giving service to something else. It implies a client server type of relationship between code. There is the server thing that offers service, and then there's the client which consumes the service. Unfortunately, that's not really what service orientation is about. When we say that services are autonomous, we're going to be giving some examples of what autonomy actually means. But just from the English language, autonomy means self-governing.
00:09:24 Udi Dahan
The issue that we run into when applying, say traditional client server paradigms to service-oriented architecture is not when you just have a client talking to a single server, but when that server ends up becoming a client of other servers. So kind of that service A calling service B calling service C. And that's where the challenge is because if you're doing synchronous request response communication from one server to another, in essence, the threads, the memory utilization of your server now become dependent on how quickly you get a response from those other servers. And it's hard to say that you'd really be autonomous, self-governing if you're so dependent on external resources to do whatever you need them to do. Now, one of the things that is important out of this, tenent number three that I quickly skipped over. Services share contract and schema not class or type. It's not just not class or type, it's important that they don't share class or type or anything else for that matter, specifically no shared database.
00:10:39 Udi Dahan
So other than an agreement on communications, nothing else. If you see multiple services that are talking to the same data store, that's usually an indication that there is some hidden coupling between them. That rather than talking directly to each other, there's this, okay, I'll just put some stuff in this database and you pick it up and do something with it. And we've all felt that pain before that we go change something in a database schema that we thought was entirely our own, and then we find out that we broke somebody else's code that we didn't even know that they existed. Now, when I say share contract and schema not class or type or anything else, don't go wrapping up that shared database with yet another service. Introducing another layer of indirection is not going to change the dependencies. So be really aware of any shared resource because that tends to hide coupling. Model all of the coupling that you've got explicitly in the form of your message schema.
00:11:47 Udi Dahan
So in terms of a definition, the issue that I have with the traditional service lingo is that people still view it as if it were run-time component. Nothing about the definition actually implies that a service is a run-time component. So I'm going to give you a slightly different definition that hopefully will clarify the purpose of a service. A service is the technical authority of a specific business capability. The reason why we talk about business capabilities is that it's important for us to have alignment between our problem domain and our solution domain. If we go and create a service-oriented architecture where everything seems technically sound but there is no alignment whatsoever with the problem domain, then that's going to cause a problem, and we're all aware of that. As we go forward, we'll see just how difficult it is to find good alignment between the problem domain and the solution domain.
00:12:48 Udi Dahan
Now, when we say that something is the technical authority, that's that word of autonomy, of explicit boundaries, of making it really clear what's mine and what's not mine. What comes out of that is that the data and the business rules that are part of fulfilling a given business capability must reside within that surface. For it to be the technical authority, it has to own that fully and completely, meaning nothing else can come in the back door and say, yeah, I just need a little bit of data over here, let me just grab that data from your database and change that field over there. That's not autonomy, that's not encapsulation.
00:13:34 Udi Dahan
So when applying these principles of autonomy, of encapsulation, of service-oriented architecture, what we end up seeing, and this is a very important element of it, is that after you've divided up your solution into services, that nothing is left over, nothing is sitting outside of all of the other services. Because ultimately for a piece of code to exist, for a piece of data to have a reason to be there, it's to serve some business capability, which means there must be some service that is responsible for that business capability. Meaning it's responsible for that data, for that configuration, for those business rules. Everything must be in some service. That's how we end up with high cohesion, that's how we end up with loose couple.
00:14:27 Udi Dahan
Now, the problem is that a lot of things that people call services don't really fit this definition. For example, a service that has only functionality. It's a function not a service. For example, calculation or validation, you can tack the service onto the end of it, and I know lots of people do. This is a calculation service, a persistent service, a UI service, whatever service. Just use the word service to tack it on to something to make it sound more important. But when doing software architecture as a rule of thumb, what you're going to want to do is be really clear as to what it means when you use a word. So if you have something that's just a function, that's fine, call it a function. This is a calculation function, a validation function. But in those cases, really ask yourself, what's the incremental benefit of having this be a remotely callable function. Usually when people use the word service, that's what they mean, it's remotely callable.
00:15:41 Udi Dahan
Is that really in your interest to make this function remotely callable given that we know that at a network level, so many bad things can happen? We can have HTTP timeouts, we can have latency issues, we can have bandwidth issues. All sorts of bad things can happen once you try to cross the network. So you should really ask yourself, is there any advantage in making this function remotely callable? But even if there is an advantage and you say, "All right, we're going to make this function remotely callable because it's very CPU intensive, and we want to offload that from the rest of the system," that's fine. Still doesn't make it a service, makes it a remotely callable function distinguished between your logical architecture and your physical architecture. Services are about the logical architecture. The physical deployment, that's a totally other thing.
00:16:34 Udi Dahan
Other things that are called services that aren't, service that only has data where the entire rest of the functionality is create, read, update, delete of that entity's data. A lot of times they see this when people create restful services, so create a restful service per entity. And they say, and of course, the rest guys are like, well, there you go. You've got your HTTP PUT, POST, GET, DELETE. There is your create, read, update, delete. Once again, not a service. If all it has is data, it's a database. Guess what SQL can do. SQL insert, SQL update, SQL select, SQL delete. You do not need to rap SQL with HTTP. SQL is interoperable enough by itself, believe me.
00:17:30 Udi Dahan
And then there's that whole thing of, well, it's a service, let's make it remotely callable. Guess what, databases are already remotely callable, you do not need to put another layer of remote call ability around the database. So if it's a database, just let it be a database. Don't try to call it a service, do not go and create layers upon layers of abstraction around it. So really try to be careful with where you introduce HTTP, where you're introducing any kind of network call, why you're doing. Majority of the time, this element of remote call ability is not as great as most people portray it to be. All of these remote calls come with a very high overhead. And from a loose coupling perspective, they don't actually change anything. So when looking at your services, don't necessarily look at them from the perspective of anything can be a service or a microservice, if that's the word that you prefer to use.
00:18:36 Udi Dahan
Instead, when we say services are autonomous, what that means is one service will be loosely coupled from another service. And when we look at our code bases and we say, "Well, how does the coupling actually flow?" A very good way of identifying service boundaries is looking at the necessary coupling in your code base. What things have to talk to each other versus what things don't really have to talk to each other? And this is where we introduce the traditional layered architecture. What we end up seeing in almost any element of layering is that layers have to talk to each other. UI layer talks to the API layer, talks to the business logic layer, talks to your data access logic layer, talks to the database. It's really rare to see layers not talking to each other. Layers are fundamentally coupled to each other. Ergo, trying to make them loosely coupled by introducing more layers in the middle, it's not really going to help.
00:19:42 Udi Dahan
How can I prove to you that these layers are tightly coupled to each other? Who when the business came to them and asked them to add another column to a given field had to touch more than one layer in their code base? Raise your hands, please. Okay, everybody is raising their hands. This is how you know your layers are coupled to each other. If you make a change in one layer and you need to make a corresponding change in other layers, that's what coupling is. Introducing more layers in the middle is not really going to help. And remember what I said before, sometimes developers say, "Oh, okay, well, there's a very simple solution to that. We'll just chuck everything to a common database. So we won't actually call through layers, we'll just zoom directly into database and get back what we need." Be careful about hiding coupling, hiding coupling never goes over that well.
00:20:41 Udi Dahan
So if we've got coupling between the layers, where do we find autonomy? Well, one of the things that we see in terms of autonomy is that different pieces of UI don't actually depend on each other that much, and different pieces of business logic within the same layer don't always depend on each other that much. In other words, when we actually look at how the code couples itself to other bits of code, what we see is a lot of the loose coupling is actually hiding within the layers rather than between the layers. And what we can start looking at is saying, well, what if we can partition our system instead of horizontally into these layers vertically into these larger strips? So we've got a certain set of data with data, access logic and business logic and UI on top of it, that stripe is tightly coupled to each other. But how coupled is it to all the things around them?
00:21:47 Udi Dahan
Now, here is where actually looking at things all the way up into the user interface can really help. So for example, instead of looking at your UI as a layer, think of your UI itself as a kind of composite, as a kind of shell in which we've got these, for lack of a better term, micro views that are all laid out side by side. So in say traditional amazon.com product catalog type of setting, we've got information about the names of the books, the author of the book, the image of the book, the price of the book, the inventory of the book, et cetera. Yet, when we look from a coupling perspective, we say, well, what level of coupling do we have between the name of the book and the price of the book?
00:22:42 Udi Dahan
Well, fundamentally they need to be connected to the same book, to the same identifier, but there really isn't any logic that spans the price of and the name of the book. When going to identify service boundaries, look beyond just your entity boundaries. Sometimes you can find loose coupling by splicing apart a given entity. One of the ways of verifying do I actually have a possible boundary here is double checking with your business stakeholders for what I call requirements versus anti-requirements. Requirements are things that the business know that they want. Anti-requirements are things that the business is sure that they will never want. While it's very difficult to get the business to know upfront what all of their requirements will be, sometimes you can identify an anti-requirement that will help you separate out the boundaries better.
00:23:54 Udi Dahan
So for example, we might have this intuitive sense that the name of the book and the price of the book are loosely coupled from each other. I mean, beyond being portrayed on the UI side by side, we don't think there's any fundamental logic that operates on both these fields of data at the same time. One of the ways to verify that is by asking our business stakeholders for an anti-requirement. So come up with some crazy rule that would need to involve both field A and field B in the same transaction at the same time. And ask your business stakeholders, would you ever want something like that? So for example, if we're talking about the name of the book and the price of the book, we can ask a business stakeholder, would you ever want to have a rule in the system that says if the name of the book begins with the letter D, customers will automatically get a 5% discount off of that?
00:25:01 Udi Dahan
And if your business stakeholders look at you kind of like, what planet are you from? Congratulations, you've found an anti-requirement. You're looking for the reaction that not only is that a stupid requirement, but I would never want something like that. It's idiotic, it's not reflective of the domain. When you get that sort of feedback, that's an indication to you that you can take those two pieces of data and put them into different services knowing that you're never going to have to do a join between them, knowing that you're never going to have to copy data from one side to the other side in order to perform some functionality or calculation on it.
00:25:47 Udi Dahan
So when looking at your UI or looking all the way down to the database, don't necessarily expect to find your service boundaries fitting very nicely around the entities that you've already got. So it's not that entity A is going to be over here and entity B is going to be over there. Rather what tends to happen more often is that three fields of entity A and two fields of entity B and one field of entity C all of those clumped together, whereas a bunch of other fields from a bunch of different entities clumped together in a different service. And that you can take this all the way down into the database. Meaning fundamentally that instead of having one big database with everything in it, you end up with multiple small databases. And by the same token, instead of having one UI that shows everything about an entity, you have this type of composite UI with little widgets from each of these services where each of them is showing their own data.
00:26:56 Udi Dahan
So when looking for your service boundaries, sometimes it can be helpful. Don't look at the UI as if it's a single monolithic piece of code that is request, respond same data from a bunch of different APIs. Instead, take that API decomposition all the way into the user interface because that's where the coupling goes. Now, this requires some more advanced techniques around building a UI and more than I can get into in the span of this hour. But if you are interested in hearing more about that, come up and see me afterwards, I'll get you one of these cards, we'll get you sorted out.
00:27:39 Udi Dahan
Now, the next bit, when you have these type of loosely coupled vertical top to bottom slices is to think about, well, how would they interact with each other? Because a lot of the coupling, a lot of the request response behavior tends to be encapsulated within a service boundary. We're not going to see very much request response between services because they just don't really need each other's data that much. However, we will need occasionally to use some sort of coordination between them. And often publish-subscribe communication techniques are a very good way of doing that. So when doing publish-subscribe, again, reiterating the fact that each one of these services ultimately has its own database. And again, I want to be specific. As a service, it's a logical thing, so it has its own database schema.
00:28:44 Udi Dahan
If in your physical deployment you wanted to take these four database schema and host them in one physical database server out of convenience for backup and monitoring and that stuff, that's fine. There is nothing about services that says you must deploy them separately. You can host them together, that's perfectly okay. When you do this kind of pub/sub, one of the things to watch out for is that you don't start duplicating data between services. A lot of times people assume that that's what pub/sub is about. They say, "Oh, okay. So I've got the price of the product, and we've got some other service over there that needs to calculate the order total. So great, serve number three will publish the products' prices and service number two will subscribe to that and it'll use that to calculate the order total.
00:29:35 Udi Dahan
If you see yourself sharing raw business data that way between services, that's usually an indication your boundaries are wrong. If you see that in order to calculate the order total I need the product price, that's usually an indication that the business assumes a relatively high level of consistency around that complete dataset. We wouldn't want there to be a situation where the customer saw that the price of the product was $50 and then the order total showed them $52. They get really upset. You say, "Oh no, it's okay, it's eventually consistent." Users don't care about eventual consistency, they want to know that the number that they saw is the number that they're going to be charged. So product price, order total, the amount that appears on the invoice and what gets charged to their credit card all need to be the same thing.
00:30:36 Udi Dahan
If you start duplicating raw business data from one place to another even via publish-subscribe, that can be an indication that your service boundaries are wrong. So you might be asking, "Well, then what on earth would I be publishing and subscribing if not data?" Usually what we pub/sub is information about what happened from a business context with an identifier and not much else. So for example, we might publish an event saying an order was accepted, and here's the order ID. We could publish an event saying an order was built, and here's the order ID. How much was it built for? None of your business. That's my data, it's in my business capability. I'm the technical authority of that, that's as far as it goes.
00:31:34 Udi Dahan
So when doing pub/sub, always make sure you have a very clear single source of truth for every piece of data. So while we move to multiple databases and the DBAs are like, "Oh, you just totally lost your single source of truth." You can preserve that so long as for every piece of business data, you're able to point to a specific service and say, that is the single source of truth for that piece of data. You don't need a single source of truth for everything all in one place, but everything needs to have a single source of truth. Now, you might be thinking, well, what about caching? We oftentimes take data out of the database and we cash it so that we can get better performance.
00:32:19 Udi Dahan
Usually the place where we cache things is up in the UI. As a result of that, that kind of pub/suby type caching data, usually that's done within a service boundary rather than between services. So when you're thinking about caching in order to improve performance, usually that's an internal service concern rather than a between service concern. Moving on a little bit. I mentioned this thing about CRUD before. You want to be very careful with how you apply CRUD when you're doing services. A good litmus test is asking yourself, is this data private data or public data? Private data is the kind of data that is operated on completely within the domain of a single service. So for example, the name of the book, the author of the book, and the image of the book. This kind of information, if I'm a user and I create a new book, I want to very much operate in a create, read, update, delete fashion.
00:33:25 Udi Dahan
And I can do this safely. I can delete that product as long as that data was private, meaning no other service was aware of the existence of a product with this ID. However, once that data moves into the public domain, so for example, I might publish an event saying new product offered for sale, and here's the product ID. At that point in time, other services can start building up their own data model around it. So for example, this is the price of that product ID says service number two, and this is the state of the inventory of that product ID says service number three. Once that data, once that identifier goes public, you can't just delete it. You need to start thinking about how do we end of life this product? Which is going to be some longer process.
00:34:26 Udi Dahan
So be very careful about how you introduce the concept of deletes when you're building this type of loosely coupled publish-subscribe environment. As long as the data is private, absolutely, create, read, update, and delete is just fine. Once the data goes public, and make it explicit. Model via some event, via a special button in the UI that says make this data public, are you sure at this point in time you will not be able to just delete it immediately? So that when the user does this, there's a very clear statement of intent, yes, this is going everywhere.
00:35:02 Udi Dahan
Now, in order to more completely resolve this, what we'll see is that our services often end up becoming the more primary element of our architecture, layers not so much. Different services based on their needs can end up being built on different database technologies, potentially even different programming languages. That's perfectly all right. Do not strive for some element of all my services should be built the same way. Different services solve needs, solved in different ways. And as we mentioned before, some element of pub/sub between these service boundaries keeps them in sync with each other.
00:35:48 Udi Dahan
Now, the last thing I want to talk about with regards to services in order to resolve coupling once and for all is that you need to look beyond the boundary of a single system. Once we move from a web-based system, we see, well, we've got this mobile app, it seems to be showing a lot of the same data that is able to be seen and operated on in the web app. And the same thing with like a back office type of application, we have users in the back office that can also see prices and customer information and all that stuff. And portals. I mean, the more you look around, the more you see the same data being operated on by different users in different places.
00:36:33 Udi Dahan
Now, if a service is really the technical authority for a given business capability, and if that means that every piece of data is owned entirely by a specific business capability, that must mean that the service that owns price in one system must own prices in all systems. The service that owns contact information in one system must own contact information in all systems. Business capability boundaries do not stop just because your process only extends that far. And no, it doesn't matter which programming language those systems are built in. The fact that the mobile app is built in Objective-C and the portal is built in Java and the back end is built in .NET is insignificant. A lot of times developers get hung up on the fact that, oh, no, no, that's a Java system, that's not part of our service or that's Objective-C, that's out of scope.
00:37:45 Udi Dahan
That's why we define services as the technical authority for a business capability. It means anything and everything technical that supports that business capability is the responsibility of that service. Meaning that we shouldn't be focused so much on system boundaries, we shouldn't be focused so much on technological boundaries. We need to see past all of those things and move to a business centric perspective. And only then can we get that full level of autonomy that ultimately results in service teams that are cross-functional in nature. We'll have an Objective-C developer, we'll have a DBA, we'll have a .NET developer, a Java developer, a tester. We tend have service teams that are fairly significant and build expertise in that business capability domain.
00:38:41 Udi Dahan
Now, when you apply this, understand that this is a huge change to everything your software development organization has ever done. And you're not going to be able to do it on Monday morning. These kinds of things take a long time to transition to. I don't want to paint an overly rosy picture that, oh yeah, just go back, rearrange all of your code, rearrange all of your teams, it'll all be great. This is a big glacier-size change, and you need to take it bit by bit in order to really get the benefits of all of service-oriented architecture. So now that I've covered the higher level of what SOA is, what it isn't, what is in scope, what is out of scope. Now, what we're going to do is we're going to take a look at the healthcare domain a little bit in order to see what sorts of requirements or potentially anti-requirements do we have in that domain, and how can we go about modeling it?
00:39:45 Udi Dahan
Now, healthcare is a huge thing, so I don't have the time in the next 15 minutes to describe everything that is applicable in the healthcare domain. But I do want to call it out, because as I said, it's sufficiently different from the retail domain, which I've given lots and lots of talks about it in the past. So it serves as a good contrasting domain. So if you're not familiar with it, we'll cover it. For those of you who are familiar with it, bear with me, it'll be over quick. So here's a quick look at healthcare. So first of all, there's a thing that probably a lot of us have experienced, the doctor office experience. Now, in the doctor office, there's usually a very small amount of what's going on in healthcare that ultimately comes into play. Things like basic demographic information is tracked, regular health, overall health. Okay, you got a cold, well, give it a few days, it'll go away by itself.
00:40:44 Udi Dahan
There's of course the billing side of things, which is a domain entirely all its own, and it's different from country to country. I'm not going to be getting into that, I'll be focusing more on the clinical side of things. Doctors sometimes prescribed medications to us. In dealing with medications, there's the whole domain of pharmacology itself, not going to be getting into that. But when thinking about medicine, one of the things that is often asked by every healthcare practitioner that you interact with is, are you taking any medication? An element of ongoing medication is something that's very important towards making other medical decisions. Another thing that comes out of this is allergies, are you allergic to anything? Are you allergic to any medication? Allergies, there's a part of it which isn't extremely well-defined.
00:41:43 Udi Dahan
Allergies ultimately mean that the body has a reaction to some stimulus. And this can be things like the regular allergens, pollen dust, et cetera. It can be allergies to medication. It can be allergies to certain types of food, nuts, shellfish, et cetera. And then of course we have that element of if you're on a certain medication, you can't take another medication because those things have adverse reactions to each other, which to some extent is kind of like an allergy that when you're on a certain medication, you become allergic to other medication until you stop, in which case this element of where do the allergy stop and the medications and their domain begin, it's difficult to draw a very strict line between them. Of course, there is the field of immunization, which is a way of preventing diseases from happening. Usually this is relevant primarily for younger children not so much with adults. Although when dealing with much older people, knowing their age has an impact on knowing potentially what immunizations they did not get in the past.
00:43:08 Udi Dahan
As we delve deeper and deeper into this domain, it becomes less and less clear where one of these entities stops and where it starts to relate back to the other entities like patient age that we talked about. There's the elements of vital signs, so heart rate, blood pressure, that kind of stuff. This is also done in the context of a doctor's office. Once every period of time, they take your vitals and make sure that more or less they're in a reasonable area. Of course, when you get into a hospital, then that element of vital signs in terms of frequency becomes a much more important thing that's tracked. There's radiology and all of the other specialized type labs that provide additional information. Usually, there is no automated business logic that is analyzing these types of pictures and then doing something with it on the rest of the patient data. But there are some systems that are created that actually can do some image processing on this to call out specific problems. And you take all of this stuff and it's put in, what's called the patient's chart.
00:44:22 Udi Dahan
Nowadays, it's not really a piece of paper anymore. We have these electronic medical records, electronic health records that takes all of this information and composes it together. In which case we might be saying, hey, look at that, that's a composite UI. We've got radiology over here, and we've got their immunization information over here, and we've got their medication over there. And all of those things sit very nicely in their own little type window that is composed into a larger record. So great, it may feel like once again that, well, here's our high-level architecture. We've got patients and meds and vitals and allergies and immunizations and labs and laps. Each of those things is standalone by itself. And then we create a composite UI and everybody's happy.
00:45:15 Udi Dahan
The challenge becomes when we want to create a larger solution that deals with pretty much the entire patient life cycle. That's ultimately the objective of a lot of these national health care programs, it's to get a global view of the patient to know what happened in one clinic when we're treating them in another clinic because if they were prescribed medication over there and they didn't remember that they took it, it could be that side effects haven't worn off yet, and that's something that's going to impact the kind of care that we give them at this clinic.
00:45:55 Udi Dahan
Now, we move from just sort of the generic healthcare domain and start dealing with more specialized cases, we start to see that not all of these business domains are as significant, for example, in dentistry. Dentists don't really deal very much with medication, that's not what they do. That element of allergies, also not a really big deal to a dentist. So you might be saying, "Oh, okay, well, we've got the other things, we've got the patients." Well, vitals aren't really that important either, and immunizations aren't really that important either. I begin to wonder, in what ways is a dentist similar or different from a regular doc? We want to have a consolidated system that can tell anybody what's going on about a patient. But quite frankly, dentists don't really care to look at what everybody else is looking at. And most of the time the other healthcare professionals don't care what the dentists did. In which case that element of saying, well, we want a composite UI that shows everything about a patient except for dentists and psychiatrists.
00:47:16 Udi Dahan
With psychiatrists, it's even more important because not only do we not want to see their data, there is actual law that states that anybody other than the person, psychiatrist, is not allowed to see that information about the patient. So it's not just a convenience thing that we don't care, but psychiatrists can prescribe medications to patients. So if they do prescribe medications, then you can see those medications when you're somewhere else, but you can't see the information that led to ultimately prescribing that medication. So you get yet another exception to the global healthcare record. Let me go into physiotherapy. And again, medication is out the door. Allergy is not really that important. Vitals kind of become a little bit more important. So what's their heart rate? Is something that is significant in certain kinds of physiotherapy.
00:48:29 Udi Dahan
And once you again, we're in this area that boundaries just don't stay put, there's an exception in each kind of case. Then we get into emergency rooms. I promise I'm not going to be showing you any gory pictures. This is not House, this is not Grey's Anatomy, this is not one of those things. Just nice pictures that are very clean. In an emergency room, now we've got multiple doctors, still the same patient. At that point in time, vitals become extremely important. But the data, the rate at which we gather the data about a person's vitals is quite a bit higher than we do in any other context. Also, what's interesting is that although we need a whole lot of this information while the patient is being treated, usually the historical data is not that relevant, which is kind of odd because in all other domains ... So for example, when your regular GP is seeing you once a quarter, once a month, whatever, once a year, they are tracking your blood pressure over time to verify your long-term health.
00:49:50 Udi Dahan
So sometimes history is important, sometimes it's only important for a short period of time and then we throw away the interim history and then we roll that up. In surgery, same relationship with the emergency room. Also, things get a little bit more blurry. For example, one of the important things in the surgical domain is to really keep track of everything that the surgeon put in you so that they can remember to take it all out of you at the end. It's important not to leave a straight clamp in your body at the end of the surgery. It's a very important part of that domain. Is that a medication or not? Because medications are things that are put into you, but we don't take those out. Kind of becomes difficult to classify what is it exactly that we're doing. In surgery as well, patients are put under by an anesthesiologist. That anesthetic itself is a kind of medication, but you can't be prescribed that. You can't walk into a doctor's office and say, "Please, I would like some of that awesome gas that knocked me out for four hours last time." It doesn't work that way.
00:51:19 Udi Dahan
So the more we look into each of these domains, the more the boundaries blur, what actually qualifies as a medication? Can you prescribe everything that's a medication to a patient? How is it administered? All that stuff goes way out the door. Even the definition of patient gets a little bit fuzzy when dealing with the delivery room. Right now we've got two vitals. We've got the vital signs of the mother, we've got the vital signs of the baby. Where do we keep track of the data about the baby even before the baby is born if all you have is a patient record? CRUD. So the more we expand out, we start to see there are challenges that make it very difficult to even categorize a piece of data, to say that this is what a medication is or this is what a treatment is, or this is what a patient is.
00:52:17 Udi Dahan
Every single place that we try to categorize something, the data slips away and says, well, it is like that over here, but it's not like that over there. In other words, we have a very context-specific environment, and that's what makes it challenging to apply those elements of, "Oh, okay, it's really simple. You've got these four layers, you just divide them up top to bottom, composite UI, and you're done." Unfortunately in this domain, it didn't really hold up. Yeah, you could potentially do it for the basic type of information and say, "I'm building a system for a single type of doctor's office type application." Then maybe that differentiation between medications and allergies and the patient data and the demographics. Yeah, that could be kept separate. But each of those domains in the context of a doctor's office is extremely basic, it's just CRUD top to bottom. It seems forced to even divide it up over there.
00:53:20 Udi Dahan
So when looking for solutions, and this is where I round things out and say, how do we go about finding these solutions? If you're looking at your domain and you're in this type of situation where you're saying, "You know, I just can't pin down this piece of data, it doesn't seem to want to sit anywhere. And even its definition of what it is is extremely context specific." It's useful to go back to basic principles. And the basic principles of service-oriented architecture is really the single responsibility principle. When we say that services are autonomous, when we say that services have explicit boundaries, that's just a fancy way of saying stick to the single responsibility principle, but really?
00:54:16 Udi Dahan
Now, when we look at the single responsibility principle, it guides us. It says, look, a given thing should have one reason to change. In other words, what we're looking at here is not only data ownership. Data is one of those things that can be a cause for change but not necessarily the only thing. So ultimately what we're looking at is what is volatile in the domain versus what is a stable abstraction. One of the ways of picking through that is not only looking at the requirements as you have them today, look back and say, "How was this domain practice 10 years ago, 20 years ago? What's changed in that time period versus what stayed the same?" And then using that to project forwards, say, "What is likely to stay the same in the future? What is likely to change?"
00:55:15 Udi Dahan
So historically when talking about things like the retail domain, we say, "Well, data structures are things that tend to change a lot." However, when we look in the medical domain, data structures, well, we might collect more information, but a patient is a patient to a large extent. Patient has a date of birth, they have an age category, if you will. But really try to look at differentiating what are the stable bits and what are the changing bits. And what you want to do is you want to focus on the differences. Now. I didn't just put up the stock photography for no good reason. The problem when you focus on the difference is that you're going to say, "I see it, it's the red umbrella."
00:56:07 Udi Dahan
Be careful of jumping to conclusions about superficial differences. It could be that's what's significant in the domain of keeping yourself dry outdoors is not the color of your umbrella, it's the size of your umbrella. It could be the height of your umbrella, could be the angle at which you hold your umbrella. Be very careful that when you're looking at something you don't pick something and say, "Oh, that's the thing that's different." It could be that it's coincidental different and it's not actually important to the domain. Really try to see more deeply into how this difference impacts the behavior of the system, the behavior of the users around it. And that's what makes finding service boundaries difficult because you're swimming around in this large domain, is that the important difference? I don't know. There is no clear answer that just hits you and says, "Oh, obviously, this is how things are different." And what you'll end up seeing very frequently is that context is king.
00:57:31 Udi Dahan
Now, in our healthcare domain over here when we said context is king, one of the things that we noticed is that the clinical context seem to govern a lot of even how we defined data. So as we looked through each one of these things, we said, well, in the dentist context, things like vitals and medication, that's not really that important. We're focused more on specific treatments that we're doing, whereas regular doctors don't have that concept of treatments nearly as much. Same thing with physiotherapists, there's more of a concept of ongoing treatment. Now, we might say, well, what's the similarities, differences between say a dentist and a physiotherapist? But really trying to zoom in on that and say, "Well, what data model is appropriate for each one?"
00:58:35 Udi Dahan
Be very careful of premature abstraction. Don't come at the world saying, "Okay, we've got patients and medications and allergies, et cetera," and then see how that fits in each environment. Try to work the other way around that when you have a context and you're seeing differences from one context to the other, try to ignore the similarities, try not to create abstractions and see what would the data model that is most appropriate to this problem be. Model that as if you were building a separate system entirely, forget everything you know about any other context. And then after you have explicitly modeled each context in and of itself, start looking for similarities, what thing could be pulled out? Say, well, there might be some general demographic type information or general billing information that happens across all contexts.
00:59:39 Udi Dahan
So whether the person's going in for surgery or going in for a dentist or going in for a psychiatrist, there is that element that they need to pay. So somehow the money needs to be kept track of. And that's something that tends to be very similar across all of these domains, it can be pulled out to its own context. But when you're going to model things, one of the challenges is really try not to shoe horn the problem into the solution that you've already come up with. And I'd say this is probably the biggest problem that I've seen with developers everywhere is that when people start giving us requirements in the first five minutes or so, we're actually listening. In the next five minutes, we're designing the solution in our head. We're not really listening anymore. In the five minutes after that, we're picking and choosing and saying, "Yep, that fits my solution. Yep, that fits my solution. Yep, that fits my solution. That bit, I think I can make it work." After 15 minutes are up, we're not listening anymore, "Yeah, I got it."
01:00:57 Udi Dahan
Believe me, if it's a significantly complex domain, you're not going to be able to come up with the solution in 15 minutes, you're just not. Try to get out of the habit of doing that, it's really hard because to a large extent, that's how our career developed. The faster we were able to come up with a solution, the better for the business around us. Unfortunately, we've gotten very good at coming up with very poor solutions very quickly. And the challenge is you never really know how poor of a solution you've created until you've tried to use it for long enough, where long enough could be six months, it could be a year, it could be two years. But invariably, somebody will say it would be faster to write the system from scratch than to implement this requirement on the existing architecture. Who said that before? Be honest.
01:02:08 Udi Dahan
That's an indication that you've come up against a requirement where you fundamentally realize the solution that we've come up with does not fit. Now, before you get to that point where you're saying it would be faster to write the system from scratch, there were a whole bunch of other requirements before that you're saying, kind of gritting your teeth, "This just does not fit." You're not yet exasperated enough to write the system from scratch, but it really does feel like you're pounding a square peg into a round hole. That's an indication that the original design is not an appropriate model for the domain. Now, I don't want to promise you that by modeling contexts correctly you won't run into those problems, but at least you'll be going in looking for those problems earlier in your project. Trying to seek out, as I mentioned before, the difference between requirements and anti-requirements.
01:03:14 Udi Dahan
Now, in some cases, UI composition won't be that significant. If your system doesn't have a strong UI component, then that element of, okay, let's divide up the UI that we've got into smaller chunks, that might not be the biggest, most important thing for you. Sometimes it's not easy to see at a UI level how to divide things up. Just to summarize on this element of the SOA problem solution side of things, the main thing I want to tell you, the main takeaway from this talk is that finding service boundaries is really damn hard. It is not something that you should expect to be able to do in a new domain in 15 minutes. When I was brought into this project, this healthcare type project, I sat there for four whole days, four days, nine in the morning to 6:00, 7:00 PM. And I sat there clueless.
01:04:24 Udi Dahan
And I got to tell you, as a consultant that's being brought in to find the client service boundaries at the end of the day, they ask, "So how's it going?" And you have no idea what the answer is. It's a very stressful position to be in. Four days in a row I was sitting there and they asked me, "So are we any closer to finding the service boundaries?" I said, "Well, to be honest, I'm closer to knowing what solutions aren't going to work for your domain, then what will." Somewhere in the morning of the fifth day, I had this idea that the clinical context could be a service boundary, that each clinical context was a service in its own right. Because the amount of data that went from one clinical context to another was extremely basic, it was just like a pile of text. The doctor at the end of a given visit or encounter with the patient, they just write up a body of text. And all of the other clinical contexts would only look at that pile of text.
01:05:41 Udi Dahan
And not only that, but the pile of text was to a large extent immutable. Once it was written, nobody changed it. In that sense, it was a kind of message from one clinical context to another. That message didn't really have a lot of machine calculatable data in it, but it was a very nice candidate for this type of service-based interactions. You say, "Oh, okay. So a given clinical context is publishing an event, here is what happened in my context that other services, other clinical contexts could use." And it worked out pretty well when they actually went to apply it. And the immutability of the data going from one context to another was, I don't want to call it to say that that was the epiphany for me, but really look for immutable data as it passes from place to place. When you're able to find something that's immutable, that once it's created it's not really changed, that's an indication that there's some loose coupling between the two sides that are passing this immutable data around.
01:06:59 Udi Dahan
Now, at this point in time, I want to tell you, there is no easy answer. All of these are heuristics. Look at the UI composition, maybe that'll help you, maybe it won't. Look for immutable data, those could be your messages that divide up your services. Maybe it's just immutable data within a given service. These are very good questions to ask as you're analyzing a domain. There is no flow chart that says, ask this question. If they give you this answer, branch to the right. Then ask this question. If they answer X, then divide up your services this way. If not, then divide up your services that way. Believe me, I've spent the better part of a decade trying to come up with a flow chart like that. I haven't yet. It's just going in and really trying to absorb all of the, let's call it inherent complexity of the domain really understand the problem. But certain things in terms of rules and coming up with the solution, be very wary of too much request response between your services.
01:08:13 Udi Dahan
Really try to neutralize the coupling, that single responsibility principle is a very core way of indicating that you've captured things the right way. So I know that this just barely scratches the surface, and maybe some of you were coming in and saying, "Well, I'm on a healthcare project, Udi is going to give me the solution, I'll just write down everything he says and then start coding." I'm sorry if that was your expectation coming in. Now, potentially this is exactly the problem that you have, in which case, great. But it's more about this style of thinking that there are more questions to ask when doing SOA, and the answers will lead you in different directions in each different domain that you're on.
01:08:55 Udi Dahan
If you want to know more about how to do this kind of stuff, you can go to this URL and sign up. Please get this card, you can type in the information in there. You get two days of videos, quite a bit more practical on the messaging side of things in terms of how you would implement a publish-subscribe solution as well as more SOA theory as well. And if you want to know more beyond that, then please come up to me, or as I said before, tweet me @UdiDahan. Thank you very much, and I hope you've enjoyed it. Thank you. All right, I'm going to put the cards over here.