[0:06] So first things first, who am I? Uh my [0:08] name is Gordon. Uh at the moment I work [0:10] for a startup called Re channel. Been [0:12] doing that for a few months. Previously [0:14] I was a team lead at Enva. Before that I [0:18] was a senior developer at Moo and before [0:19] that I did some net. Um you can contact [0:23] me on these two um places. I'm generally [0:27] not good at responding but give me a [0:29] prod. I'll get back to you. Um, but [0:31] generally honestly, if if you don't get [0:33] a chance to catch up with me at any [0:35] point and you do have questions about [0:36] anything that comes up in these, please [0:37] feel free to contact me and I'll uh I'll [0:40] get back to you and I'll answer you as [0:41] well as I can. So, um, there's a [0:45] generally held belief in conference [0:47] speaking that the the bravest or the [0:49] stupidest thing you can do is a live [0:52] demo. [0:54] Um, I believe that I might have found [0:57] something braver or stupider to do in a [1:00] room full of PHP developers who are all [1:03] hung over from a social last night who [1:05] are just coming up to their lunch and [1:08] are going to want to have [1:10] that. I'm going to talk about [1:13] golf. Now, I can see some people [1:15] nervously looking to the door now. Um, I [1:18] can assure you you don't need to know a [1:20] single thing about golf to enjoy this [1:22] presentation hopefully. Um, I personally [1:25] I am a golfer. I like playing golf and I [1:27] started writing a golf application um, a [1:30] couple of years ago not using any of the [1:33] techniques that I'm about to talk about [1:34] today. And I recently started rewriting [1:36] it using a lot of the techniques. So [1:39] this uh, talk is going to have a little [1:41] bit of a before and after element to it. [1:43] I'm going to show you some of the code I [1:44] did write. I'm going to show you some of [1:45] the code I have now got. Um, and so like [1:49] I say, there's a golf theme to it, but [1:50] you really don't need to know anything [1:52] about golf for that. Um, the other thing [1:54] that I want to make perfectly clear is [1:57] that I wrote the first version in Kana. [2:00] Um, and I'm now working with Symphony. [2:03] Um, but I want to state for the record [2:05] that I like. I think Kohana is a great [2:06] little framework. So, I don't want the [2:08] takeaway point from this to be some form [2:10] of framework flame war like me saying, [2:13] "Oh, it's wrong in Kahan and it's right [2:14] in Symphony." That's that's not the [2:16] intent at all. Um, and thirdly, um, some [2:20] of the coding examples I'm putting up [2:22] are a combination of real code, pseudo [2:26] code, exaggerations for effect. Um, and [2:29] I will let you decide which you think is [2:31] which. [2:34] So we'll start with um two or three just [2:36] examples of the code as I had it in [2:38] Kahana. Um so the first thing we've got [2:40] here is we've got a club a golf club. Uh [2:44] extends a kahan. Uh it has a name. It [2:47] has a a golf field where you go out and [2:49] you play your golf and it has a course [2:51] where you would go and learn how to play [2:53] golf. I can see one or two golfers [2:56] shuffling uncomfortably in the seats at [2:58] some of the terminology there. And I [2:59] will address that in time. Uh and [3:02] there's also a function here to be able [3:03] to book a tea off time at this [3:06] club. We also have uh a simple [3:09] controller to add a new club. It takes [3:11] values in from the request uh and it [3:14] saves a [3:16] club. We have a details controller does [3:19] the opposite of that. It takes a club, [3:20] displays it out. [3:24] and um another controller where we take [3:27] in the user, we take in a club, we take [3:29] in a date and we book a tea off time for [3:31] this user. Like I say, the [3:34] actual things that are that is happening [3:37] there is not that important. It's just [3:39] for illustration. Um and we'll compare [3:41] them side by side as we go [3:43] along. So the first part of this talk is [3:46] domain driven design. Can I have a quick [3:49] show of hands about how many people know [3:51] and understand that [3:53] term? Great. Is there many people in [3:56] here who don't really know anything [3:57] about domain driven design? This is a [3:59] completely new term to them. Okay. Those [4:02] people that raised their hands the [4:03] second time round, um, are you strong [4:05] with object [4:06] orientation? Okay. So, I don't think [4:09] you're going to learn too much new here. [4:11] There's not going to be anything here [4:12] that blows your mind in terms of, uh, [4:13] domain driven design. And there's a lot [4:15] of parallels between DDD and object [4:18] orientation. So the first thing we're [4:20] going to look at is the [4:21] domain. Now the domain is essentially [4:25] the sphere of knowledge. It's the thing [4:26] you're writing your code [4:29] about. So there's a quote here from Eric [4:32] Evans who quite literally wrote the book [4:35] on this. Um the book is called Tackling [4:38] Complexity in the Heart of Software. It [4:39] came out in 2003 and most subsequent [4:42] writing on the subject comes from this [4:45] book. It expands on this book. It takes [4:47] the ideas put forth in this book and it [4:50] um it elaborates on them but nothing [4:53] really has changed much since this book. [4:56] Uh and he says in order to create good [4:58] software you have to know what that [4:59] software is about which makes sense [5:01] right? You um you cannot create banking [5:04] system unless you understand what [5:05] banking is about. [5:07] Um, so you must understand the domain of [5:10] banking to be able to write [5:12] that. So your domain is a sphere of [5:14] knowledge or influence or activity. It's [5:16] it's what you're doing. It's the subject [5:19] area to which a user applies a program [5:21] and the domain evolves collaboratively. [5:24] Now this is a topic I'll come back to [5:26] again and again over the next 20 minutes [5:28] or so. [5:31] Um so I'm going to spend the first half [5:33] of this talk as I say talking about DDD [5:35] some of the principles involved in DDD [5:38] and then I'm going to move on to [5:38] hexagonal [5:40] architecture. So [5:42] um we have entities and value objects in [5:46] in DDD. Now what I'm going to do here is [5:50] I'm going to try a little [5:51] experiment. Does anybody have a£10 note [5:55] on them? [5:58] Got a hand up here. I have a£10 note on [6:03] me. Would you mind swapping your 10 note [6:06] for my 10 pound note? [6:09] Yes. [6:11] Okay. So, you can see here two10 notes, [6:13] two different£10 notes. This one here [6:17] from the gentleman. This one here was [6:18] mine. I'm going to take that and I'm [6:20] going to swap [6:24] that. Yeah. You happy with that [6:26] transaction? Yeah. I can feel a sense of [6:29] anticipation building. I can I can see [6:32] people looking. What's happening here? [6:34] It's a magic trick. It's not. Uh that [6:37] was exactly as mundane as it looked. Um [6:40] but the point is that I have a new 10 [6:44] note and you have a new 10 note. But [6:46] this hasn't changed anything. These 10 [6:48] notes are equal. They are different, but [6:51] they're equal. And the equality comes [6:54] from the values held within. It is 10 [6:57] and it is pound sterling and that's how [7:00] we compare them. These are value [7:03] objects. Now I notice there you've got a [7:06] laptop. You know we've just established [7:10] here that um you know I like to do a [7:14] trade. I've just done a successful [7:16] trade. You've seen that partner here is [7:18] happy with the trade. Would you be [7:19] willing to swap your laptop for my [7:26] laptop? Of course not. Of course not. [7:29] And the reason for that is your laptop [7:31] has state. Your laptop has the things [7:34] that you have downloaded to it. Your [7:35] programs, your files, your emails. Mine [7:38] has state as well. It's got a picture of [7:40] a train I drew last night. [7:44] Um but the concept there is that that is [7:48] a unique laptop. It is very much your [7:52] laptop. It is individual. It's not [7:55] interchangeable. It has as a value or [7:58] sorry as an entity. It has an ID. It's [8:01] specific to you. This one has an ID. So [8:04] the differences there. Value objects are [8:06] immutable. You don't change them. You [8:08] know, we didn't upgrade this [8:10] gentleman's£10 note by changing it. [8:12] changing the picture of the queen. [8:14] Although you could do that, I wouldn't [8:15] recommend it. They don't have an [8:17] identity in this system. They're just [8:19] the equality is based on the values of [8:20] them. Whereas the entities do they [8:22] contain state the state changes over [8:25] time. They describe the current status [8:27] of the application and the equality is [8:30] based on this [8:32] identifier. I'll have you know last [8:34] night when you're all at social, I went [8:36] and bought that. That's my commitment to [8:39] a visual gag. [8:44] So let's talk a little bit about model [8:45] driven [8:46] design. Um so within the concept of um [8:51] of DDD we have [8:54] models. Models are the nouns in your [8:58] domain. models represent the things you [9:01] talk [9:01] about when you talk outside the [9:04] software, when you're talking with your [9:06] product owners, when you're talking with [9:07] your project managers, when you're [9:08] talking with your clients, whoever it is [9:10] you interact with, you talk about [9:13] things. [9:15] Um, and we want to make sure that we're [9:18] naming these things as we talk about [9:20] them outside the software, within the [9:23] software. And I'm about to, excuse me, [9:26] I'm about to come to that um in a bit [9:28] more detail later on. They should be [9:31] simple. Your models represent nouns. [9:35] They represent entities. They represent [9:38] behavior. But they also should adhere to [9:40] the single responsibility principle. [9:42] They do one thing. They know about the [9:44] relationships. If anybody was at [9:45] Marcelo's talk yesterday, he was talking [9:47] in a similar vein about models. Um [9:50] complex logic doesn't belong in there. [9:53] Um, and if you get your model correct, [9:57] it becomes trivial to enhance the [9:59] application. You don't need to complete [10:02] your model at the first pass. You just [10:04] need to know what it is, how it [10:06] interacts with certain things. And as [10:08] your domain grows, you can add new [10:10] models. You can add new relationships [10:11] with these models, but it should be [10:12] quite trivial because these things are [10:16] small and simple. So, let's look back at [10:19] the code here. We've got our club here. [10:22] We've got a golf field and we've got our [10:24] course uh which are strings. We're just [10:27] having names in these right now, but [10:29] these are things that we would talk [10:31] about outside the [10:34] um in in the real world. We would talk [10:36] about as as actual things. A field is a [10:39] thing. It's not just a string. It's not [10:40] just a [10:41] name. So, we should split that out and [10:44] represent that. We have a model now to [10:46] represent our golf field and we have a [10:48] model now to represent our course. [10:52] And then this becomes represented in our [10:54] club as well. You'll notice that the [10:55] string there has changed to the [10:59] object. Let's talk about udicus [11:03] language. What this essentially [11:07] means um and again this is another quote [11:09] from Eric Evans but what this basically [11:12] means is talk in the same language. [11:17] um be very very clear with how you're [11:19] naming things and make sure that those [11:20] names represent how people outside of [11:24] the software talk as [11:27] well. So we want to remove any [11:29] ambiguity, any names that have meaning [11:32] that could mean many things. It could [11:33] mean depending on on who's talking about [11:36] it. The language should be defined by [11:38] the domain [11:40] experts. And one thing to remember, [11:42] you're not the target audience of your [11:43] site in most cases. I know in some cases [11:45] that will be the case. But crucially use [11:48] the same language in the codes that you [11:51] use when you're planning when you use in [11:53] discussions when you use when you're [11:55] writing that language should filter [11:57] across throughout your company. The same [11:59] thing should represented everywhere. So [12:02] one example in my company that we saw um [12:06] I work in wholesale retail B2B and in [12:10] retail B2B we have the concept of [12:13] forward orders and we have the concept [12:15] of [12:17] reorders. Now a forward order is [12:19] essentially what I would think of as a [12:21] pre-order. It's something that happens [12:23] before stock is created. So the the [12:26] retailer sorry the the brand makes [12:28] available the stock says this is the [12:30] things that are coming. We've not made [12:32] any yet. We want you to place all your [12:34] orders so that we know what the demand [12:36] is so we can go and make them. And a [12:38] reorder is what I or any of you would [12:41] think of as an actual order. They come [12:43] back after that initial period and they [12:46] they order more. So to a degree they are [12:48] reordering, but if you're thinking at it [12:50] from a BTOC point of view, it's an [12:53] order. You come to the website, you have [12:54] it there, you press the stock, you go to [12:56] the order, and you place it. And we had [12:59] countless discussions internally with um [13:02] a couple of developers who were adamant [13:06] that this was an order. To them the word [13:10] reorder made no sense and in a way I can [13:13] understand that. Um it it is an order [13:16] and they were thinking purely in that B [13:18] to C term and the discussions and the [13:21] arguments we had we have to call it an [13:24] order. This is an order because it makes [13:25] sense to me. I want to call it an order. [13:28] We go back and say no, we can't call it [13:29] an order because in our domain, our [13:32] domain experts are talking about uh [13:35] reorder. We have to reflect [13:38] that. So you've heard me define the term [13:42] domain experts a couple of times here. I [13:44] want to do another little experiment [13:46] here. [13:48] Can you put up your hand if you are if [13:52] you own a company? If you run a company, [13:54] if you manage a company, can you put up [13:57] your hand as well? If you work in [14:00] product, you're a product manager, [14:02] product [14:03] owner. Can you put up your hands as [14:06] well? if you are a business [14:10] analyst. [14:12] Okay. So, if you don't have your hand up [14:15] right now, I hate to break it to you, [14:18] but you're not the domain [14:21] expert. Now, at Ray channel, uh I was [14:25] lucky enough to be involved at the very [14:26] start. I architected the system with [14:29] with help from my team. Obviously, I [14:31] have been involved in writing or [14:32] reviewing pretty much every line of [14:34] code. I understand implicitly the [14:36] relationships between all the entities [14:38] within our system. I know the [14:41] domain, but a lot of our clients are um [14:47] are brands in women's [14:49] wear. I don't understand why retail [14:52] buyers come to our system and they order [14:55] lots of this and none of this. I don't [14:59] understand when our brands are putting [15:01] together their [15:02] collections that this season everything [15:05] has to be blue and polka dots. I don't [15:09] understand why handbags cost [15:13] £500 [15:15] when I paid £30 for that one and it [15:17] carries [15:19] more. I'm not the domain expert. I [15:22] understand the domain in terms of [15:24] software, but I'm not the domain expert. [15:29] So let's look back at our code [15:31] here. When I wrote this code, [15:35] um, I was thinking about it from my [15:37] point of view. A course to me is [15:39] something you go on to learn. So it [15:41] makes sense to call that thing a [15:43] course. And a golf field makes sense. [15:46] That's where you go and you go play. You [15:48] play golf on the field. So I'm going to [15:50] name these this way because that's what [15:52] makes sense to me as a developer. [15:53] Obviously, this is an awkward example [15:55] because I'm the developer and the [15:56] product owner and everything, but run [15:58] with me here. Um, so I've chosen as a [16:02] developer to name things this way [16:05] because it makes sense to me as a [16:06] developer. Now, imagine what happens [16:08] when the product owner comes to me and [16:10] says, "Okay, we need to change the cost [16:13] of the course." And I look at it and go, [16:15] okay, when you say course, do you mean [16:18] the course you mean or do you mean the [16:19] course I [16:22] mean? This should [16:24] reflect across the entire business. The [16:28] words in the software need to represent [16:29] the words outside of the [16:34] software. So I'm going to talk about [16:36] bounded context a little bit here. What [16:39] a bounded context essentially is, it's a [16:42] subdivision of your domain. [16:44] So we spoke about your domain being your [16:47] sphere of influence. It's it's [16:48] everything about your business, but you [16:51] can sometimes segregate that more. Um so [16:54] to keep the the golf analogy going, [16:56] imagine we have um a green keeper who is [17:00] responsible for maintaining the the golf [17:03] course itself. Uh we have the the club [17:06] pro who is responsible for giving the [17:09] lessons in the green keeper. They are [17:13] they have a lot of tools for example [17:15] that they would use. They're going to [17:16] have a lawn mower. They're going to have [17:18] all the uh all the tools they need to to [17:20] cut the grass to to do everything they [17:22] need to do. These things are very very [17:25] specific to that small area of the [17:28] domain. You know, the the club pro is [17:30] not going to come along and and start [17:31] using the lawnmower. Could if they [17:33] wanted to, but that is we've got this [17:36] little bounded context here that is for [17:38] them. Likewise, the pro, they're going [17:40] to have their their teaching calendar. [17:42] They're going to have [17:44] um uh a set of people they've had [17:47] lessons with before and after. They're [17:48] going to have the inventory of the club [17:50] shop. Usually, the club pro runs a club [17:53] shop. So, bounded context can have [17:56] unrelated concepts. You've got the [17:57] teaching calendar. You've got the lawn [17:58] mower on one side, but it can also share [18:01] concepts. So, think of the course, for [18:03] example. the club pro is going to go and [18:04] play on the course and the the green [18:07] keeper is going to maintain the [18:10] course. But what we've got to be wary of [18:13] is that words and phrases mean different [18:15] things in different contexts. So [18:19] just without any context whatsoever, if [18:22] I say the word ticket, what does that [18:24] mean to [18:26] you? I can guarantee there's about four [18:28] or five different things going around [18:30] the room at the moment. Everybody's got [18:32] a different thing because I've not put [18:33] any context on it [18:35] whatsoever. So, think of, and again, to [18:38] go back to our golf example, think of a [18:41] bunker. Um, to those that aren't um [18:44] proficient golfer, don't don't know that [18:45] much about golf, a bunker is basically [18:46] an obstacle on the golf course that's [18:48] filled with [18:49] sand. If you are the the club pro, the [18:53] bunker, it's it's annoying. It's it's a [18:55] thing that's there that when you're [18:57] playing golf, you sometimes land in and [19:00] you have to get out of it. It's a value [19:04] object because it doesn't matter which [19:06] bunker you're in as a pro. Just you're [19:08] in a [19:09] bunker. But if we think of it from the [19:11] point of view of the green keeper, it's [19:14] that specific bunker. It suffers with [19:17] drainage in the winter, for example, and [19:18] it tends to floods or the grass around [19:20] the lip of it is too long. to the green [19:24] keeper. These things are very specific. [19:26] So things mean different things in [19:28] different [19:30] contexts. [19:32] Okay. So [19:38] services are the actions in your [19:41] application. We spoke about the uh the [19:44] nouns before we've built our models. [19:46] Services the actions when something has [19:48] to do something. [19:51] Services cause state changes to [19:53] entities but they do not have state [19:57] themselves and we're still being driven [19:59] by the same principles that we've just [20:00] spoken about ubiquitous language and [20:02] domain [20:03] expertise. We still need to make sure [20:05] we're having that discussion when [20:07] something happens in our system. We have [20:09] a service it represents a real world [20:11] need that's spoken about. So let's look [20:14] back at our model here our [20:17] club. Um, we've got an action we want to [20:19] perform here, which is booking a tea off [20:21] time for a [20:23] user. You notice the name of that [20:25] function doesn't actually involve the [20:27] word club and it's interacting with a [20:30] number of different things. It's not [20:32] really affecting the state of the club. [20:34] It does depend on how you've modeled it. [20:36] If the model if the club has a series of [20:37] of tea off times within it, then [20:40] perhaps. But how I would prefer to look [20:42] at this is let's create a booking [20:45] service and we have a a manager for [20:48] booking tea times where we pass a user [20:49] and a club into it. Now within this [20:52] booking service which is name spaced off [20:55] we could also have a restaurant booking [20:57] manager. Uh many golf clubs have have [21:00] restaurants as part of the complex. [21:06] So continuous [21:08] integration we move into next um CI is [21:14] um was spoken about by Javi. Did anybody [21:17] go to Jav's talk yesterday? Um well he [21:20] was talking about continuous deployment. [21:22] Uh whereas I'm stopping at the first one [21:25] continuous integration [21:27] here. Your domain is constantly going to [21:30] evolve. It's going to change. is going [21:32] to shift as you move into slightly [21:35] different spheres of influence. What was [21:37] right isn't going to be right anymore. [21:39] We need to maintain discussion. We need [21:42] to maintain take that step back and [21:44] don't just furiously code. Let's take a [21:46] step back and see is this changing [21:49] anything that we used to take for [21:51] granted. Testing strategies will help [21:54] flag changes to this. If you are using [21:57] uh for example PHP spec to build your [22:00] domain and you have it making a certain [22:03] set of expectations and somebody changes [22:06] a domain your tests are going to break [22:07] and that's a good point where you can [22:08] look at it and go oh do we want to [22:11] change these break these tests at this [22:13] point is this a change we want to make [22:14] or is this an accidental [22:16] change but mainly merge code quickly and [22:19] often. If you have two teams running off [22:22] in different directions writing code, [22:26] the domain is going to shift. They're [22:28] going to make certain changes. It might [22:29] be subtle. It might be big. But if you [22:32] come six months later and try to merge [22:34] that code back in when two teams have [22:36] started going in that direction, it's [22:38] going to be hard. You should always look [22:40] to keep changes small, iterative, merge [22:43] quickly, merge often. [22:48] So these are just a few tips that I've [22:50] had from the the successful application [22:52] of DDD with the projects I've worked on. [22:55] So crucially build models as a [22:58] collaboration. This isn't [23:00] just product owner, product manager, [23:02] business analyst comes to you and says I [23:04] want this go and do it. This is a [23:06] collaborative process between both teams [23:08] to work out how to approach this. The [23:11] domain experts know how it works in the [23:13] real world. you know how it works in the [23:15] software world. Come together and work [23:18] out the best way to make that work so [23:20] that we can apply the principles we've [23:22] just spoken [23:23] about. Build your application [23:25] iteratively, small chunks. We don't need [23:27] to solve this problem. Again, Marcelo [23:29] spoke about this last night. Big design [23:31] up [23:31] front. Accept your domain will evolve [23:34] and change. You don't have to get this [23:36] absolutely spot on first [23:38] time. Have complete access to a domain [23:40] expert. This is one of the most key [23:42] things that I found in successful [23:44] projects [23:46] is when somebody who's invested in the [23:49] delivery of the project is [23:51] available 90 95% of the time it's easy [23:55] because you can ask them questions. Did [23:57] you mean this? Is this what you want? [23:59] I'm not sure what this means. Can you [24:00] clarify it for me? If you don't have [24:03] that, you're guessing. If you're [24:05] guessing, like I said before, you're not [24:07] the domain expert and you're going to [24:10] probably guess wrong. And I think Marcel [24:13] is going to kick my ass for this one. [24:16] Test, test, test. Um, if you can, so [24:20] what Marcela spoke about yesterday is [24:21] what you're not doing. You're not [24:22] testing, you're specking. And I do agree [24:25] with that. But the output of specking is [24:28] that you have a test suite. If you can [24:30] write these tests up front as you go [24:32] along, that would be brilliant because [24:34] like we just said, if you have a [24:37] breaking change and it is reflected in a [24:40] test that breaks, then that will be [24:42] flagged up very quickly and you can see [24:45] did we mean to do this? Do we want to [24:47] change the behavior of this domain or is [24:49] that accidental? [24:53] So if you take nothing else from this [24:55] talk, if there's only one tip you take, [24:58] please let it be that talk with each [25:04] other. So why are we not all doing this? [25:06] Why do we don't all just well it's it's [25:09] the [25:10] future? I use the word downside here. I [25:13] don't necessarily believe that is true. [25:15] That's why I use ish. Um but there is no [25:19] doubt it's time consuming especially [25:21] initially to set this up to start [25:23] changing your mentality to start [25:25] changing your thinking to put the [25:27] infrastructure in place to start putting [25:29] testing mechanisms in place up front to [25:31] start putting enhanced discussions [25:34] there. It's time consuming but you [25:36] notice the star there. It's timeconuming [25:38] initially but this pays itself back [25:40] manifold um towards the middle and end [25:44] of a project. [25:45] It can be confusing if you don't [25:47] understand the domain. We just spoke [25:49] about orders versus reorders versus [25:50] forward orders. If a new developer comes [25:53] into a system, you know, you've got your [25:55] language, you've got your way of [25:56] speaking, they're not going to [25:57] understand it necessarily at first. You [25:59] have to take the time to educate them, [26:00] to bring them up to speed so they [26:02] understand what you're talking [26:05] about. And there is an overhead in [26:08] maintaining constant dialogue. [26:10] A lot of your managers, your bosses will [26:13] think, okay, you're a developer, you sit [26:14] there for eight hours a day, head down, [26:17] code away. If you're having if you're [26:19] having discussions, you're not [26:20] delivering anything. Again, to me, [26:23] that's not a downside. I can see why it [26:25] could be perceived as, but having that [26:28] discussion means you're more likely to [26:30] get it right first time. [26:36] Okay, so we have now evolved our code [26:41] from the first iteration. We've got it [26:43] now nicely cut off into a domain. So I'm [26:46] going to talk a little bit about [26:49] geometry. So what are we trying to [26:51] achieve with hexagonal architecture? [26:53] There's a quote there from Alistar [26:55] Cockburn who is kind of the authority on [26:58] this. If you've not read his blog, then [27:00] it's it's the first one that comes up [27:02] when you type hexagonal architecture and [27:04] it's well worth a read. He says, "Allow [27:07] an application to be equally driven by [27:09] users programs, automated tests or batch [27:11] scripts and to be developed and tested [27:13] in isolation from its eventual runtime [27:15] devices and [27:17] databases." Obviously, what does that [27:20] actually mean? It means that if you [27:22] split your domain well enough, then [27:26] there's going to be many things in the [27:27] outside world that want to interact with [27:29] it. You're going to want to retrieve [27:31] data from multiple sources. Perhaps you [27:34] have an XML reader, you have an HTML [27:36] front end, you have an API, and you may [27:39] need to output data to multiple sources. [27:42] You could be using you could be [27:44] using Reddus, you could be using [27:46] MySQL. Doesn't matter inside your [27:49] domain. Your domain does not care. Your [27:51] domain cares about I have this object [27:54] and I want it [27:56] persisted. That's all I care [28:00] about. And this is the question that I [28:03] anticipated would come up most often [28:05] than not. The hexagon is not a hexagon [28:08] because the number six is important. It [28:09] could be pentagonal architecture, [28:11] octagonal architecture, docahedronagonal [28:15] architecture, but rather to allow people [28:17] doing the drawing to have room to insert [28:18] ports and adapters as they need, not [28:21] being constrained by a one-dimensional [28:22] layer diagram. So, traditionally, this [28:24] would be viewed left to right, top to [28:28] bottom. Um, and the hexagon just gives a [28:31] visual effect. So, this is another image [28:33] that came from Alyssa Cockburn's blog. [28:36] You can see um we speak traditionally [28:40] and again to reference Marcelo's talk [28:43] yesterday he spoke about um abstractions [28:46] deal with abstractions and push the [28:49] concretions down and away. Um if you [28:52] were at that you remember that slide top [28:54] left push the concretions down and away. [28:57] What I'm saying is basically the same [28:59] thing but I'm saying push them out and [29:02] away. Your application he uses the word [29:05] application here. This is what we've [29:06] just described as a domain sits in the [29:09] middle here and push the concretions [29:11] outside of [29:14] it. So let's look back at our [29:19] club. We're extending the OM in the club [29:23] here. This is a um the way that Kohana [29:26] uses OM to give you essentially active [29:31] records. what this [29:34] means. And I apologize for this diagram. [29:38] Um, I had a friend that helped me write [29:40] most of the slides, so they look [29:42] generally quite nice cuz he's good at [29:43] that kind of thing. I had to do this [29:44] myself. It kind of [29:47] shows. Um, but the principle of the [29:50] thing [29:51] is we want all the dependency arrows to [29:55] flow [29:56] inwards. Um, and just actually one thing [29:59] that may be slightly confusing, you'll [30:01] notice here there's two hexagons. And [30:04] you'll notice here there's two hexagons. [30:07] My outer hexagon here represents his [30:10] inner hexagon. Um, just to confuse you [30:13] even more, obviously. [30:15] Um, this isn't necessarily something [30:18] that you would need to do or want to do. [30:20] I just prefer to do it that way. I like [30:22] to split the domain models inside and [30:26] put the services wrapped around that and [30:28] then put the application layer around [30:31] about that and that's the outer hexagon [30:33] that Alistister Cogburn talks about. So [30:36] you see we've got our controllers coming [30:38] in through managers through our [30:40] services. The services bring come in [30:42] towards our um models. Everything's [30:46] great so far. That's what we want to [30:48] see. But the red arrows there, they're [30:51] coming back out now. There's kahana now [30:53] lives within our domain and is important [30:55] within our domain and we don't want that [30:57] to be the [31:00] case. So let's talk about ports. If you [31:03] noticed on the first slide um when I [31:06] mentioned hexagonal architecture, it [31:08] also said ports and adapters. Ports and [31:10] adapters is just a different term for [31:12] that. So ports are the gateways into [31:15] your domain. they define the purpose of [31:17] the [31:20] conversation. Um, so like I mentioned [31:22] before, you know, you want to store data [31:25] somewhere, but your domain doesn't care [31:28] where. So if we have another quick look [31:30] at this diagram here, the lines, the the [31:34] bold lines where it says database, [31:36] notifications, where it says user data, [31:39] where it says administration, these are [31:40] the ports in our uh application here. or [31:45] sorry that's confusing because he uses [31:47] application in our system here. [31:50] Um what the ports are for is to say okay [31:55] you can save data I'm the database port [31:58] and I will give you the contract of how [32:00] to save data but how you then use that [32:03] is up to [32:04] you. So let's illustrate that with a [32:07] little bit of [32:08] code. So I've got my club now and what [32:11] I'm building is a club repository. [32:14] The club repository is this uh contract. [32:18] Now it says if you want to persist a [32:22] club then you have to adhere to the [32:25] rules applied by this port. You can save [32:28] a club and you can find a single club by [32:31] its ID. That's all you can [32:34] do. I don't care how you do it. I don't [32:37] care where you put it. But that's the [32:39] two things you can do. [32:43] And now we look at our club. So we are [32:47] no longer using Kahano RM. So we need to [32:49] build in our constructor now which came [32:51] for free [32:53] previously. Um but nothing much more has [32:56] changed. We still got our simple club. [32:59] Um I've started name spacing a little [33:01] bit here um just to help the [33:02] illustration but it's not overly [33:04] important for this [33:05] example. Um but the important point is [33:08] we now get a constructor. build our [33:10] club, but a club doesn't know how to [33:12] save itself. Um, I missed a code I [33:15] wanted to put another slide in here that [33:16] I forgot to put in. I apologize. Uh, our [33:19] constructor, uh, sorry. Um, [33:22] originally [33:24] our No, I'm not going to go back to it. [33:27] Um, we were calling club save. The club [33:30] knew how to save itself. And this came [33:32] from the OM. And that was showed the [33:35] arrow flowing back outwards. the club [33:37] knew about application logic. Now we [33:39] don't have that. Now we pass a club into [33:41] the repository that knows how to save [33:46] itself. So we've got our ports. So the [33:49] second part of this contract is [33:53] adapters. Adapters are built on top of [33:55] the ports and they provide functionality [33:59] concretely. And you can have multiple [34:02] adapters. you probably will have [34:04] multiple [34:05] adapters. So for [34:09] example, here is a very specific [34:11] adapter. We implement the club [34:13] repository. We're using the port. We're [34:15] using that set of rules we've [34:17] defined and um through space obviously [34:20] I've commented out, but that would be [34:22] some SQL that would save a club. Some [34:25] SQL to find a club and return [34:29] it. I want to save it in [34:34] same port, same simplistic I can save [34:38] it, I can find it. And that's your your [34:40] language to um to save those to um [34:44] find one by [34:45] ID. And so a major advantage of this is [34:49] you wanted to swap your storage [34:51] mechanism out for from MySQL to [34:54] for some reason. That's how easy it is. [34:56] That slightly trivializes it obviously, [34:59] but your domain doesn't care. Your [35:02] domain doesn't [35:03] change. No behavior has changed at all [35:06] in your domain. You just build another [35:09] adapter, configure it to use that [35:11] adapter now, and you're now using [35:16] So, we've got a file system club [35:18] repository. This is how we test. We [35:21] build um we use Bhat and we use file [35:25] system. So when we configure when Bhat [35:27] spins up instead of configuring the [35:29] MySQL adapter, it configures the file [35:31] system adapter. Um it's quicker. We [35:34] don't need to go near the database when [35:35] we're running our test suite. We've just [35:37] got an adapter. Same contract. We're [35:39] still using the club repository. We [35:41] still got just our two simple [35:46] methods. And now we go back to the [35:48] controller here. So where I did have as [35:51] I just mentioned that save function now [35:54] we're passing the club into the club [35:55] repository [35:57] uh and we're saving it that way. We've [35:58] defined our [36:03] contract. So now we look a little bit [36:05] like this in the [36:07] hexagon. So these two repositories the [36:10] club repository and the tea time [36:11] repository are now the ports into our [36:14] system. Anything that wants to save [36:15] anything into a data storage has to come [36:18] through these repositories. And you'll [36:20] notice that we've got a Reddus one and a [36:22] MySQL one coming through there depending [36:24] on how we configure it, depending on [36:26] what we're running at any given [36:30] time. But you'll see the red line here, [36:34] the create club controller is still [36:36] going directly into our domain. It still [36:39] knows how to manipulate. If you go back [36:41] a slide here, we're still creating a new [36:43] club directly. [36:48] We need a port at the other side [36:52] here. So we've got a club [36:55] porter. Um I use the word porter because [36:58] it's to do with the import and export of [37:00] data in and out the system to the UI. So [37:03] it's portation. It's a porter. Um we've [37:06] defined two two rules. You can either [37:09] import a club with mixed data depending [37:11] on where it's coming from or you can [37:12] export a club which sends a club which [37:15] takes a club and exports mixed data. So [37:18] let's see a concrete realization of [37:21] that. We've got a request club porter [37:24] takes in a request builds our club from [37:27] the information [37:29] um and we can export a club by taking [37:31] the club putting the data into the [37:33] response and returning that. As I said [37:35] before that some of the code examples [37:37] are are pseudo code just for [37:39] illustration rather than than real [37:41] genuine [37:42] code. But the advantage we have here is [37:46] that same thing. We don't want to take [37:49] in a request anymore. We want to take in [37:51] JSON. We want to take in HTML. We want [37:53] to take in [37:56] XML. So let's go back to our controller. [37:59] Now all of a sudden I've got a oneline [38:02] controller. [38:05] Um, data comes in through the porter. [38:08] Data gets saved through the [38:12] repository. Domain doesn't care where [38:14] it's coming from. Domain doesn't care [38:16] where it's going [38:19] to. So, this gives us expands the [38:23] diagram a little bit here. And now we [38:25] can see the flow of arrows is all coming [38:29] in. the the users, the clubs, the [38:32] models, they don't care where the data [38:33] is coming from. They don't care how [38:35] they're made. They don't care anything. [38:37] The services don't care where the data [38:39] comes from. They know what they have to [38:41] do. And the concrete implementations are [38:44] based on [38:49] configuration. So, what sort of ports [38:52] should there be? Um, traditionally in a [38:55] web application, you're not going to [38:56] need that many. Alistister Cockburn when [38:59] he originally wrote his slides he was [39:02] dealing in enterprise software big big [39:05] behemoth systems and he said he'd never [39:07] seen more than four um traditionally as [39:10] I say in a web app you're not going to [39:12] see much more than than a couple data [39:15] comes in and out to screen to UI data [39:17] gets persisted into a database [39:20] um you could maybe have logging ports [39:23] notification ports if you needed [39:25] that But [39:27] um the hexagon as I say is not you don't [39:30] need to have six ports. There aren't six [39:32] defined ports. It's just an illustration [39:34] of a number of [39:38] ports. [39:40] Okay. Thank you for your time. [39:44] [Applause] [39:54] Like I say, if um if you do have any [39:56] further questions on this and you do [39:57] want to try and contact me and you don't [39:59] get a chance to see me today, then [40:01] please feel free to contact me through [40:02] those [40:04] um places. [40:06] And that's a reference to the book that [40:09] Eric Evans wrote. The second link is a [40:12] um it's a PDF that summarizes the book. [40:16] Um I built a lot of the first part of [40:18] the the talk on that and that's uh also [40:21] Cobburn's blog on hexagonal architecture [40:23] is worth reading as well. [40:28] Yeah, if there's any [40:33] questions there [40:36] I go first. Yeah. [40:41] Okay. So am I going first or? Yeah, go [40:44] ahead. Okay, Gordon, what would you [40:47] suggest for a team uh so if your team [40:51] leading a team and some of the people in [40:54] the team still not up to speed with DDD, [40:57] how do you recommend the team lead to [40:59] kind of u bring them up to speed, what [41:01] what kind of things did you Well, the [41:03] main thing I would suggest um did [41:05] everybody hear the question? Okay, it's [41:07] how to introduce new team members to TDD [41:09] or to DDD. The main thing is as I say [41:13] like the main point I put across it's [41:15] communication. Take the time. Um the [41:19] domain language you use is going to [41:21] become second nature to you. You're [41:22] going to refer to things without [41:23] thinking about it. So it just it's a [41:27] slow process. You have [41:29] to go through with them. You have to [41:31] make sure they're involved in a lot of [41:33] meetings with you. So don't split out [41:35] the meetings into well these two guys [41:37] know about this so they're going to sit [41:39] and have this discussion and nobody else [41:41] is going to know. Try and involve as [41:42] many people as you can in those [41:44] discussions when you're talking about [41:45] domain objects when you're talking about [41:47] models uh when you're talking about [41:48] behaviors of the domain so that it [41:51] becomes second nature to people over [41:53] time that they'll start picking it up. [41:55] Uh in terms of the techniques you can [41:57] use certain things you can use pairing [41:59] with more senior developers who do [42:01] understand it. um code reviews um [42:04] helping pick out uh maybe places they've [42:07] gone wrong sit with them help them [42:09] understand okay I see what you were [42:11] trying to do there but maybe you know we [42:13] try to approach a problem this way help [42:15] them understand why to do that um but [42:18] it's just continuously working with them [42:21] um and investing that time uh like I [42:24] said there's there is some overheads and [42:26] this is an overhead that's worth it [42:28] invest the time team lead may have to [42:31] take a cut in how they can actually [42:32] deliver during that. They're maybe not [42:34] doing so much programming during that [42:35] time, but if they invest the time, then [42:38] the team as a whole grows through that. [42:41] Does that help? [42:44] Hi. Um could you come back to your [42:47] hexagonal row? This one here. [42:52] Yeah. Um my question is uh if you talk [42:56] about um um your code [42:59] domain so why the the service is out of [43:03] this domain of this core sorry they are [43:06] not. So this was what I spoke about when [43:08] I said it was maybe slightly confusing [43:10] between the two um diagrams. My core [43:13] domain here is the outer hexagon and I [43:16] split the inner hexagon to be the domain [43:18] models [43:20] but the outer hexagon is domain. So the [43:22] domain still contains the services but [43:25] if if you you could go to the controller [43:28] please. One second. [43:31] Sorry. Yeah. [43:33] Yeah. You you're calling here direct to [43:36] the [43:37] repository and um I don't know why [43:40] you're doing this instead of uh calling [43:42] from your service that it's from your [43:44] domain. I mean if you have the interface [43:48] you only need the the implementation in [43:50] the controller. Yes. Um absolutely right [43:53] and this is a conversation I had about [43:55] half an hour ago before I started [43:57] myself. Um you would perhaps want to so [44:01] what I'm trying to illustrate mainly [44:03] here is the the data comes in in a [44:08] format. it comes through a porter which [44:11] is defined by the port and it's now in [44:13] your domain and it goes out through a [44:16] repository [44:17] um through a specific one. So that's the [44:20] layer I'm trying to enhance uh to show [44:22] here. Um I'm using a controller as um [44:27] because we're you it's we're generally [44:29] web developers here so we do use [44:30] controllers but what you might want to [44:32] do is abstract that knowledge into the [44:35] domain as well. have a service that [44:37] deals with um converting the data from [44:41] the controller into the format that your [44:44] uh concrete adapter would then use in [44:46] the domain in that model. Um so yes, [44:49] perhaps that's maybe not clear. And the [44:51] other thing that um to follow up on the [44:53] point you just mentioned there that I [44:54] was um thinking is that the controller [44:58] here points at the porter, but if you [45:00] actually look at the code, it also comes [45:01] around the other side and points at the [45:03] repository as well. [45:05] So the controller itself doesn't quite [45:07] fit this model. Um I I tried to draw it [45:09] in here just for illustration that um [45:12] it's there. What you would maybe want to [45:14] do is have another service like you say [45:17] inside the domain that um that takes [45:20] that converts the data through the [45:21] controller. We would use a param [45:22] converter for example to do that um and [45:26] uh use that uh that process. [45:30] Okay. Does that make sense? Yeah. Yeah. [45:33] the controller the controller doesn't [45:36] quite fit the model. I agree with what [45:38] you're saying there. The important part [45:39] I was trying to illustrate was data's [45:42] coming in in one format. You use a [45:44] concrete um implementation of a port to [45:47] get it into your domain. [45:50] Thank you. [45:56] One over here. One over there. [46:00] Yeah. Good. [46:08] Hi um thanks for the talk. Um I was [46:11] wondering I work in a large organization [46:14] with different teams in you know in [46:16] different countries for example so the [46:18] bounded context stuff is quite [46:19] interesting. Have you got any advice on [46:21] on how that scales and what are the [46:23] artifacts and agreements that you you [46:25] end up with? [46:27] Um not great advice because I work in a [46:30] startup. I work in a very small um code [46:33] base. Uh how I would have approach or [46:35] how I approached that within our system [46:38] is through name spacing. [46:41] Um [46:43] and so you you split it out that way. [46:45] But it's not a problem to be honest that [46:48] I've solved myself. Um because generally [46:51] speaking, a lot of the um code bases I [46:54] work with are quite small. They are [46:55] quite contained. They're not as [46:57] sprawling unfortunately. So I don't have [46:59] that much advice I could give you there. [47:02] Um okay I have one other question. Um [47:04] we've used a lot of terms like value [47:06] objects, models, services and then [47:09] overlapping that with standard MVC um [47:12] web frameworks. So could you give like a [47:15] a summary of of how these things map or [47:17] or where they don't map well? [47:20] Uh that would be a talk in itself I [47:22] think um to do it properly. But um like [47:25] I said at the start uh in terms of OO um [47:30] design most of us are relatively okay [47:33] with that. You know your models map to [47:35] your objects. Um so the concepts do [47:39] cross over in terms of MVC. You're [47:42] seeing we're still using uh a [47:44] controller. The model becomes the domain [47:47] really. You're working with the full [47:48] domain even if you're only using parts [47:50] of it. the view is is coming through the [47:54] port. So you are you're using your [47:56] porter to export data. You might have an [47:58] HTML porter that ports to that. Um you [48:02] might use an API to export the [48:04] information out that a front end can [48:06] then consume. Um so the V is almost [48:11] irrelevant in MVC. Um with this [48:13] hexagonal architecture you just you [48:15] output uh your models in AI and how the [48:20] the front end would then consume that is [48:22] up to [48:22] it. Um in terms of O like I say much of [48:26] the much of the structure is the same. [48:28] You have objects that interact with each [48:30] other. The principles of keep your [48:32] objects small still apply. The [48:34] principles of dealing with abstractions [48:36] encapsulation they all still apply. So [48:39] there's [48:40] nothing there's not a huge shift in [48:42] mentality required to start thinking in [48:44] terms of DDD. The biggest shift is the [48:49] conversational aspect of it and [48:50] understanding that [48:52] um there are people employed in your [48:55] organization who do know the domain [48:57] better than you. So let them help you. [49:01] But for example um you know in your [49:03] diagram um which ones are the services [49:05] which ones are the entities where are [49:07] the models in in that what I've tried to [49:10] do with this uh diagram if you can bring [49:12] it back up onto the screen [49:15] please is the color code here. So the [49:18] inner hexagon are my models. Those are [49:21] the simple objects. There's club there's [49:24] course they can interact with each [49:25] other. The club knows about the course. [49:28] The second layer uh color coded in [49:31] green, these are our services that [49:33] interact directly with our models. But [49:35] you notice that our models don't [49:36] interact backwards with the services. [49:38] And then external to the hexagon. So [49:40] this goes into our application layer um [49:43] start dealing with the services [49:45] themselves. [49:48] That's helpful. Thank you. Yeah. Hi [49:50] there. Um great talk. Um interested when [49:53] you're talking about the uh naming and [49:57] say um later down the line the domain [50:00] experts realize they've made a mistake [50:02] and a user should be called a player. [50:04] Would you go to the extent of renaming [50:07] all the users in the code to to players? [50:12] Ideally yes I would. Um but there has to [50:15] be a time and place for it. [50:18] Um I'm not generally a fan of [50:21] refactoring for refactoring state [50:23] stopping and um you know just having [50:26] we're just going to do code now. Um I do [50:28] believe in always moving the business [50:30] objective forward. So at a point where [50:33] it made sense to do that I would do it [50:36] but the short answer is yes I would [50:38] advocate doing that. [50:42] Um one more about naming which seems to [50:45] be uh very important. Um if you're [50:48] coming from a design pattern backgrounds [50:50] uh you will most likely use a lot of [50:52] names like this is something factory or [50:55] observer or anything. What is conflict [50:57] with using uh domain based naming or do [51:02] they work together because they don't [51:03] apply to actually the same entities? I [51:06] believe that you can um and you'll [51:09] notice I use the word collaboratively [51:11] quite often. Um it's not necessarily the [51:14] fact that you have to adhere to what [51:16] your domain expert says because you know [51:20] you guys are the technical experts and [51:22] there is a a middle ground. You should [51:26] always try as much as you can to to name [51:28] things as people as things are going to [51:29] be named but it might not always be [51:31] possible. There might be ways of naming [51:33] things. You might call something for [51:34] example a factory or an observer. That's [51:36] perfectly okay as long as there's still [51:38] a description that maps to the outside [51:40] world. [51:47] Hi there. Do you have any advice for [51:49] structuring the um application? Do you [51:52] have like a a domain uh a namespace for [51:54] your models and your services or do you [51:56] mix them together? [51:59] How I tend to do it is at the the root [52:02] source folder. Um I would have name [52:05] spaces for each of my domain models. So [52:07] a user um I would have a club course [52:12] would maybe live within club. Um the the [52:16] services live at that level as well. But [52:18] you'll notice if I go back [52:23] um I use the word service there. The [52:26] services live within there but they live [52:27] at the same level. Uh like I say this is [52:30] personal preference. I'm not saying that [52:32] this is necessarily right or wrong. [52:34] Um and then we have a folder as well at [52:38] that level called infrastructure and our [52:42] doctrine uh lives in there or symfony [52:44] lives in there. All our controllers live [52:46] in there that um are essentially outside [52:49] our domain. So the three layers live at [52:53] the same layer within the code. Um you [52:55] could what I have done in the past is [52:58] split out the model layer into its own [53:01] um subdomain as well. So you have model [53:03] slash user slash user model [53:07] clubcourse. Um it's partially down to [53:11] personal preference I think but as long [53:13] as there is a clear distinction to you [53:15] and it makes obvious to you and your [53:17] team um then I think there are there are [53:21] ways to do it that suit that suit you [53:23] that's just how we choose to do it. [53:25] Thank you. [53:27] Any more questions? [53:42] Okay, thank you everyone. [53:45] [Music] [54:13] I don't [54:14] think I [54:18] want I want