TubeSum ← Transcribe a video

php[tek] 2017: Workshop: Domain-Driven Design Deconstructed

2h 16m video Transcribed Jun 17, 2026
Intermediate 68 min read For: PHP developers with some experience in object-oriented programming who want to learn about Domain-Driven Design.
112
Views
4
Likes
0
Comments
0
Dislikes
3.6%
📊 Average

AI Summary

Domain-Driven Design (DDD) is a software development approach that focuses on understanding and modeling the core business problem. It emphasizes creating a shared 'ubiquitous language' between developers and domain experts, which is then directly reflected in the code. This workshop provides a practical introduction to DDD, using the example of building software for a brewery.

[8:00]
Definition of DDD

DDD is about focusing on core business problems, developing collaboration with stakeholders, and modeling objects in an understandable and maintainable way.

[29:05]
Ubiquitous Language

A shared language between developers and domain experts, ensuring everyone uses the same terms for the same concepts.

[52:21]
Event Storming

A collaborative modeling technique using sticky notes to discover domain events and build a shared understanding of the problem space.

[66:28]
Value Objects

Small, immutable objects that represent a specific value in the domain and are always valid. They encapsulate validation and business rules.

[66:50]
Entities

Objects with a distinct identity and a lifecycle that can change over time. They are mutable and have state.

[67:24]
Aggregates

A cluster of entities and value objects treated as a single unit for data changes, ensuring consistency.

[45:25]
Bounded Context

A boundary within which a particular ubiquitous language applies, separating different parts of the domain.

[107:44]
Hexagonal Architecture

An architectural pattern that separates the core domain logic from external concerns like frameworks and databases.

[119:44]
CQRS (Command Query Responsibility Segregation)

A pattern that separates read operations from write operations, often using separate models for each.

[122:49]
Event Sourcing

A persistence pattern where the state of an entity is derived from a sequence of stored events.

Clickbait Check

95% Legit

"The title accurately describes the workshop's content, which is a deconstruction of Domain-Driven Design principles."

Mentioned in this Video

Tutorial Checklist

1 52:21 Meet with domain experts and use sticky notes to brainstorm domain events (past-tense actions).
2 58:26 Translate each domain event into a command (an instruction to perform an action).
3 58:58 Identify the models (entities and value objects) that the commands act upon.
4 60:12 Identify the actor (e.g., brewer) who performs the commands.
5 76:04 Create value objects for small, immutable pieces of data (e.g., RecipeName, Temperature). Validate them in the constructor.
6 98:18 Create entities for objects with identity and lifecycle (e.g., Brewer, Grain). Use value objects for their properties.
7 103:22 Create aggregates to manage clusters of entities and value objects (e.g., Recipe aggregate containing Grain entities).
8 110:52 Implement domain events to communicate between bounded contexts (e.g., 'Brew Session Planned' event).

Study Flashcards (12)

What is ubiquitous language in DDD?

easy Click to reveal answer

A shared language between developers and domain experts that is used in both conversation and code.

29:05

What is a value object?

easy Click to reveal answer

Small, immutable objects that represent a specific value in the domain and are always valid.

66:28

What is an entity in DDD?

easy Click to reveal answer

An object with a distinct identity and a lifecycle that can change over time.

66:50

What is an aggregate in DDD?

medium Click to reveal answer

A cluster of entities and value objects treated as a single unit for data changes.

67:24

What is event storming?

medium Click to reveal answer

A collaborative modeling technique using sticky notes to discover domain events and build a shared understanding.

52:21

What is a bounded context?

medium Click to reveal answer

A boundary within which a particular ubiquitous language applies, separating different parts of the domain.

45:25

What is a domain event?

medium Click to reveal answer

An event that has happened in the past, represented as a past-tense verb phrase (e.g., 'Beer was brewed').

55:41

What is a command in DDD?

medium Click to reveal answer

An instruction to perform an action, often derived from event storming (e.g., 'Create Recipe').

58:26

What is hexagonal architecture?

hard Click to reveal answer

An architectural pattern that separates the core domain logic from external concerns like frameworks and databases.

107:44

What is CQRS (Command Query Responsibility Segregation)?

hard Click to reveal answer

A pattern that separates read operations from write operations, often using separate models for each.

119:44

What is event sourcing?

hard Click to reveal answer

A persistence pattern where the state of an entity is derived from a sequence of stored events.

122:49

What is a specification in DDD?

hard Click to reveal answer

A class that encapsulates a business rule and returns a boolean answer.

114:35

💡 Key Takeaways

⚖️

Ubiquitous Language is Key

This is the foundational principle of DDD, emphasizing a shared language between developers and domain experts.

29:05
🔧

Event Storming for Discovery

A practical, collaborative technique to model the domain and build ubiquitous language with stakeholders.

52:21
🔧

Value Objects for Safety

Value objects encapsulate validation and business rules, making the code more robust and reducing errors.

66:28
💡

Hexagonal Architecture for Flexibility

This architectural pattern protects the core domain logic from changes in frameworks and infrastructure.

107:44
📊

CQRS and Event Sourcing are Advanced

These patterns are powerful but complex, and are not necessary for most applications.

119:44

✂️ Creator Tools: Viral Hooks

AI-generated clip ideas for Shorts based on the transcript

Why DDD Makes You a Better Developer

40s

Taps into the universal desire for self-improvement and career growth, with a clear promise of a better problem-solving approach.

▶ Play Clip

Stop Thinking About Data!

45s

Challenges common developer habits with a humorous, relatable critique of jumping to infrastructure solutions, prompting reflection and engagement.

▶ Play Clip

Name Things Like the Business Does

48s

Introduces the transformative concept of ubiquitous language through concrete examples, making a complex topic feel simple and achievable.

▶ Play Clip

[00:01] All right, I assume everybody can hear

[00:02] me. Do I need to talk a little louder?

[00:04] Are we good?

[00:06] Yeah. All right, great. Um, hi everyone.

[00:10] Um, I've met some of you before. Uh, but

[00:13] I'm Andrew Cassell. Uh, PHP developer.

[00:16] I've been developing for about 10 years.

[00:18] Um, I'm kind of local here. Uh, I live

[00:21] in H. turn, which is about 10 miles away

[00:26] or approximately 8 days travel uh during

[00:28] DC rush hour.

[00:30] Um

[00:32] we're for a uh a nonprofit that's called

[00:34] the Marine Spill Response Corporation

[00:36] and uh we clean up uh oil spills. We're

[00:39] a uh nonprofit um we're the largest in

[00:42] the United States uh that does what we

[00:44] do and we have all kinds of equipment

[00:46] and people who are trained uh if there's

[00:48] an environmental disaster to respond.

[00:52] Uh I work um like I said at doing PHP

[00:54] development there. I do mostly

[00:56] applications. We also build their

[00:58] website and I work as a uh part of a

[01:01] three-man team. So um three developers,

[01:03] small team. Uh, but I would put our

[01:05] three developers up against a team of 10

[01:08] uh, any day.

[01:11] Uh, I'm also the organizer of DCPHP. Uh,

[01:13] so if you're local, uh, we'd love to see

[01:15] you at our meetups.

[01:18] Um, today, uh, hopefully it's going to

[01:21] be a lot less formal than most

[01:22] presentations. Um, this is a workshop,

[01:25] so I intend it to be interactive. Um,

[01:27] the video is going to be recorded. If

[01:29] you guys need to refer to the slides

[01:30] later, uh, I'll put them up on the

[01:32] joined end. I'll also post them a link

[01:35] to Twitter. Uh joined in is the uh

[01:37] conference rating system that you guys

[01:39] should uh you know write this talk

[01:40] afterwards. Uh so the video is the

[01:44] slides are going to be recorded but

[01:45] nothing is going to be video recorded.

[01:47] Um you know so you guys don't have to

[01:48] worry about being up on camera or

[01:50] anything like that if we as we do uh

[01:52] stuff together here. Um I'm going to be

[01:56] you know kind of presenting here for a

[01:57] little while. Then we'll do some work

[01:59] and then we'll present a little bit and

[02:01] do a little work again. But while I'm

[02:03] presenting because I want to try to keep

[02:04] this informal, it's kind of a, you know,

[02:06] small enough group we can do this. Just

[02:07] raise your hand and if you have a

[02:08] question, I'll stop and try to answer

[02:09] your question and stuff like that. Um, I

[02:11] really don't want to go any further

[02:12] unless you're not, you know, you're

[02:14] understanding something.

[02:17] So, um, for also for today, you can

[02:19] assume that all the code you're going to

[02:20] see and do is around is PHP 7 or 7.1.

[02:24] Uh, but that doesn't mean you can't use

[02:26] PHP 5. have been doing this longer than

[02:28] you know PHP5 is what we did it uh you

[02:31] know for a long time before PHP7 came

[02:33] out. So all of the code that you know

[02:35] the examples and stuff you're going to

[02:36] see the only differences will be type

[02:38] hinting uh on the returns and stuff like

[02:40] that that uh you know you'll see from

[02:41] PHP7 but other than that nothing changes

[02:43] to go back to PHP 5. Uh we're also going

[02:47] to take a break in the middle um right

[02:49] around 11 when they um the other session

[02:51] gets out just you guys use the bathroom

[02:53] get another cup of coffee or whatever.

[02:56] Uh also you know as we're doing

[02:58] exercises if you need to leave you know

[03:00] whatever that's fine too. So

[03:03] to get into you know why why are we here

[03:06] today? Um why you know why are you here?

[03:08] Why am I here? Because you know I'm here

[03:09] for the same reasons. I want to become a

[03:12] better developer. I want to be uh a

[03:14] better resource for my organization. Um

[03:16] you know I believe in becoming becoming

[03:19] a craftsman meaning having better code

[03:22] craftsmanship raising the level of my

[03:24] code and becoming a more mature

[03:26] developer and becoming a more mature

[03:29] developer means um better understandings

[03:31] of the problems that you're trying to

[03:32] solve. Becoming uh you know more of a

[03:35] value uh for the company that you work

[03:37] for or for your customers.

[03:41] One of the best ways that I know to

[03:43] become a better developer is through

[03:44] domain driven design

[03:46] and domain domain driven design. It's

[03:50] often referred to as DDD uh in the the

[03:53] you know cool kids on the street call it

[03:54] that. Um but it's a very very large

[03:59] topic and there's no way I can teach you

[04:01] everything in about two and a half hours

[04:02] we have today. Uh but I'm going to try

[04:04] to show you what I think are the

[04:06] fundamentals and insights that everyone

[04:08] uh can benefit from hearing. So um you

[04:11] know anytime a presentation starts with

[04:13] a survey or a definition definition I

[04:15] immediately hate it. Uh but I am going

[04:16] to start with a survey and a definition

[04:19] because I want to kind of find gauge

[04:20] this because it's gonna be you know kind

[04:22] of a workshop. I want to know um couple

[04:23] of questions here. So does anybody know

[04:25] BDD or has experience with DDD at all?

[04:29] One person. Okay. Do okay.

[04:31] >> You've read it. Okay. So this will be

[04:33] this will be fun. Um

[04:36] yeah, it's going to be a very beginner

[04:39] um introduction. I think it'll be good

[04:40] for you and then I'm going to give you a

[04:42] ton of resources at the end so you guys

[04:44] can go and learn more and you know

[04:45] obviously answer questions. So let me

[04:48] tell you what DD is not. It is not drink

[04:50] drive and develop but we are going to be

[04:54] talking about beer today. So please

[04:56] drink responsibly and code responsibly.

[04:59] No. Uh so today's talk and today's

[05:01] workshop is on common sense software

[05:03] development and when I mean common sense

[05:06] software development I mean you know

[05:08] doing things that make sense as as it

[05:10] says um you know to as every

[05:13] presentation should steal a quote from

[05:15] Steve Jobs um design is not just what it

[05:18] looks like it's and feels like design is

[05:21] how it works. If you look at the

[05:23] circuitry of an Apple computer, you

[05:26] know, the old ones, they're they're

[05:27] beautiful compared to most, you know,

[05:29] computers of the time. Uh, and your code

[05:32] should be beautiful, too. There's not

[05:33] much more effort to be put in in order

[05:35] to make your code, you know, more repres

[05:37] more more presentational.

[05:40] So, um, because software to me is first

[05:42] and foremost about problem solving. Now,

[05:45] Freddy Krueger is an excellent problem

[05:47] solver. He is designed to kill and is

[05:49] very effective at it. But what I'm

[05:51] saying is people will enjoy your

[05:53] software much more if it's more like

[05:54] James Bond. Still designed to kill

[05:56] people, okay? But, you know, you're

[05:59] going to want to hang out with James

[06:00] Bond at a bar more, you know, and drink

[06:01] a martini and things like that. So, you

[06:03] want to get the job done, but do it in

[06:06] an aesthetically pleasing manner to both

[06:07] you and your clients.

[06:11] So, the bulk of the information I'm

[06:12] going to talk about today are from these

[06:14] two seminal books on domain driven

[06:16] design. Uh the first one domain driven

[06:18] design uh was a book by Eric Evans. Uh

[06:21] he wrote it in 2004. Um you can kind of

[06:23] think of this uh as the Old Testament of

[06:27] domain driven design. Uh the first time

[06:29] I read it, I did not understand it at

[06:31] all. Maybe I'm a little dense, but it's

[06:33] a very very theoretical book and it but

[06:37] once you understand more of the you know

[06:39] experimental side of things and you go

[06:40] back it makes a whole lot more sense. Uh

[06:43] the second book uh was by Von Vernon.

[06:45] People call it the uh the red book, you

[06:47] know, kind of the new testament of

[06:48] domain driven design. And this goes into

[06:51] much more practical application of how

[06:53] to uh build your code uh using domain

[06:55] driven design. There's been plenty of

[06:58] books afterwards once everybody got on

[06:59] the gravy train of domain driven design.

[07:01] Um you know, if you want to learn more

[07:03] about the techniques and things like

[07:04] that or um you know, if you just you

[07:06] were like me in high school and just

[07:07] read the cliff notes, the domain driven

[07:09] design books on the end in PHP and do

[07:12] domain driven design quickly. um those

[07:14] were, you know, good good uh source

[07:17] material to get going quicker.

[07:20] But, um first off, like when I'm talking

[07:23] about the code and patterns and stuff

[07:25] like this, none of this stuff is new.

[07:27] Nothing that the domain driven design

[07:28] people um created was new. It was all

[07:31] looking at patterns that had already

[07:32] existed in software development for a

[07:33] long time, whether that's repository

[07:35] patterns and object-oriented program um

[07:38] things like that. And you know, most of

[07:39] this comes from books that are even

[07:41] older than the books that I just talked

[07:42] about.

[07:43] Uh, a couple people that I want to thank

[07:46] real quick from the PHP community is

[07:47] Matteas Reyes and Bo Simonson. They've

[07:49] been um, you know, fantastic uh, pushers

[07:52] of DDD and PHP and couldn't do this

[07:56] presentation without them. Okay, so for

[08:00] those of you who haven't heard about do

[08:02] main driven design, this is your

[08:04] definition. So if you read the Wikipedia

[08:06] definition of it, um, you kind of get an

[08:08] idea. uh DDD is about focusing on the

[08:10] core business problems that you're

[08:12] trying to solve, developing a valuable

[08:15] collaboration with the other people who

[08:17] have a stake in the process or in the

[08:19] project that you're you know you're

[08:20] building and then trying to model uh the

[08:23] objects in your software in a way that

[08:25] is both understandable and maintainable.

[08:29] So DDD is really meant um to help you

[08:33] tackle really complicated problems much

[08:35] like putting together IKEA furniture but

[08:37] for software. Um so you know we're going

[08:40] to be trying to figure out the model,

[08:42] how to model what the business is trying

[08:43] to do it and then figure out how to

[08:45] apply that model to code.

[08:49] So, if you don't have a good grasp on

[08:50] object-oriented programming um so far, I

[08:53] apologize. Uh but this is going to be

[08:56] very object-oriented uh heavy. And when

[08:59] I mean object-oriented programming, I

[09:00] don't mean how they teach you

[09:02] object-oriented programming about how

[09:04] you know dogs drive and cars bark and

[09:06] those kind of things. Um this is

[09:08] object-oriented programming how it was

[09:09] meant to be. If you go back and read

[09:11] some of the older books on

[09:12] object-oriented programming from small

[09:13] talk and things like that, um you're

[09:17] gonna this is where the DDD people, you

[09:19] know, read this and applied it to new

[09:22] software practices.

[09:24] So to summarize DDD, we're going to be

[09:26] talking about encapsulation. So

[09:28] encapsulating business rules and things

[09:29] like that in logic, immutability,

[09:32] um something that's going to make your

[09:34] software much easier to maintain and

[09:36] write, modeling. So, we're going to talk

[09:38] about modeling objects and entities and

[09:41] uh stuff like that and behavior and

[09:43] encoding the behavior of the business or

[09:44] the process that you're trying to model

[09:46] in into your software.

[09:49] So, when I when I say the word domain,

[09:51] I'm talking about the problem we're

[09:52] trying to solve. So, or the problem

[09:54] space is it's kind of a universal word

[09:56] in the sense it's either the problem or

[09:57] the this problem space. So, for me, my

[10:00] domain is, you know, oil spill response,

[10:02] but that's probably not very exciting to

[10:04] you guys. So, we're going to talk about

[10:06] something I'm much more excited about,

[10:08] which is beer. So, uh I'm sure many of

[10:11] you have been to a brewery. Um do any of

[10:13] you home brew or veryware know how to

[10:16] brew beer?

[10:18] Great. So, we got at least a couple of

[10:20] domain experts in the room here. Um I've

[10:23] been brewing for 15 years and I'm 34.

[10:27] So, do the math.

[10:31] I I found out you could buy all the

[10:33] ingredients in college and you know they

[10:35] don't stop you.

[10:37] Um so we're gonna we're going to try to

[10:39] model the process of uh you know doing a

[10:41] brewery. I sent you all a handout out um

[10:43] it's got some stuff in it about brewing

[10:45] and whatnot. Um but my first job out of

[10:48] college uh or sorry in college still as

[10:50] a co-op was in the beverage industry. I

[10:52] worked for a company that built um

[10:54] high-speed packaging equipment uh for

[10:56] Budweiser and Heineken and stuff like

[10:57] that and they could package 300 cases of

[10:59] beer a minute. So it's an industry that

[11:02] I you know familiar with um on both

[11:04] sides you know and so we were we were

[11:06] writing and I can't show you the screens

[11:07] that we were writing but um you know we

[11:10] were writing human machine interfaces uh

[11:13] you know for those big giant machines.

[11:16] Again, I hope that, you know, this

[11:18] presentation is both going to get you

[11:19] wanting to do domain driven design and

[11:21] brew your own beer at home. But I I you

[11:23] know, domain driven design is very safe.

[11:25] You don't have to worry about it. But

[11:26] brewing can be dangerous. There's hot

[11:27] liquids, there's steam, things like

[11:29] that. Please, if you're going to go into

[11:30] it, be safe. Be careful. Um care about

[11:33] your safety very much. Uh if you want to

[11:36] learn how to brew, first thing is grow a

[11:37] very big beard. Uh no, that's actually

[11:40] not necessary. I can't. So, but I'm

[11:42] doing fine. Um there is a book that's

[11:44] out there that's called How to Brew.

[11:45] It's kind of the seinal uh knowledge

[11:47] that's out there. But uh on the first

[11:49] page of your handout, I've got this

[11:51] diagram and you kind of refer to that uh

[11:54] today, you know, as we do some of the

[11:55] process modeling, things like that. Um

[11:58] this is my favorite diagram of the

[11:59] brewing process. Um because one I think

[12:01] it it shows you that you know the things

[12:03] are going into the process but it also

[12:05] um has two features that I really like

[12:07] is that you know it everything goes

[12:09] through the process of milling the grain

[12:11] and mashing the grain which is like when

[12:13] you you put the grain in at 150 degrees

[12:15] 158 degrees of water that's like 65 C if

[12:18] anybody's international or not

[12:21] imperialist. um to put the the grain in

[12:24] the mash ton um which is this container

[12:27] right here and it steeps for like an

[12:29] hour depending on how long you're

[12:31] needing to do it. You separate the grain

[12:34] from the water and that's called spent

[12:36] grain comes out and then um you take the

[12:39] liquid that's left over from the grain

[12:41] and then that's what you boil and that's

[12:42] what you throw in the hops which is what

[12:44] gives beer that bitterness and that that

[12:46] flavor. You boil that, you cool it down,

[12:49] you put it in a a fermenttor, which is

[12:51] either a giant stainless steel vessel or

[12:53] a bucket. You put um an air lock on it,

[12:55] so you separate it from the outside

[12:57] environment, so no back bad bacteria and

[12:59] things like that get in. You add your

[13:02] yeast, which is usually um a brewer's

[13:05] yeast, which you can buy at a, you know,

[13:07] a shop, and it usually fermentss maybe

[13:10] two weeks, three weeks, depending on

[13:11] what you're making. Um, some beers you

[13:14] can make at room temperature. Others

[13:15] like loggers you need to do cooler. So,

[13:17] there's some, you know, there's a lot of

[13:18] things you can you can do with this

[13:19] process to make different types of beer.

[13:22] And then usually it comes out of the the

[13:23] ferment into a keg or into bottles and

[13:25] is carbonated either using force

[13:27] carbonation or if you add a little bit

[13:29] more sugar back into the beer, you can

[13:32] get uh, you know, it can condition in

[13:34] the bottle so it can carbonate it. So,

[13:35] yeast when they eat sugar, there's two

[13:38] things that come out. There's CO2 and

[13:39] alcohol. few and a few other things, but

[13:41] for the most part CO2 and alcohol, which

[13:43] is, you know, the things we really like.

[13:45] But the reason I really like this

[13:47] diagram is that, you know, as the

[13:48] process goes through this way, on one

[13:49] end you get beer, and on the other end

[13:51] of the spent grain, you get bacon. So,

[13:54] those are two really good things.

[13:58] So, just to show you some of the

[13:59] ingredients that um you know, these are

[14:01] this is barley. Um I've got some the

[14:03] ingredients up front you guys can take a

[14:05] look at. Um then you you know malt the

[14:07] barley as I said you know it look a bit

[14:10] closer look after it molts it turns you

[14:11] know brown a little bit toasted. This is

[14:13] a picture of the mash tun where they're

[14:14] mixing the grain and the water. These

[14:18] are hops. Um you don't usually see hops

[14:20] in wild most places. So they're grown in

[14:24] big farms for the most part. Um that's

[14:25] what a hop looks like. Um you know

[14:27] they're about that big or so. And then

[14:30] it goes into the boil kettles. So you

[14:32] can either do loose leaf hops like this

[14:33] or you can buy it in pellets. So, this

[14:35] is um boiling the the liquid that came

[14:38] off of the grain that was separated from

[14:39] the grain with the hops. And that helps

[14:42] extract some of the flavors and stuff

[14:43] from the hops. And then you cool it

[14:46] down, add your yeast, which is uh the

[14:48] little bugs, which we want bugs in our

[14:50] beer, but not in our software. And then

[14:52] put it in a ferment, and out comes beer.

[14:56] So, you know, and everybody hopefully

[14:58] likes beer, but if you don't, I

[14:59] apologize. Uh these are a couple beers

[15:01] that I brewed. Uh so you know why am I

[15:04] talking so much about beer? Well, we're

[15:06] going to be making beer brewing software

[15:08] here today and there there are plenty of

[15:09] examples of uh beer brewing software. Um

[15:12] this is one that I use a lot. Uh it's

[15:15] called uh brewer's friend. It's okay. Um

[15:18] this is a recipe uh that I made uh for

[15:21] the conference here. It's the Northeast

[15:22] IPA.

[15:24] So um we will be uh I'm not going to

[15:27] have any during the workshop because you

[15:29] know I want guys to stay focused. But I

[15:31] do I did bring some bottles of it with

[15:33] me. I also have my heavites

[15:35] uh with me as well so we can sample that

[15:37] later. There's plenty of software out

[15:38] there already. So we got some good

[15:40] examples to look at if we need to. Uh

[15:41] beer smmith is probably the most widely

[15:44] used. Um it is very complicated and I

[15:46] realize that picture is kind of blurry

[15:48] but it doesn't matter because there are

[15:50] so many knobs and switches and

[15:52] everything in the software. It's

[15:53] ridiculous.

[15:54] Um this is uh supposed to be the easy

[15:58] water calculator. um very very many

[16:01] fields in an Excel spreadsheet to fill

[16:03] out. Um this is the not easy uh water

[16:06] calculator. So when you're putting your

[16:08] water in your beer, you want to kind of

[16:09] adjust um you know various minerals in

[16:11] it and stuff like that to uh try to

[16:13] figure it out. And you tend to have to

[16:15] use like multiple pieces of software all

[16:16] together. Uh and then you know people

[16:18] can get um 16,000 views on YouTube for

[16:22] how do you use the two pieces of

[16:24] software together because it's really

[16:25] complicated. Um you know and I mentioned

[16:28] Brewer's Friend. This is one that I've

[16:30] used that's not terrible. Um, there's

[16:32] another one, a brewer wall that's more

[16:34] like calculations and stuff like that.

[16:36] It's kind of useful. Um, so I've got in

[16:39] my head the last like month or so. I'm

[16:41] going to write a new piece of software

[16:43] and I'm kind of using it to do some, you

[16:45] know, the examples here and you know, I

[16:47] told my wife I need time to work on

[16:48] software, but it's for the conference.

[16:50] Don't, you know, it's not for this

[16:52] stupid hobby of mine. Um, that costs way

[16:55] too much money. But anyway, uh, so

[16:58] beeriously is what I'm calling it. And,

[17:00] um, hopefully you learn if you're

[17:02] writing beer software. I don't if you've

[17:03] seen this XKCD comic or not, but it

[17:06] talks about programming seal with the

[17:08] amount of blood alcohol concentration.

[17:10] And they call it the bomber peak. So, if

[17:12] you get it right around a 0.12,

[17:15] you're um, you're an excellent

[17:16] programmer. So, that's what I would

[17:17] highly recommend everybody try. So,

[17:20] that's enough about about how you know

[17:23] the process of brewing and stuff like I

[17:24] just want to get you guys familiar with

[17:25] it. Um, but you know, if you're going to

[17:28] build software to manage a brewery and

[17:31] you know, say that, you know, you've

[17:32] walked into a brewery and they've asked

[17:35] you, okay, you're going to build

[17:36] software for you. Now, most developers

[17:38] when they start thinking about software,

[17:40] um, you know, they start thinking about

[17:41] the data that the software is going to

[17:43] have. So, they're they're worried about,

[17:44] okay, we're going to need a recipe table

[17:45] because obviously this brewery needs

[17:48] recipes. We need a we need a hop table

[17:50] because we're going to store like, you

[17:51] know, data about hops and things like

[17:52] that. need a grain table. You know,

[17:54] we're identifying the data and stuff

[17:57] like that. And that's kind of how our

[17:59] developer repa reptile brains work. You

[18:02] start thinking about data and the

[18:04] infrastructure and things like that. You

[18:05] know, okay, we need a hop inventory uh

[18:07] database. You know, are we going to use

[18:08] NoSQL or MongoDB? You know, these kind

[18:10] of questions start popping into your

[18:12] head. I don't know if it's the ADB

[18:13] kicking in or if it's just all

[18:14] developers. But I mean, I think that's,

[18:16] you know, kind of how our brain starts

[18:17] working. We just start flying off the

[18:18] handle. We haven't even, you know,

[18:20] thought about the problem we're trying

[18:21] to solve. We're already starting to

[18:22] think table table. You know, what's the

[18:24] events? Oh, we're going to use events,

[18:26] things like that. We have a Q. We need

[18:27] uh you know, are we going to get rabbit

[18:28] MQ? How are we going to do these cues

[18:30] and things like this? You know, maybe if

[18:31] you're a Symphony developer, you're

[18:32] going to um you're already thinking

[18:34] about, okay, roll user, how are we going

[18:35] to do the permissions, things like that?

[18:37] You know, I can't stress this enough,

[18:39] but you know, and this is kind of what

[18:41] the beginning of this presentation is

[18:42] about is just slow down. Try to

[18:45] understand the problem you're trying to

[18:47] solve. Um, most of us, and I'm, you

[18:49] know, guilty myself, is we don't

[18:50] actually take the time to try to figure

[18:51] out what the problem is. We have, we're

[18:53] all these, you know, super intelligent

[18:55] beings that have brains that work at a

[18:56] thousand kilometers an hour. Um, but,

[18:58] you know, you have to stop and think

[18:59] about the problem you're trying to

[19:00] solve. So, you know, what I'm saying is

[19:03] that the imple implementation is

[19:04] important. How you implement your code,

[19:06] what frameworks you use, stuff like that

[19:07] is important, but that's often the first

[19:09] thing we start thinking about as

[19:10] developers or it's how we identify the

[19:12] developers. I'm a Symphfony developer.

[19:13] I'm a Laravel developer. I'm a Zen

[19:15] developer. No, we're we're here to solve

[19:17] problems. It doesn't matter which one of

[19:18] these frameworks they use. They're all

[19:20] fine except for one. I'm not going to

[19:22] tell you which one. No, just kidding.

[19:24] Um, see, I could already get people

[19:26] hating if I just picked one. No.

[19:28] So, um, yeah, there's this saying uh

[19:31] people uh don't want to buy a

[19:33] quarterinch drill. They want a

[19:34] quarterinch hole. They they don't want

[19:36] to hire you. Honestly, they don't want

[19:37] to pay you money. Why would they want to

[19:38] pay you money? What they want is they

[19:40] want their problem solved. So, you have

[19:42] to identify the problem space. you know,

[19:44] you have to work with the people that

[19:45] you're going to be working for and

[19:46] actually identify is what you're trying

[19:48] to solve a problem in the first place.

[19:50] Put your, you know, the value that you

[19:52] can give to a company, you know, to the

[19:54] right place. Make sure you're solving

[19:55] the right problem. And remind yourself

[19:58] that unless you work for yourself in

[19:59] your own consultant, which then, you

[20:00] know, your money is made in being part

[20:02] of the problem. Remind yourself that

[20:04] your your job is to make a pile of money

[20:06] or save a pile of money for your company

[20:08] through software. So maybe writing your

[20:11] own DI container, writing your own

[20:12] framework, writing your own session

[20:13] management, doing password resets and

[20:15] stuff like that and not focusing on the

[20:17] core business problems is dragging the

[20:19] company down a little bit. So you know

[20:21] really just relying on frameworks to do

[20:23] the things that frameworks do well is

[20:24] very important because you're going to

[20:26] have enough problems dealing with your

[20:27] own code and dealing with the problems

[20:28] of the business.

[20:32] I like this tweet. I just saw this the

[20:33] other day so I added it. But um you know

[20:35] despite what newcomers think

[20:37] understanding a language framework or

[20:38] even algorithms is not the hard part of

[20:40] building software and I agree with that

[20:43] and I would remind everybody that you

[20:45] know we're all probably all using PHP

[20:48] today. That's probably not going to be

[20:50] the case in 20 years. Hopefully I know I

[20:52] still want to be doing my job in 20

[20:53] years. Might be even PHP might be

[20:55] another language. You don't know. I mean

[20:57] the tools change. We we've all seen the

[20:59] tools change in our careers in our

[21:01] lifetime.

[21:02] the practices and how you approach

[21:04] problems that doesn't change. You get

[21:06] better and better at this and you learn

[21:07] a way of meth a method of approaching

[21:08] problems. Your your skills can apply to

[21:11] any language or any job. There's a a

[21:14] whole methodology of I don't want to you

[21:16] know bore you too much um but there's

[21:18] this whole methodology of trying to

[21:19] figure out what is the problem you're

[21:20] going to solve. It's jobs.org and you

[21:22] know he has this whole spiel that he

[21:25] does like a telemarketer or something

[21:26] like that about you know milkshakes that

[21:28] you can hire them. Um but you know

[21:31] really the whole the whole idea is um

[21:35] you know why why is the person using

[21:37] your software Monday at 8 a.m. you know

[21:40] try to understand them and get in their

[21:42] mindset and not try to just you know

[21:44] build feature feature feature feature

[21:45] feature feature that may not be actually

[21:47] what they need try to under understand

[21:49] the problem that they're doing or the

[21:51] problem that they have you know and try

[21:53] to put yourself in their shoes. One way

[21:55] you can do that and this is from you

[21:56] know from them the jobs to be done is

[21:57] the five W's and the problem is here if

[22:01] you're the people that you're working

[22:02] for are probably not software developers

[22:03] they're probably not software designers.

[22:06] So you know if you show them something

[22:08] and the first thing they see they're

[22:09] like wow that's awesome you know you've

[22:12] impressed them sure but maybe you

[22:14] haven't actually solved their problems.

[22:16] So

[22:17] what we want to do is go from somebody

[22:19] saying like wow that's great to of

[22:21] course that's how it should be. So that

[22:23] that's where we want to end up with with

[22:25] our software is of course that's how it

[22:27] should be.

[22:29] Otherwise you might end up with you know

[22:30] a beautiful app but it delivers artisal

[22:32] toast or something like that something

[22:33] silly. We want to solve a real problem

[22:35] here. So an example of the five W's.

[22:37] Like let's say you walked in the brewery

[22:39] and I'm going to suggest that you do a

[22:41] drink for every Y here as part of the

[22:43] plan here. Um but say you know the

[22:46] brewer says you know oh I need a list of

[22:47] grain in inventory. So, okay, you know,

[22:50] if you're the the quick and easy

[22:51] developer, you're just going to say,

[22:52] "Yep, I'll give you a list of out of the

[22:54] database. Select all." You know, you

[22:56] know, whatever. But, you know, if you're

[22:58] thinking, you're going to ask that

[22:58] brewer, why do you need this list? And,

[23:00] you know, the brewer is going to say,

[23:01] "Well, because, you know, I need to be

[23:03] able to sort the list of grain to see

[23:05] the inventory to see which one I'm

[23:07] running low on." Well, if you ask him

[23:09] why again, he's going to say, "Well,

[23:11] because, you know, when we formulate a

[23:12] recipe, we need to check and see how

[23:14] much of a particular grain we have on

[23:16] hand." Then I have to figure out, okay,

[23:18] how much do I need to brew that recipe?

[23:21] I'm going to do the little math in my

[23:22] head and figure it out. So, at this

[23:23] point, maybe you're thinking, oh, you

[23:24] know, I can build a search mechanism out

[23:26] of that list. I can list the inventory

[23:28] right there. But if you don't keep

[23:30] asking why, you're not actually going to

[23:31] get to a better solution. So, if we ask

[23:33] them a why, well, why don't we

[23:35] automatically calculate how much grain

[23:36] is needed to order? you know on the

[23:38] brewery recipe creation process that's

[23:40] you know handled by the brew master um

[23:43] you know in the ordering may be a

[23:45] completely separate department but you

[23:46] know if you ask the questions why you

[23:48] might figure out that you know why can't

[23:51] we just automate the process why can't

[23:52] we say when like you know recipes

[23:54] designed and it's we're scheduled the

[23:56] brew session we just automatically order

[23:58] the stuff if you don't ask the why why

[24:01] why you know you start up with you know

[24:03] what is maybe the simplest solution it

[24:05] will take you least amount of time but

[24:06] you end up with automation and what is

[24:08] real powerful software that's going to,

[24:10] you know, save the businesses tons and

[24:11] tons of time, perhaps tons and tons of

[24:13] money.

[24:16] So, you know, DDD, just to kind of

[24:19] phrase it all over, is not about the

[24:21] patterns. It's not about, you know,

[24:22] you're going to hear things about CQS

[24:24] and event sourcing, all these fancy

[24:25] things in DDD. They don't matter. Um,

[24:27] it's not about adding tons and tons of

[24:29] complexity to problems. If you have a

[24:30] simple problem, you know, keep it

[24:32] simple. So, DDD is not for every

[24:35] project. It's not even for every part of

[24:38] a software application perhaps you know

[24:40] um we're trying to keep a um things

[24:43] simple you know as Kiss keep it simple

[24:45] stupid but so don't use what I'm you

[24:48] know kind of teaching you here for you

[24:49] know things that are simple crud like

[24:52] you have a data entry form and you need

[24:53] to display that like don't don't bother

[24:56] this you know use Laravel or something

[24:58] like that it's going to be much faster

[25:00] um you know don't use it for content

[25:01] sites or websites like we have like I

[25:03] said I I build applications for the

[25:04] company I work

[25:05] We didn't use DDD at all on our website.

[25:07] Like it, you know, a little bit for some

[25:09] of the stuff, like pieces of it, but for

[25:11] the most part, it was just, you know,

[25:12] it's content. It's not it's not worth

[25:14] it. Um, you know, don't use it where

[25:17] you're doing functional programming

[25:18] things like that. Um, if you take it to

[25:21] the extreme, you end up with, and this

[25:22] is a great GitHub project to go check

[25:24] out. It's enterprise quality coding, the

[25:26] Fsbuzz Enterprise Edition. I think it

[25:29] solves the FSBuzz problem in like 8,000

[25:31] lines of code or something. I can't

[25:32] remember exactly but and you know just

[25:36] to kind of iterate it or sorry to

[25:38] finalize it you know that DDD is not the

[25:40] one true way to build software that is

[25:42] obviously Ruby on Rails.

[25:47] Okay so all of the normal solid

[25:48] principles apply for doing good code. Um

[25:51] you know if you don't you not have a

[25:52] good grasp on this you know maybe you

[25:53] spend a little time and read about it.

[25:56] But what we're concerned about today is

[25:58] the quality of the software and quality

[26:01] software. Um if you look at you know

[26:04] research about you know what is good

[26:05] quality software. Carnegie Melon uh has

[26:07] a great uh training program for that. Um

[26:10] we talk about you know what are the

[26:12] things that make good software good and

[26:15] I'm going to pick like five out of these

[26:17] you know big giant uh list of software

[26:20] quality. And you know that's what I

[26:23] think are the most important is

[26:24] correctness meaning the software you

[26:26] know works as expected testability

[26:29] usability

[26:31] maintainability and modifiability. So

[26:33] you know just what I think are the five

[26:35] most important things about good

[26:36] software. And we're going to compare a

[26:39] DDD app domain driven design app against

[26:41] you know your usual CRUD app what mo

[26:43] most of us learned how to develop uh

[26:45] doing

[26:47] uh Mattas Reyes who I mentioned earlier

[26:49] has a lot of great blog posts but this

[26:50] is a good one. It's CRUD is an

[26:52] antiattern um you know designing your

[26:56] software to modify data in a database

[26:58] but not creating software for behavior

[27:01] um will cause you problems over time.

[27:03] Um, people in the DDD

[27:06] world, you know, they don't they don't

[27:07] call it CRUD apps. They have another

[27:09] name for it. It's called the big ball of

[27:10] mud app. And I'll get into kind of

[27:13] explaining that in a minute. Um, but if

[27:15] you were to um, you know, compare like

[27:17] what kind of apps you should use in DDD,

[27:19] even in a brewery versus CRUD, like I

[27:21] said, if you're going to do recipe

[27:23] building and brewing sessions and

[27:24] calculations, that's all going to be

[27:25] good stuff for DDD. The crud mud side of

[27:28] things might be the inventory because

[27:29] it's just, you know, it's basically

[27:30] read, update, and delete the beer menu.

[27:32] You're just adjusting prices and things

[27:34] like that. It's probably not very

[27:35] important to the business um to, you

[27:37] know, have good modeling and good

[27:39] practices in place.

[27:43] So, who is responsible um for this this

[27:46] software being good? You know, who's

[27:48] going to be responsible for this? Well,

[27:50] it's both you and the domain experts.

[27:52] you know, Lord Business here or, you

[27:54] know, as we call them, the the product

[27:55] owners, the domain experts, you know, so

[27:57] in the brewing case, you're going to be

[27:58] talking to the brew master. You're gonna

[28:00] be building a software for him or her.

[28:02] That's the person whose problems you're

[28:03] trying to solve.

[28:05] Now, you're going to have to work with

[28:07] that person because, you know, maybe he

[28:09] or she is not, you know, a big software

[28:11] developer, doesn't know what's possible.

[28:12] You guys are all very intelligent. Very

[28:15] intelligent. And you know what is

[28:17] technically feasible in software. They

[28:19] they don't know what's possible both

[28:20] from Yeah. that that's completely

[28:22] impossible. We could never do that to

[28:24] yeah, that's going to take me 10

[28:26] minutes. And they're absolutely amazed.

[28:27] You know, they have they have no clue.

[28:28] They're not technology experts. And you

[28:31] also use the internet a lot. So, you see

[28:33] um you know, more software, great

[28:35] software, you kind of know what software

[28:36] you like to use, what is good software,

[28:38] what is bad software.

[28:41] But you know when you're talking to

[28:42] these um these domain experts and I like

[28:44] this tweet a lot and it says you know

[28:46] what the biggest strategy in software

[28:47] engineering um you know talking crud uh

[28:50] to the people you're you're meeting with

[28:53] um we open the blue book which I

[28:54] mentioned was the you know the first

[28:56] book like in page 24 of a it's 500 pages

[28:59] it's roughly 500 page book so page 24

[29:01] you open basically right up after the

[29:03] preamble the first topic that comes up

[29:05] is ubiquitous language and ubiquitous

[29:09] language is the ultimate power of domain

[29:11] driven design. That's if you leave here

[29:13] today, there's going to be like two big

[29:15] things that I'm going to try to, you

[29:16] know, focus on. Ubiquitous language is

[29:18] probably the number one. It's not

[29:19] necessarily the most important, but it's

[29:21] probably the most important. Um, this

[29:24] ubiquitous language is a shared language

[29:26] that your development team and the

[29:28] domain experts agree to speak. Everyone

[29:30] on the same page, same word. What a word

[29:32] means means the same um to them and you.

[29:36] Um the power of DDD here is

[29:38] understanding the business mindset, the

[29:40] language and solutions, understanding

[29:42] how the business implements the

[29:44] solutions to its problems. So like I

[29:45] mentioned that process of brewing beer.

[29:47] If you don't understand that process,

[29:49] you're not going to be able to write

[29:50] software that builds that. You know, if

[29:51] you're just editing fields in a

[29:53] database, you're not actually building

[29:55] software that's going to solve problems.

[29:57] Um you know, some examples of language

[29:59] that you're going to try to share with a

[30:00] brewer. You know, brewers call them

[30:03] sessions or session beers. We have

[30:05] session database sessions, things like

[30:07] that. You know, user sessions and

[30:08] cookies. You know, if we start saying

[30:10] sessions and they start saying sessions

[30:12] and we're not saying the same word, it's

[30:13] going to be confusing later. Um,

[30:17] you know, this this ubiquitous language

[30:18] again, it's one of those things that,

[30:20] you know, as tools change, when you

[30:21] switch from PHP to JavaScript, stuff

[30:22] like that, this will stick around. This

[30:25] is lifetime guarantee stuff. I mean,

[30:26] once you learn how to use this and apply

[30:28] it effectively, um, you know, it's going

[30:30] to be a skill that you can keep forever.

[30:31] Um you know as von Vernon says in the

[30:33] red book DDD is primarily about

[30:35] discussing listening understanding

[30:38] um it's about discovery you know finding

[30:40] out what what is going on in the problem

[30:42] and creating in your codebase a

[30:45] centralized knowledge uh for the

[30:46] business. So your code should accurately

[30:48] reflect the business's problems and the

[30:51] solutions to those problems and you're

[30:53] going to see speak the same language. So

[30:55] everything that's in the you know how

[30:57] the business works should be in your

[30:58] code. you know, it should be a one to

[31:00] one mapping. Um, you know, so the what

[31:03] I'm saying kind of is that domain driven

[31:04] design in the ubiquitous language should

[31:06] be speaking an idiomatic language. So

[31:08] whatever the business calls something is

[31:09] what you should be calling something.

[31:11] Um, I'm guilty of this too, but you

[31:13] know, you have a you have a user table

[31:15] probably in your database somewhere. So

[31:17] you have a user object. Well, they don't

[31:19] call them users. The only people who

[31:20] call things users are drug dealers and

[31:22] developers.

[31:24] you know,

[31:25] they refer to people as brewers or

[31:27] employees or tasters or customers. So,

[31:30] you know, is it really that much hard

[31:32] effort on your part to rename the class

[31:33] to brewer? I mean, it's not that big of

[31:35] a deal. Um, so when you go to talk to

[31:37] them, you're saying the same words that

[31:38] they're saying. I mean, it's it's so

[31:40] much simpler. Um, guys, I'm sure aware

[31:42] aware of David Letterman. He has, you

[31:44] know, the top 10 lists. Um this is the

[31:46] binary version of the top you know two

[31:48] reasons that programming is hard is

[31:51] naming things cache invalidation and off

[31:53] by one errors.

[31:55] So the end result of this is that um the

[31:59] naming things should be really easy like

[32:02] you should never have that problem

[32:03] again. If you understand the business's

[32:05] problem you talk to them and you share

[32:06] the same language they they are pretty

[32:08] much going to name the things for you.

[32:10] You'll you know be able to apply this

[32:11] directly to your code.

[32:14] So, I'm not picking on Laravel at all

[32:17] here. Um, they're fine. But, you know,

[32:20] most of us developers have at one point

[32:23] probably written code like this where

[32:24] you're just pulling stuff off of the

[32:26] database. Um, you know, find or fail

[32:28] where name equals something. Take one

[32:32] get recipe hops array contains hop ID.

[32:35] If, you know, we have this if check in

[32:36] this if not right here, this exclamation

[32:39] point. Hops array attach hop ID and then

[32:42] maybe some data. And then you have to

[32:43] save. Now, imagine if you showed a

[32:45] brewer this code. You know, their

[32:48] reaction would probably be, "Huh? What?"

[32:52] You know, you don't um take a hop

[32:57] off the hop repo. You know, they go and

[32:59] they get it out of the grain out of the

[33:01] storage, the cooler. They don't take it

[33:03] and then get it. Like, that doesn't make

[33:04] any sense. Um, you know, the recipe

[33:06] doesn't have a hops array. That's that's

[33:08] not something that means something to

[33:09] them. They don't attach a hop to a

[33:11] recipe. that's that's not how they're

[33:13] thinking. But for some reason, we've

[33:14] written code like this and that's just

[33:16] how we've siloed ourselves in the world.

[33:18] We've completely ignored how everybody

[33:20] else thinks.

[33:22] So kind of, you know, and this is like

[33:24] it's going to seem to you completely um

[33:26] simple because it is,

[33:29] but when they say to you, we need to be

[33:30] able to add a measured amount of grain

[33:32] to a recipe, you should have a method on

[33:33] your recipe object called add grains.

[33:36] Sorry, pushed the wrong button. You

[33:38] should have a method called add grains

[33:40] or add grain.

[33:42] You know, we need to be able to

[33:43] calculate an estimated uh that's alcohol

[33:45] by volume for a recipe. They'll say ABV.

[33:47] So, you know, if you need to kind of not

[33:50] remember, you can't remember what ABV is

[33:52] all the time. Maybe they have some, you

[33:53] know, specific words that they use, put

[33:56] those in a method together. You know,

[33:57] recipe, get estimated alcohol by volume

[34:00] ABV. You know, put the words that

[34:02] they're using in your methods and in

[34:03] your objects.

[34:07] you know, we need to know how much

[34:08] winter wheat is in our storage silo

[34:11] number four. Well, we'll go to the sto,

[34:14] you know, you can say new storage

[34:16] facilities. Okay, that's, you know, we

[34:17] have to do that kind of stuff because

[34:18] that's how peachy works. We have to have

[34:19] some, you know, constructs and things

[34:21] like that. But they could probably

[34:23] understand this. You know, you're going

[34:24] to you look at the storage facilities

[34:25] and find the storage facility by name,

[34:27] silo number four, and then storage, how

[34:30] much grain of type, new grain type,

[34:32] winter wheat. So, you know, they can

[34:34] kind of get this. I think it's starting

[34:36] to get more technical, but it's still

[34:38] much more understandable with somebody

[34:39] just looking at this.

[34:42] You know, things get much more

[34:43] complicated, you know, in this kind of

[34:44] brewing software and I'm sure in your

[34:46] software packages, you know, we need to

[34:47] add 02 ounces of a 12 ounce 12% alpha

[34:50] acid per gallon of Simco hops to recipes

[34:53] at a 7day after the boil is complete.

[34:55] And that's called dry hopping. So, um,

[34:58] you know, the bottom here kind of

[34:59] showing you as things get more

[35:01] complicated, but it's still readable.

[35:04] If you're probably already, you know,

[35:05] your brain's already thinking, but um

[35:08] can you imagine this is not very

[35:09] difficult code to write. Like there's

[35:11] not much change between what I showed

[35:12] you before and what I'm showing you now,

[35:14] but it's all in the naming and how

[35:15] you're going to apply things. And later

[35:17] when you're like they're like, "Oh, we

[35:19] want to see how that dry hopping thing

[35:20] works in the software." You go, "Oh,

[35:22] yeah. Let me find the dry hop method."

[35:23] You know, search your whole entire

[35:24] codebase for dry hop. It's all going to

[35:26] come up.

[35:28] Oh, by the way, if if there's anything

[35:30] you're not understanding, on the back of

[35:31] that packet, I have a glossery. So like

[35:34] the last page if I'm using words in

[35:35] brewing industry that you know like dry

[35:37] hopping that's that's adding uh hops in

[35:39] after the fermentation. So boil is

[35:41] already done. Beer's almost ready to

[35:43] drink. You're adding the hops in right

[35:44] before it's uh consumed. So um but you

[35:49] know maybe if you're using be hot or

[35:50] girkin languages and things like that

[35:52] you're already doing this but you don't

[35:53] realize it. You're putting these in your

[35:54] scenarios and features. You know a user

[35:56] should be able to dry hop a recipe. User

[35:59] adds dry hops. You know right there is

[36:01] where you know that's your method names.

[36:02] you're not realizing it, things like

[36:04] that. But if you're not, you know,

[36:06] you're just applying this, you know, you

[36:08] know, if you go in here and you, you

[36:09] know, in BOD, if you like tell it to

[36:11] generate a step definition, it's

[36:12] actually going to generate a step

[36:13] definition like a user should add, you

[36:15] know, dry hopping, you know, whatever.

[36:17] And that's exactly what the method

[36:19] should be, you know, on your objects

[36:20] later.

[36:22] And as I mentioned, this ubiquitous

[36:23] language, it's something that you both

[36:24] agree u to speak. So they call it dry

[36:28] hop. You know, you're going to have a

[36:29] method called dry hop. Maybe they have

[36:30] they're like, "Oh, we just, you know,

[36:31] get a bunch of ingredients. We throw

[36:32] them together. So you have your

[36:33] ingredient, you know, uh adding it to a

[36:35] boil. We add we added it to a boil

[36:37] kettle, you know, it's just different

[36:38] ways that you know, some of you know the

[36:40] people that you're working with talk,

[36:41] you know, and what they speak, maybe

[36:43] where you're from, you know, what

[36:44] country, you know, maybe you wanted to

[36:45] use some of the words that are local,

[36:46] but understand their language, speak the

[36:49] same language and apply it directly to

[36:50] your code. And, you know, we're going to

[36:52] get into um some of like building

[36:54] business rules and things like that

[36:56] using, you know, this language. So like

[36:58] the last one, you know, we could have a

[36:59] recipe add to mash ton and there's no

[37:02] reason you should put be putting hops in

[37:04] that part. It's just the grain. You

[37:06] know, we're going to build some of these

[37:07] log this logic in here to you know, fail

[37:08] on things like that.

[37:11] So you know, you're going to have um you

[37:14] know, this wouldn't be all all one

[37:15] method, but you know, just to kind of

[37:17] you know, summarize the whole thing

[37:19] about naming your stuff. Um, you know,

[37:21] for the most part, a brewer should be

[37:23] able to understand this and figure out

[37:25] what is going on. Even if they're not a

[37:27] software developer, it pretty much reads

[37:28] like English. And, you know, when you're

[37:31] talking about them about the software,

[37:33] um, I don't know how many do does

[37:34] anybody here speak a foreign language?

[37:36] Like, does anybody learn Spanish or

[37:38] German? So, I learned German. And when I

[37:40] first started learning the language um

[37:42] you know you have to think about what is

[37:44] the German word for tree you know it's

[37:46] it's bal town and bal that means you

[37:49] know whatever you so you have to think

[37:51] about the word what is tree eventually

[37:53] as you get better at speaking German you

[37:55] stop thinking about what is the English

[37:57] word for this thing now it's just like

[37:59] in your software if you're speaking the

[38:01] same language as the person that you're

[38:03] developing software for. I don't have to

[38:04] think, oh, you know, the the hops uh

[38:07] array is actually the number of hops in

[38:09] the recipe. Like, I don't have to do

[38:10] this translation in my head. You're

[38:11] speaking the same language. It's going

[38:13] to flow easier and be much easier to

[38:15] understand later.

[38:20] So, if if you're comparing, you know,

[38:22] what is a CredMod app versus DDD? um

[38:24] kind of these objects and this naming

[38:26] and stuff like that. You know, your

[38:28] Cudmud app is going to have users and

[38:29] strings and integers and floats and

[38:31] arrays of OM objects and things like

[38:33] beer inventory repository interface. Um

[38:37] DDD app, you know, you should expect to

[38:38] see objects called brewer, like a brewer

[38:40] or brewers, like a collection of brewers

[38:42] would be, you know, brewers. You're

[38:44] gonna have an object called recipe name

[38:45] that represents the name of the recipe.

[38:47] Things like IBUS, which are how bitter a

[38:49] beer is, um alpha acids, things like

[38:51] that. You're gonna expect to see these

[38:52] objects.

[38:54] um in a thing in a in the in the

[38:56] software. Now, one last topic on the

[38:58] ubiquitous language before we start

[39:00] getting into you know actually doing an

[39:01] exercise is the um natural

[39:04] identification of things in your

[39:06] software. Now hopefully if you're not

[39:08] using UU ids as your database I you know

[39:11] definitely recommend

[39:13] stop start using UU IDs for all your

[39:16] primary keys on your database. make your

[39:17] lives so much easier uh as you're

[39:19] developing software. But those UU IDs,

[39:22] as I'm sure you're aware, are big j long

[39:24] giant strings that don't mean anything

[39:27] to anybody else other than us. So those

[39:29] are our primary keys of our database.

[39:31] Most of what you're developing software

[39:33] for probably already has natural

[39:34] identification built in. So if you're,

[39:36] you know, building software for a

[39:38] library and books, you know, there's

[39:40] already an ISBN number on there. You

[39:42] don't have to use that necessarily as

[39:43] your database primary key, but all of

[39:45] your lookups and things like that should

[39:46] be done based on the natural

[39:48] identification. Um, it's going to make

[39:50] understanding your software later a lot

[39:52] easier. Now, you're still going to have

[39:54] queries that are by ID, you know, in

[39:56] controllers and things like that, but

[39:57] when you're actually building uh

[39:59] business logic and looking for things,

[40:00] try to use natural identifiers. So, if

[40:02] we're looking at a bag of hops, which I

[40:04] brought some bags and ingredients and

[40:05] stuff like that for you guys to look at

[40:06] later, you know, there's already some

[40:08] natural identifiers on here. They've

[40:10] already got a lot number here in the

[40:12] bottom of the package. So you can

[40:13] identify off of that. The name is a, you

[40:16] know, a unique name. Centennial hops is

[40:18] a unique, you know, flavor of hops. So

[40:21] you know, look at your business and,

[40:24] you know, when you're when you're

[40:25] finding things out of the repository for

[40:27] people, you know, you can find it by

[40:28] name by, you know, the string that you

[40:29] take in or things like that. You don't

[40:30] have to use UIDs everywhere in your

[40:33] software.

[40:35] All right. To sum up all of this, and

[40:37] this is kind of an older book, structure

[40:38] of inter uh interpretation of computer

[40:40] programs. One I was probably supposed to

[40:42] read in my computer engineering

[40:45] uh one of my classes at Penn State, but

[40:48] you know, I went to a state school, so I

[40:49] I learned more about beer than I did

[40:51] programming probably. Um but the most

[40:53] important thing, and this is a great

[40:55] quote, is programs must be written for

[40:57] people to read and only incidentally for

[40:59] machines to execute. I've been at the

[41:01] same place that I worked for for 10

[41:03] years, and I looked back at the code

[41:04] that I wrote

[41:06] last week. No, I mean seven, eight years

[41:08] ago and it's just it's it's almost

[41:10] garbage. It's pretty much throw away

[41:12] because it's all ORM based. It's

[41:14] database driven. Modifying any of that

[41:16] is terrifying. Like it some most of it

[41:18] doesn't have tests because that was

[41:20] before we started testing everything. Um

[41:22] but you know to try to make a change it

[41:25] it could take you you know a week to

[41:27] make a very very small change because

[41:29] nothing is encapsulated. Everything is

[41:31] just, you know, scripts everywhere and

[41:33] doing updates and reads and deletes and,

[41:36] you know, you delete one thing one

[41:38] someplace and you don't make the updates

[41:39] in the other and stuff gets haywire that

[41:42] bad things happen. You know, I'm going

[41:43] to try to push you guys into a place

[41:45] where um, you know, building software

[41:47] that's, you know, better and, you know,

[41:50] it's more correct. It's going to stay

[41:51] correct longer and be, you know, easier

[41:53] to change and things like that. All

[41:55] right, real quick. you know, as the

[41:58] business evolves, um, you know, the

[41:59] language evolves, too. Um, so, you know,

[42:01] if they decide they're going to start

[42:03] changing the names of things, um, change

[42:05] them in your software. You know, move

[42:06] along with the business. Don't, you

[42:08] know, you can't just, you know, stay,

[42:10] you know, stuck in the the,

[42:12] you know, 20 years ago. You know, we

[42:14] don't we don't brew like we brewed in

[42:16] the 1600s. Um, because, you know, people

[42:19] got sick all the time of stuff like that

[42:20] from infections. Um, but oddly enough, u

[42:24] beer is very, very safe to drink. almost

[42:26] cannot be poisoned um from beer. The

[42:28] only thing you have to worry about

[42:29] really is um

[42:31] what is it? Uh whatever. It's a very

[42:34] minor infection. It's in none of my

[42:37] beer. Uh I should have wrote it in my

[42:39] notes here. Um but anyway, uh you know,

[42:43] beer, the alcohol in beer kills almost

[42:45] everything. So, it's very safe to drink.

[42:47] Um so, even you know, back in the 1600s,

[42:48] that's why people drank beer so much

[42:50] because it was, you know, safe. The

[42:51] water was terrible. Beer was still safe

[42:53] to drink. But processes have changed.

[42:55] You know, we have giant stainless steel

[42:56] fermenters now. We don't they don't use

[42:58] barrels, you know, from the 1600s to

[43:00] make their beer still. There probably

[43:01] are places that do, but most breweries

[43:04] don't. So, evolve with your company.

[43:06] Evolve, you know, with technology. You

[43:08] know, you're you're going to see things

[43:09] in the technology side of things that's

[43:11] going to change how the business is

[43:13] going to operate. It's your duty to go

[43:14] to the business experts or the domain

[43:16] experts and update the ubiquitous

[43:19] language there, too. You know, if you're

[43:20] operating a theater, you're not going to

[43:22] have a ticket counter forever. You know,

[43:24] now there's online ordering, things like

[43:25] that. You have to go to the business and

[43:26] they're going to they're going to have

[43:27] to change, too. You know, that's

[43:29] ubiquitous language. It's a two-way

[43:30] street. It's not one way them telling

[43:31] you what to do. It's, you know, both

[43:33] ways.

[43:35] All right. This is I promise the last

[43:37] thing about ubiquitous language. And

[43:39] when I mean ubiquitous, it's not across

[43:42] the entire universe. It's not, you know,

[43:43] what they call a hop may not be the same

[43:46] thing across the entire universe. It's

[43:47] not even across the entire organization.

[43:50] It could just be that one project that

[43:51] you're working on with one team in the

[43:53] organization. So, you know, if you have

[43:54] many u parts of your brewery or

[43:56] whatever, marketing and finance and

[43:58] production and inventory, what they

[44:00] refer to as a hop may be something

[44:01] completely different. So, for marketing,

[44:02] it's a you know, it's a flavor. It's

[44:04] they're going to market it as something

[44:05] that's flavorful and things like that.

[44:06] For finance, it's an expenditure. You

[44:08] know, it's just something we have to pay

[44:09] for it. It's awful. You know, for

[44:11] production, that's an ingredient. You

[44:12] know, they're building, they're making

[44:13] the beer. They're, you know, they're

[44:14] dumping it in. For the inventory people,

[44:17] it's just, you know, a quantity of a

[44:19] thing at a location. That's all they

[44:20] care about. So, you know, when you're

[44:21] building the inventory system, you're

[44:23] going to refer to those hops

[44:24] differently. You're going to have

[44:25] different methods and you're going to

[44:26] namespace like PHP has now, which is

[44:28] great. You can namespace those hop

[44:30] things into the inventory namespace. So,

[44:32] you're going to separate your

[44:33] application either through namespacing

[44:35] or if you're big enough maybe

[44:36] microservices. Not something I would

[44:38] recommend you run out and try to do as

[44:39] microservices. It gets very complex. But

[44:42] even if you have what you know they call

[44:43] the majestic monolith big giant

[44:45] application that has like I do you know

[44:46] we have I don't go I don't know how many

[44:48] classes we have in lines it's huge but

[44:51] we still break it down you you still

[44:53] have to solve one little problem at a

[44:54] time so when you go to talk to the

[44:56] inventory people you're talking about

[44:58] hops you know you might still be

[44:59] referencing databases that are similar

[45:01] that are used shared across data that's

[45:03] shared across but you're going to build

[45:04] separate code base you're going to build

[45:06] stuff to their language that it's

[45:08] understandable by them and

[45:09] understandable you and you're speaking

[45:10] the same language at the

[45:11] Because if you're like me and I've you

[45:13] know I've been there for 10 years like I

[45:14] said I built software for somebody five

[45:16] years ago and then five years now we

[45:18] come and we look at it and try to

[45:21] understand it again it's going to be a

[45:22] lot easier if it's written in this

[45:24] language.

[45:25] What I'm talking about in domain driven

[45:27] design is they call it bounded context.

[45:29] So, like I said, we're going to

[45:30] separate, we're going to silo our code,

[45:31] into the recipe section, into the

[45:33] inventory section, the brew house

[45:34] section, because in what they call the

[45:37] big ball of mud, that's the CRUD app

[45:39] that's just got data and updates and

[45:41] sets and everything everywhere going on

[45:43] that's totally incomprehensible or

[45:45] spaghetti code or shanty town code,

[45:47] however you want to look at it. Um, you

[45:49] know, that that's what you end up with

[45:51] if you don't keep things separate. Um

[45:53] the way that I recommend that you do if

[45:55] you're when you're going to separate

[45:56] your code and you know obviously you

[45:58] know the brew house is going to have to

[45:59] talk to the inventory system. You know

[46:01] if you do that spaghetti code you got

[46:03] stuff you know flying everywhere objects

[46:05] calling methods and other sections and

[46:07] stuff like that. If you do that and you

[46:09] go to update your system it's not going

[46:10] to be modifiable because you want to

[46:12] change say you know it's been five years

[46:13] and you haven't touched the inventory

[46:14] system you want to make an update. Well

[46:16] if you've got all these methods that are

[46:17] being called in the brew house from the

[46:19] inventory system now you have to touch

[46:21] both code bases.

[46:23] Keep everything siloed, keep everything

[46:24] separate. And the way to do that is to

[46:26] pass messages between the different

[46:28] domains. And you know, you can do that

[46:31] however you you know, you feel like you

[46:33] use, you know, if you're using Symphony,

[46:34] use the event publisher, build your own

[46:36] queue, you know, do what do whatever you

[46:38] know, your implementation, you know,

[46:40] makes it easiest for you to do. But

[46:41] you're going to pass these as messages

[46:43] or events. You're going to publish an

[46:44] event and let for people, you know,

[46:45] listen. And, you know, in DDD, we call

[46:47] this a a domain event, you know. So,

[46:50] we're going to pass these domain things

[46:52] that happen in say in inventory, you

[46:54] know, uh uh ingredients received. You

[46:59] know, it's going to fire up an event and

[47:00] now the brew house knows, hey, the

[47:01] ingredients have been received. We can

[47:03] start brewing. So, we're going to pass

[47:04] this message of ingredient that

[47:06] ingredients were received. Brew House is

[47:08] going to pick that up and then move on

[47:10] to its next thing. All right,

[47:12] we're just about ready to stop talking

[47:15] and start doing, but I wanted to stop

[47:16] real quick. Does anybody have any

[47:17] questions uh about the ubiquitous

[47:20] language and what we've been talking

[47:22] about? We're going to start how do you

[47:23] actually you know work with a domain

[47:25] expert and build this ubicous language

[47:27] through an exercise. But does anybody

[47:29] have any questions before we do that?

[47:42] >> Yeah. Um, so what what you want to do

[47:45] there, um, so if you're trying to build

[47:47] like a generic app that works for

[47:48] multiple people, is that what you're

[47:50] saying? Like, so you have like let's

[47:51] just say it's a purchasing app and you

[47:53] have three companies that want to use

[47:54] it, something like that, right? Um, what

[47:56] you'll typically want to do is build

[47:58] your interfaces like class interfaces in

[48:01] the domain language. So what you

[48:02] understand is the domain, your

[48:04] understanding of the domain. Those will

[48:06] be your interfaces. So when you're

[48:07] applying or using those interfaces when

[48:09] I if I don't know experience level here

[48:10] of classes but you have you know you

[48:11] have classes which are concrete objects

[48:13] you have interfaces which just define

[48:15] what a what a class can do. So you want

[48:18] to build those interfaces in your domain

[48:19] language. Then you'll probably have to

[48:21] build custom classes that you know

[48:23] implement things differently but

[48:25] implement that interface so you can kind

[48:28] of keep things separate and you actually

[48:30] you know namespace those implementations

[48:32] per the client name. They're that

[48:34] specific. Um, we have things in our

[48:36] company where certain rules are for only

[48:38] certain regions in the company. So, you

[48:41] know, we want to put that in there

[48:42] because you want to know why the heck is

[48:44] this doing this? Well, it's because they

[48:45] asked us to do it, you know. So, we know

[48:46] who asked us kind of thing. So,

[48:56] >> yeah,

[49:03] pretty much.

[49:07] Yeah. Um, definitely naming things like

[49:09] that. But what I'm saying is like if you

[49:10] have an app where like they're they're

[49:12] typing in uh let's say like in a brewery

[49:15] they have a QA program where they just

[49:16] record values like oh how much

[49:18] carbonation was in this? How much acid,

[49:20] you know, what was the pH? Things like

[49:22] that. You don't really have to build

[49:23] that domain driven design. You can let

[49:25] Laravel or Symphony or Doctrine generate

[49:27] forms for you generate stuff. You know,

[49:29] they type it in, they hit save. There's

[49:31] not really any business logic there.

[49:33] It's just recording. So that would be an

[49:34] instance where don't it's a little bit

[49:37] more overhead to do DDD stuff because

[49:39] you're going to spend more time

[49:40] modeling. You're going to spend time you

[49:41] know figuring out the language and stuff

[49:42] like that. If it's not it doesn't matter

[49:44] just do it. I mean it's a balance.

[49:57] >> Yeah.

[50:07] same thing.

[50:16] >> Yeah. I mean, I look at, you know, cons

[50:19] like p publishing versus subscribing. Uh

[50:21] like kind of like what you're saying,

[50:22] like you're you're pushing to an API. um

[50:25] that that is code that you're writing

[50:27] and you're you're responsible for

[50:28] testing that code when you're consuming

[50:30] APIs and things like that. Um publishing

[50:33] an event out to the system kind of like

[50:35] you know wiping your hands clean and

[50:37] walking away um from it. So it tends to

[50:40] if you have very separate systems it

[50:43] tends to work better for things that are

[50:44] happening that other systems need to

[50:46] respond to. Now again like you're saying

[50:48] you may have an API to the inventory

[50:49] system or a service that can you know if

[50:51] the brew house needs information from

[50:53] the inventory system. Yeah. Build what

[50:55] they call um so I'll get into this

[50:57] hopefully later hexogonal architecture.

[50:59] And it talks about what they call ports

[51:00] and adapters. And really what you want

[51:02] to do is you have a very simple

[51:03] interface that's between the inventory

[51:04] system and the brew house. So your

[51:06] methods very clear. It's kind an API or

[51:09] you know again it's a microser you're

[51:10] going to separate that into a completely

[51:12] different web server. But you want to

[51:14] have these very tiny classes that

[51:16] transfer those messages across just like

[51:17] publishing an event. So you know you can

[51:19] still talk to other domains but it's

[51:21] done through a very restricted channel

[51:23] so that you know when one changes and

[51:24] the other needs to be updated you don't

[51:26] have to update both sets code bases. You

[51:28] just have to update the adapter.

[51:31] Okay.

[51:42] No, I haven't because I'm usually I

[51:44] would usually defer to the business

[51:46] because it's their problem you're

[51:47] solving. I mean, it's, you know, you can

[51:49] convince them otherwise.

[51:51] All right. Um,

[51:54] any other questions? I'm going to pass

[51:55] out some treats. There's a tradition in

[51:57] the brewing industry for uh these nut

[51:59] rolls. So you guys that ask questions,

[52:02] you get a anybody allergic to peanuts

[52:04] that I just asked a question.

[52:11] Yeah. Yeah. No, too late. I'll have

[52:15] extras at the end. All right. So, we got

[52:17] a few minutes before the the first the

[52:19] break here.

[52:21] Um what we're going to build the

[52:23] ubiquitous language through is an

[52:25] exercise. It's called eventtorming. And

[52:27] uh this was done by Albert created by

[52:28] Alberto Randolini.

[52:31] Um but when you you're building this

[52:33] ubiquitous language and this this thing

[52:34] you want to go out and actually meet

[52:36] with the domain experts. You know having

[52:38] somebody spec pass you the specs is not

[52:40] the way to build software. You know a

[52:42] million tickets in Jira and have a

[52:44] burndown chart is not the way to build

[52:46] proper software. Um this is me out on

[52:49] one of our ships you know meeting with

[52:50] the crews and stuff learning how uh to

[52:52] build software. UX professionals, they

[52:54] call this ethnographic research. It's

[52:56] fancy word for saying get yourself out

[52:58] from behind your fancy desk that goes up

[53:00] and down and get out there and learn.

[53:02] You know, in a brewery, that's that's

[53:04] actually probably pretty fun, but on a

[53:06] ship, it's just smelly and dangerous.

[53:08] So,

[53:10] and it makes you seasick. Um, you know,

[53:12] you'll hear this thing about user

[53:14] experience talking about personas. You

[53:16] know, don't worry about personas. You

[53:18] shouldn't be thinking about personas.

[53:20] You know, I love this example of

[53:22] personas. It's like, oh, you know, we're

[53:23] going to build software for a brewer and

[53:26] he loves poetry or she has a library

[53:29] science degree and just got a job at the

[53:30] brewery. No, you know what? Actually,

[53:32] these are all the same people. Um,

[53:33] they're just all in different makeup and

[53:36] disguises. Um, yeah, that that persona

[53:39] doesn't matter quite as much. It's kind

[53:40] of something that's been created by UX

[53:42] professionals so that developers don't

[53:43] have to talk to the clients. I think um

[53:46] you know, a lot of times like you build

[53:47] these personas, you end up building

[53:49] either a racist or a stereotypical piece

[53:50] of software. You know, I I love this

[53:53] example here, but you know, it's a

[53:54] computer, but why does it have to be

[53:55] pink? Because it's for a girl. It

[53:57] doesn't doesn't make any sense. Or

[53:58] you're building software for women. It

[53:59] doesn't need to be pink. You know, um I

[54:02] read a great quote. It's like, please

[54:04] remove age, gender, ethnicity, locations

[54:05] from personas. None of that makes any

[54:07] difference. As these guys that have nut

[54:10] rolls, no, it didn't matter where you

[54:11] came from, what your age is, what your

[54:13] experience is. You're hungry and you

[54:14] wanted a nut roll. That's why you wanted

[54:15] to ask that question.

[54:18] Solve the problem that you have. I mean

[54:19] there's a great book that's user

[54:20] experience that's uh talking about user

[54:22] research and

[54:24] uh you go read that about getting in the

[54:26] mental model of the person when you're

[54:28] meeting with a stakeholder and building

[54:29] ubiquitous language you know talked

[54:31] about the five wise you know this

[54:33] understanding the business problem when

[54:35] we do this exercise I don't want anybody

[54:37] to be to using what I call the seven

[54:39] dirty words of meeting with a domain

[54:40] expert that's just like George Carlin

[54:42] words but these are worse session

[54:44] repository abstract interface class

[54:46] database foreign key those are really

[54:47] words that nobody else understands

[54:49] except for all of us. Don't use those

[54:50] words. All right. So, what you're going

[54:52] to do is you're going to get your your

[54:53] sticky pads out and your pens and

[54:55] markers. And we're not going to build

[54:58] any kind of user interfaces yet. We're

[54:59] just going to try to understand the

[55:00] problem. And the reason you use sticky

[55:02] pads, markers, and pens is that not

[55:04] everybody else is as good as using

[55:06] computers as we are. You know, they're

[55:08] maybe not as technically inclined. You

[55:09] know, I had a meeting one time. I was

[55:11] scrolling through software so fast. The

[55:12] guy said, "Hey, you're making my eyes

[55:14] roll back in my head. I can't read. you

[55:16] know, as fast as you can. So, we're

[55:19] going to get low tech here. We're going

[55:20] to use sticky pads and pens, markers,

[55:22] and stuff like that. And we're gonna

[55:24] build uh a model of the problem that

[55:27] we're trying to solve. And you have

[55:29] colored things um and your your little

[55:31] stickies there. We're just going to

[55:32] create like basically a legend of what

[55:34] things are. We have a domain event,

[55:36] which I'm going to explain, a command, a

[55:38] model, and an actor in your software. A

[55:41] domain event is something that happens

[55:42] in the software. It's past tense. um

[55:44] like beer was brewed, grain was added,

[55:47] hops were added, brewer changed email

[55:50] address, things like that, things that

[55:51] happened um you know or will have

[55:53] happened in the past once the software

[55:55] is working and you just start building a

[55:57] chain of these events um as you go

[55:59] through. So recipe was created, the

[56:01] grain bill was added to the software,

[56:05] you start building a huge chain of

[56:07] events. Eventually the chain gets so

[56:09] long you realize, oh, we're talking

[56:10] about recipes and brewing. That's where

[56:12] you can start identifying your about in

[56:14] context when things get too far and too

[56:15] big and complex. So, you know, we split

[56:17] it down. We just look at maybe we'll

[56:19] just look at the the recipe context

[56:20] here. Um, so these are the things you're

[56:22] starting to get about building a recipe.

[56:24] You're going to be adding grain, adding

[56:25] yeast, adding hops. You know, as you you

[56:28] know, go through the I'm just going to

[56:30] speed through this here, but um you

[56:32] know, you look through the um the

[56:34] different events that happen in the

[56:35] system. So, I'm done talking promise for

[56:39] a while. Why this is not going forward?

[56:48] Yeah. All right. Promise done talking.

[56:52] Um, you don't have to listen to anymore.

[56:54] We're going to take a little quick

[56:55] break. Let's, you know, try to give it

[56:56] like five minutes or so. Get your

[56:57] coffee, use the bathroom, whatever. Uh,

[57:00] come back and we're going to start

[57:01] working on this uh uh event storming.

[57:06] When you go back to your companies and

[57:07] and do this, I'm going to do the same

[57:09] thing. um recommend that you know as you

[57:11] start the session you put up the first

[57:13] orange cards which are the events that

[57:15] have happened in the system. You write

[57:16] the first ones get the ball rolling. You

[57:18] may not be right that's fine but at

[57:19] least if everybody's just sitting there

[57:21] staring at each other they're not going

[57:22] to know what to do. So I've created um

[57:24] the first four things in your um you

[57:27] know if you're looking at this diagram

[57:28] that I gave you earlier. These are the

[57:30] first four things that happens. You know

[57:31] brewery plans a session they make a

[57:34] yeast starter which you don't have to

[57:35] worry about too much. You know they

[57:36] measure the grain and then the grain

[57:38] they mill. That's the first one of the

[57:41] first things there is the grain is mil

[57:43] here and then it's put in the mesh mesh

[57:47] in. So those are the events that we're

[57:48] going to talk about and you guys are

[57:49] going to come when you get back we'll

[57:51] we'll start working on that. So soon as

[57:52] you get back just start working

[57:55] I'll be around to answer questions.

[58:03] reason, you know, we're writing these in

[58:04] the past tense and present tense is um

[58:08] that's how they're going to translate to

[58:09] the code. Other than that, there's not

[58:11] really a really good reason. So,

[58:13] examples of foods, you know, if you're

[58:15] looking at the the brewing stuff, it's

[58:16] like a brew session was started. You

[58:18] know, start a brew session, you know,

[58:19] add grain to recipe, add hops to

[58:22] ferment, those are the things you're

[58:23] going to be adding. Now, um so, you

[58:26] know, recipe was created, your command

[58:27] is going to be called create recipe. You

[58:29] know, the grain bill was added, the

[58:31] command is going to be called add grain.

[58:33] you know, water profile is selected.

[58:34] However you guys have, you know, kind of

[58:36] come up with this, you know, you you

[58:38] guys are your own domain experts. So,

[58:39] however you did it is correct. So, go

[58:42] ahead, take the blue stickies, translate

[58:44] your event into a command. Should take

[58:47] you just a couple minutes.

[58:54] Can keep adding your commands if you

[58:55] need to. But, um, moving on, the next

[58:58] thing is the models. So now is when you

[59:01] can kick in your developer brain a

[59:02] little bit and start thinking about the

[59:04] objects and stuff that you're going to

[59:06] be relating to. So this is the things

[59:08] that the commands are done upon and that

[59:10] might be both you know in your case the

[59:13] um the model that you're looking at like

[59:15] the recipe or the ingredient or the

[59:16] brewer. It might be related stuff you

[59:18] know so if you're doing the recipe

[59:19] context create recipe that deals with

[59:21] the recipe adding grain that might be

[59:23] the recipe and the grain kind of you're

[59:25] just trying to figure out what's all

[59:26] involved. So take a couple minutes and

[59:28] work that out.

[59:36] You don't need to write grain 17 times

[59:38] if you can remember. You know,

[59:43] it's not necessarily the data. It is the

[59:45] the things that you're acting upon. So,

[59:48] you know, you're you're interfacing with

[59:50] a brew kettle that could be on there.

[59:52] You know, your objects that it's the

[59:53] things in the world that your software

[59:55] is trying to model. Don't don't worry

[59:57] about okay, we need to know for grain.

[59:59] We need to know its name and its weight

[1:00:00] and its things like that. Don't worry

[1:00:02] about that kind of stuff.

[1:00:12] Okay, so I think you guys are you're far

[1:00:15] enough long on that one. Um the last

[1:00:17] thing and we're kind of actually done

[1:00:19] because the la the last one is the actor

[1:00:23] and that is you know who did the

[1:00:25] command, who did the action. Um, in this

[1:00:28] case, you know, we probably have like

[1:00:29] one person, the brew master or the

[1:00:30] brewer. So, it's probably going to have,

[1:00:32] you know, the same person on every task.

[1:00:35] So, I'm not going to make you um, you

[1:00:37] know, put green sticky on each one. Um,

[1:00:40] but, you know, I do have to congratulate

[1:00:41] you guys. Guys, diagrams are pretty

[1:00:44] pretty pretty good. Um, they're

[1:00:47] terrible. No, I'm just kidding. Um, so

[1:00:50] you covers kind of, you know, building

[1:00:52] the um ubiquitous language.

[1:00:55] Um, does anybody have any, you know,

[1:00:57] questions about the process? The only

[1:00:58] thing I I would say that I've noticed,

[1:00:59] you guys did a good job naming all your

[1:01:01] stuff. Um, some of the things you're

[1:01:03] going to have problems with in code. So,

[1:01:04] if you called something grain and then

[1:01:06] you had an object that's called mil

[1:01:07] grain. Now, that's fine when you're

[1:01:09] building this, but you're going to have

[1:01:10] a problem. You're going to have problems

[1:01:11] transitioning objects with PHP. It's

[1:01:13] difficult unless you separate them into

[1:01:15] different bounded contexts. When you you

[1:01:17] have an object called grain and you have

[1:01:19] a function called mill, you can't change

[1:01:22] that type of object. So it can't

[1:01:24] translate into a new kind of object. You

[1:01:26] have to create another object called mil

[1:01:28] grain gets a little complex. So

[1:01:30] sometimes you may want to store the

[1:01:31] state of the grain as a you know a

[1:01:33] property of that object not having a new

[1:01:34] object called mil grain. But you know it

[1:01:37] might be important enough that maybe

[1:01:38] they're dealing in one section with just

[1:01:40] milk grain. So you may have an object

[1:01:41] called milk grain. It's possible. Does

[1:01:43] anybody have any questions about this?

[1:01:48] Yeah. Uh sure. It so it's basically the

[1:01:51] who did it. So, um, later when we look

[1:01:55] at the command, it's going to be the

[1:01:56] person who, you know, punched the button

[1:01:58] on the software that said add grain. You

[1:02:00] know, the grain was added. It's going to

[1:02:02] be tied to the event. You know, they're

[1:02:04] going to they're going to be a model in

[1:02:06] your in your somewhere in your software.

[1:02:08] You're going to have an object called

[1:02:09] brewer. You know, that's going to be the

[1:02:11] person logging into your software and

[1:02:12] using it. So, you know, they're they're

[1:02:15] not exactly a bounded context. They're

[1:02:16] not really part of any of uh one

[1:02:19] specific particular bounded context.

[1:02:22] what's called a supporting valid

[1:02:23] context. So they're going to show up

[1:02:24] everywhere in your software. There's not

[1:02:26] really a way to avoid that. Um other

[1:02:28] than you can if you know it's complex

[1:02:30] enough, you may want to create a

[1:02:32] inventory user interface or something

[1:02:34] like that. So that way you have a

[1:02:35] limited set of functions on the user in

[1:02:37] that um area of the software. That may

[1:02:39] help keep things a little bit better

[1:02:41] organized. Or if you have very distinct

[1:02:43] teams that are working on different

[1:02:44] parts of the software, you're more

[1:02:46] likely to do that where you have your

[1:02:47] user which is like a symphony user

[1:02:49] Laravel user and that might end up

[1:02:51] implementing like 15 different

[1:02:53] interfaces from different namespaces.

[1:02:56] That answer your question.

[1:03:02] Yeah.

[1:03:06] >> Yeah.

[1:03:09] Event storming. Event storming. Yeah. Um

[1:03:15] there's other ways you can do it and and

[1:03:17] I'll kind of touch at those real quick.

[1:03:18] Um you know, you guys started building

[1:03:20] diagrams. You can see they're already

[1:03:21] getting kind of large. Um you're going

[1:03:23] to want to break those down into bounded

[1:03:25] context like I mentioned as the thing

[1:03:26] gets larger. Um you know, you start

[1:03:28] circling them off. If you're doing it,

[1:03:29] do this on a whiteboard or a big giant

[1:03:31] long sheet of paper so you can you start

[1:03:33] doing it over and separate the stuff

[1:03:35] out. Um, you know, these, like I

[1:03:37] mentioned, these events are going to be

[1:03:38] pushed around to the different contexts.

[1:03:39] So, like the inventory context needs to

[1:03:42] know when a brew session is planned to

[1:03:43] make sure the ingredients are there or

[1:03:44] something like that. You know, we're

[1:03:45] going to order the grain form

[1:03:47] automatically or something like that.

[1:03:48] And it might be, you know, multiple

[1:03:50] events from the same bound context that

[1:03:51] are coming to it. Um, if you're really

[1:03:54] having problems understanding the

[1:03:55] process, the business process and stuff

[1:03:57] like that, um, there's a couple other

[1:03:58] techniques you can use from user

[1:04:00] experience side of things. Uh, one's

[1:04:02] called business origami and um, learned

[1:04:04] about this at 2011 uh, in 2011 at UX

[1:04:06] week. Um, there's a handsome guy in the

[1:04:08] background there,

[1:04:11] but basically you make these fancy

[1:04:12] little cards uh, and you actually

[1:04:14] physically um, let me jump ahead a

[1:04:16] little bit here. You'll see. But like if

[1:04:17] you're building like an e-commerce

[1:04:19] thing, you actually physically move the

[1:04:20] people around the um, you know, origami

[1:04:24] uh, store so to speak buying things. So

[1:04:26] that way you can identify which cards to

[1:04:28] to write on the process. So it might be

[1:04:31] um useful to actually build a physical

[1:04:33] model of the real world in paper or

[1:04:35] something like that in order to figure

[1:04:36] out oh what cards you know do we to have

[1:04:38] in our um event storming session.

[1:04:42] There's other ways to do this too like

[1:04:44] they call it user story mapping and it's

[1:04:46] kind of the same thing. You build like a

[1:04:47] big long list of um events and then you

[1:04:50] try to find you know the different

[1:04:52] things that you're going to do and break

[1:04:54] it up into you know planned releases and

[1:04:55] stuff like that. But I you know I think

[1:04:56] it's the idea here is that we're going

[1:04:59] to identify the behavior first. You know

[1:05:01] people think about software they don't

[1:05:03] think about database models like I was

[1:05:04] mentioning. They think about what does

[1:05:05] the software need to do for me. So

[1:05:07] they're thinking that you know I need to

[1:05:08] be able to add grain to this. I need to

[1:05:09] be able to you know do things. Those are

[1:05:11] the events. So starting with the events

[1:05:13] and starting with the things that have

[1:05:14] to happen in the software is a much

[1:05:16] better way to to build software other

[1:05:18] than starting with the databases and the

[1:05:20] data. Um so I would give this you know a

[1:05:23] correctness and usability much higher as

[1:05:26] compared to you know CRUD code.

[1:05:29] All right. So, we're going to start

[1:05:31] talking about actual code.

[1:05:34] How do you implement this ubiquitous

[1:05:36] language and how do you, you know, make

[1:05:38] software that is maybe completely

[1:05:39] different from how you guys are writing

[1:05:40] it today. And um you what I mentioned

[1:05:43] earlier is going to be heavy on the

[1:05:44] object-oriented uh side of things. Um

[1:05:47] but it's hopefully not too difficult to

[1:05:49] understand. In domain driven design, we

[1:05:52] have pretty much four basic uh kinds of

[1:05:55] entities and objects in our system. We

[1:05:57] have value objects which are going to

[1:05:59] represent um small things in our system,

[1:06:02] pieces of information. Domain events,

[1:06:04] those are the orange cards that you put

[1:06:06] in your event storming uh session there.

[1:06:08] Those going to translate exactly to

[1:06:10] objects in your system. Entities, those

[1:06:12] are your yellow ones, those are the

[1:06:14] models. Um you know that you had a you

[1:06:17] know you have a grain model that's going

[1:06:19] to become an entity. Aggregates um those

[1:06:22] are your fancy um models and I'll get

[1:06:24] into that. They basically contain child

[1:06:26] entities. So

[1:06:28] um you know a value object like I

[1:06:29] mentioned is the smallest pieces of your

[1:06:31] software. Um biggest thing about them is

[1:06:33] they're going to be immutable. Um they

[1:06:35] have no identity. I'll get into that.

[1:06:37] But examples of value objects in the

[1:06:39] brewing thing is like a hop name, an

[1:06:41] amount paid, a temperature, things like

[1:06:42] that. They're they're values. They're

[1:06:44] not um things that have uh things that

[1:06:47] are stangeable about them. Entities are

[1:06:50] things that are identifiable and they're

[1:06:51] mutable and they have a life cycle and

[1:06:53] they're going to operate on those

[1:06:55] smaller value objects and I'll get into

[1:06:57] that later. But an example of models

[1:06:59] might be a line item in a in invoice.

[1:07:02] You know, you could change the quantity

[1:07:04] or change the price. You know, that that

[1:07:06] that could change over time or you could

[1:07:07] delete the line item. So that has a you

[1:07:09] know life cycle. Brewers, the names

[1:07:11] change. They come and they go, they're

[1:07:12] fired. They're hired. Water chemistry,

[1:07:15] you know, you might have a model for

[1:07:16] your your water chemistry. Well, your

[1:07:18] city water changes, you know, daily. So,

[1:07:20] if you're measuring it, you're going to

[1:07:21] be constantly updating your your water

[1:07:23] supply.

[1:07:24] An aggregate. So, an aggregate is

[1:07:26] basically a fancy entity, a bigger

[1:07:28] entity, and it is responsible for

[1:07:30] managing smaller entities, and it's

[1:07:33] primary job. It's going to have business

[1:07:34] logic for sure. Um, but it's going to be

[1:07:37] the um larger, more identifiable objects

[1:07:40] in your thing. So if you had um things

[1:07:42] on your uh eventtorming session like

[1:07:44] brew session um you know that's going to

[1:07:46] be controlling some things as far as

[1:07:48] what state we are in the process and

[1:07:49] stuff like that. the recipe recipe is

[1:07:51] gonna if you flip to the the recipe that

[1:07:53] I gave you in the packet there it has

[1:07:55] hops it has grains it has yeast you know

[1:07:58] it's got to contain all these other

[1:07:59] models so it's got to manage and it's

[1:08:01] got to hold them all together to build

[1:08:02] one giant thing called a recipe that's

[1:08:05] an aggregate

[1:08:08] but if of all those things value objects

[1:08:11] are by far the most important

[1:08:14] so um the value objects again we were

[1:08:18] talking about out of kind of this the

[1:08:19] brewing You might have an email address

[1:08:21] for a brewer. I don't know. That's kind

[1:08:22] of an easy example. A recipe name. Um

[1:08:24] the date we brewed the beer on. That's

[1:08:26] an example of a value in the system that

[1:08:28] is immutable. You can't change when we

[1:08:30] brewed it on. The weight of grain you

[1:08:32] might have, you know, that's a 13 pounds

[1:08:34] is 13 pounds. You can't you can change,

[1:08:37] you know, how much grain you've weighed

[1:08:38] from 13 to 15 pounds, but the value of

[1:08:41] 13 pounds does not change. It's that is

[1:08:43] 13 pounds. You know, 70 degrees uh

[1:08:46] Fahrenheit is 70 degrees Fahrenheit.

[1:08:48] There's no changing that. If you change

[1:08:49] to 71 degrees, that's as a new

[1:08:51] temperature.

[1:08:53] And all these value objects in the

[1:08:54] system are going to come directly from

[1:08:55] the ubiquitous language that you know

[1:08:57] when somebody if they call it, you know,

[1:09:00] uh the date we brewed on, yeah, you

[1:09:02] might want to shorten that to brood on

[1:09:03] in your code or something like that. But

[1:09:04] if they call it a recipe name, it's a

[1:09:06] recipe name in your code.

[1:09:09] And we're going to have classes that map

[1:09:11] directly to um the classes or we're

[1:09:14] going to have classes that map that you

[1:09:16] look at this language directly to the

[1:09:18] objects in our software. So if you're

[1:09:20] talking about temperature in the brewery

[1:09:22] that you're building software for it

[1:09:24] does everything in Fahrenheit, well

[1:09:25] you're going to have a class called

[1:09:26] degrees Fahrenheit that's going to

[1:09:27] represent that. Um there's no reason to,

[1:09:29] you know, build it out in Kelvin. There

[1:09:31] just brewers don't talk in Kelvin. They

[1:09:33] don't, you know, think about in, you

[1:09:34] know, Kelvin or even maybe degrees

[1:09:35] Celsius depending where they're from. So

[1:09:37] have a degrees Fahrenheit class because

[1:09:39] that's how they're going to class in

[1:09:40] your software because that's how they're

[1:09:41] going to have to put information in.

[1:09:42] They're they're going to want to use

[1:09:43] degrees Fahrenheit and everything.

[1:09:44] They're not going to have to convert.

[1:09:47] And you know these objects are not just

[1:09:49] about creating uh classes that do static

[1:09:52] typing, meaning type hitting in your

[1:09:53] functions. That's not the point of them.

[1:09:55] Um there's studies that have shown that

[1:09:56] you know just the variable names is

[1:09:58] enough to keep you from swapping

[1:09:59] parameters. That's not the whole point.

[1:10:01] Um the point of value objects is to

[1:10:03] reduce complexity and reduce um checking

[1:10:06] in your software. So value objects I

[1:10:09] mentioned are immutable meaning they do

[1:10:11] not change. Um there's no in there's no

[1:10:14] factor of time involved in a in a value

[1:10:16] object. You know the temperature doesn't

[1:10:18] change over time. 70 degrees Fahrenheit

[1:10:20] is 7 degrees Fahrenheit regardless of

[1:10:22] when it is. The other reason um you want

[1:10:25] to have as many objects in your system

[1:10:27] uh immutable in your software is because

[1:10:30] PHP passes objects by reference and if

[1:10:33] you pass an object to a function that is

[1:10:36] mutable. So um that function could

[1:10:38] change something on that object and you

[1:10:40] don't know that. So when that object

[1:10:41] that you pass in could be changed. Now

[1:10:43] if it's an immutable object like a value

[1:10:45] object and you pass that to that

[1:10:46] function you don't have to worry about

[1:10:47] that object being changed. So if I pass

[1:10:49] 70 degrees Fahrenheit to a function, I

[1:10:51] don't have to worry about it coming back

[1:10:52] as 68 degrees. It's not possible. That

[1:10:54] object is locked and it's immutable.

[1:10:56] There's no possible way to do it.

[1:10:59] The other way um the other thing that

[1:11:01] helps you in your software here is your

[1:11:02] your value objects will always be in a

[1:11:04] valid state. Now they don't have state,

[1:11:05] but what I mean by that is they're

[1:11:08] always valid. So 70 degrees Fahrenheit

[1:11:10] is a valid temperature. Now if anybody

[1:11:14] remembers from high school physics,

[1:11:15] there's something called absolute zero.

[1:11:17] you know, you can't be below what 273

[1:11:19] degrees Celsius. You know, 300 degrees

[1:11:22] negative Celsius is not a valid

[1:11:24] temperature. So, we're going to prevent

[1:11:26] that uh in this uh value object class.

[1:11:28] So, anywhere you deal in temperatures,

[1:11:30] you know, it's always a valid

[1:11:31] temperature.

[1:11:33] Value objects become like the thin candy

[1:11:35] shell uh in your application where

[1:11:37] everything stops and keeps everything

[1:11:39] from hitting the nice um creamy center

[1:11:40] in the middle of your application. the

[1:11:42] earlier you can solve problems in value

[1:11:44] objects um the easier you're going to

[1:11:46] have time uh building software

[1:11:49] if you're not doing software uh you're

[1:11:51] not doing test-driven development now

[1:11:53] value objects are a gateway drug to test

[1:11:55] driven development they um are by far

[1:11:57] the easiest to develop doing test driven

[1:11:59] methods

[1:12:01] #my tests don't pass

[1:12:05] so what are value objects they're like I

[1:12:07] mentioned they're just small little

[1:12:08] classes that have one purpose they're

[1:12:10] plain PHP objects

[1:12:12] Um they don't necessarily have to

[1:12:14] inherit from anything or be part of

[1:12:15] something else. They're called call them

[1:12:17] popos. I mean a plain old PHP object. Um

[1:12:21] they're all their properties are

[1:12:24] private. There's no public way to change

[1:12:26] anything about them. Um there's no

[1:12:29] setters on them. Like I said, you can't

[1:12:30] change anything about them. They're

[1:12:32] mutable. U they don't hold references to

[1:12:34] mutable objects. Um, so you know like uh

[1:12:39] a grain for example, you can't have that

[1:12:41] as a value object because the grain

[1:12:44] could actually change like different

[1:12:45] acids and stuff like that or enzymes

[1:12:47] could be different in the grain. So you

[1:12:48] can't hold a value object and have an

[1:12:50] entity inside of it that can change.

[1:12:52] It's not possible. That value object if

[1:12:54] it's 70 degrees Fahrenheit, like I said,

[1:12:56] should be 70 degrees Fahrenheit forever.

[1:12:57] There's no change to it. The biggest

[1:12:59] difference um in domain driven design

[1:13:02] code versus most code is um we're going

[1:13:04] to throw as many exceptions as possible

[1:13:06] in the construction of these objects.

[1:13:08] And exceptions are going to be your

[1:13:09] friend. You're going to catch these

[1:13:10] exceptions when you need to to react to

[1:13:12] it. But for the most part um you know a

[1:13:14] lot of your validation is going to come

[1:13:16] from throwing exceptions in the

[1:13:17] constructor.

[1:13:20] And like I said, value objects only

[1:13:22] depend on scalers and other value

[1:13:24] objects. Um so like I said, you can't

[1:13:25] pass an ID to a value object and hold

[1:13:27] it. um 70 degrees Fahrenheit. To hold

[1:13:30] that, you need maybe a float that's 70

[1:13:33] and a unit that's Fahrenheit. So there

[1:13:35] might be two values you need to hold.

[1:13:36] Those don't change. Um that's all the

[1:13:38] dependencies that this this value object

[1:13:40] is going to have. Um and they're not

[1:13:42] dependencies that you have to inject

[1:13:44] either. Um so you know, sure, if you're

[1:13:46] following Solid Principles, you know,

[1:13:48] dependency injection, things like that,

[1:13:49] if you have repositories and services

[1:13:52] and stuff like that, you don't want to

[1:13:53] just be littering those willy-nilly in

[1:13:55] your code. That's that's a bad practice.

[1:13:57] Value objects are a little bit

[1:13:58] different. Um they're pretty much like

[1:14:00] scalar types. Like do you worry about

[1:14:01] having integers in your code anywhere or

[1:14:04] strings? No, you don't. You don't worry

[1:14:05] about that. These are pretty much just

[1:14:06] an extension of the scalar types. So

[1:14:09] don't worry about saying new temperature

[1:14:11] in anywhere in your code. It's it

[1:14:13] doesn't have any dependencies. It's

[1:14:14] designed that way. Uh it's going to be

[1:14:16] perfectly fine to have those new uh

[1:14:18] things happening in your code. You may

[1:14:20] um you know value object gets very

[1:14:22] complex. You may need a factory which

[1:14:24] you know if you guys are familiar with

[1:14:25] patterns you may need a factory to build

[1:14:28] that uh value object sure you might want

[1:14:30] to inject that in that case but for the

[1:14:32] most part value objects you just put

[1:14:34] them wherever you need to put them and

[1:14:35] use them. All right enough talking about

[1:14:39] value objects let's look at an example

[1:14:40] and I put this example in the packet

[1:14:42] that I put out just so you guys can see

[1:14:44] it a little bit closer. Um but let's

[1:14:46] talk about you know the business rules.

[1:14:48] Uh we're going to apply those directly

[1:14:50] to our code. So the brewers have told us

[1:14:52] that yeah we name all our recipes and

[1:14:54] they have to be nice creative witty

[1:14:55] names um that we put up on the board and

[1:14:58] everybody smirks at and they they sniff

[1:15:00] it first and drink it. No, I mean so

[1:15:02] important thing is to have you know some

[1:15:04] business rules associated with this

[1:15:06] recipe name. And basically the business

[1:15:07] rule is that a recipe name cannot be

[1:15:10] empty. So if I if I create a new recipe

[1:15:13] name object and I pass an empty value in

[1:15:16] it should blow up. So it's going to

[1:15:17] throw an exception. you know, if I add

[1:15:20] if I pass in a valid name, it should

[1:15:22] give it back to me in the getter. So,

[1:15:24] it's get value. It's kind of a simple

[1:15:25] way of saying, you know, give me back

[1:15:27] the value out of this object.

[1:15:29] A lot of times I like to do on these

[1:15:31] simple value objects, if you can cast

[1:15:33] into strings, we'll put a two-string

[1:15:35] method in that'll just cast it. So, you

[1:15:37] don't have to have get value everywhere

[1:15:38] in your code. Uh, can get a little

[1:15:40] verbose. Hopefully, those are nice witty

[1:15:42] names like iphpa and recursive viton.

[1:15:46] So, uh, like I mentioned the recipe

[1:15:48] test, I think you guys can see that I

[1:15:50] printed it out.

[1:15:52] So, um, like I said, we're doing

[1:15:54] test-driven development. We've added our

[1:15:56] test. Let's run it. And everything fails

[1:15:58] because the class doesn't exist. The

[1:15:59] method's not found, all of that. So,

[1:16:02] let's start, uh, by building that class.

[1:16:04] And like I mentioned, the thing that

[1:16:05] we're going to do most of the time in

[1:16:07] these value objects is throw an

[1:16:08] exception in the constructor when things

[1:16:10] fail. So, when you're building your

[1:16:12] value objects, you're going to try to

[1:16:13] identify the failure points for these

[1:16:15] value objects. So, if the value that's

[1:16:17] passed in is a string, we don't have to

[1:16:19] test if it's string because we're using

[1:16:20] PHP 7.1. Um, if we're using PHP 5, you

[1:16:24] couldn't type hint that string there. If

[1:16:26] it was value, so you'd have an

[1:16:27] additional check like if uh not is

[1:16:31] string in PHP, you would then throw an

[1:16:32] exception saying this is not a valid

[1:16:34] string. Um, but yeah, I mean, if it's

[1:16:37] empty, we throw an invalid recipe name

[1:16:39] exception. In this case, I've created an

[1:16:40] exception class because maybe you need

[1:16:42] to deal with that exception specially.

[1:16:43] If you don't need to deal with the

[1:16:44] exceptions especially in this case throw

[1:16:46] an invalid argument exception which is

[1:16:48] in the root you know base name space of

[1:16:50] PHP that that's perfectly fine I I do

[1:16:52] that in some of the examples and then we

[1:16:54] hold the value and

[1:16:57] that you know that is enough to pass our

[1:16:58] first test in that uh recipe test thing

[1:17:01] where it's testing to make sure we pass

[1:17:03] an empty string

[1:17:05] it fails.

[1:17:08] Next thing we have to do is we just add

[1:17:09] a get value function and that returns

[1:17:11] the value back out of the value object

[1:17:14] again. Run the next test pass test

[1:17:16] passes and then the uh tworing that's

[1:17:19] really easy to implement. You just get

[1:17:21] the value back. You could also just wrap

[1:17:22] the the get value function. Um you know

[1:17:25] internally you could just call that

[1:17:27] public function internally. Not a big

[1:17:28] deal. Um, I mean, again, I don't I

[1:17:31] wouldn't stress too bad or too much

[1:17:34] about the value objects and how you

[1:17:35] implement them. As long as you're

[1:17:36] testing them and you're um, you know,

[1:17:38] you're wrapping things in test and

[1:17:39] you're identifying the fault points. The

[1:17:41] internal code, if you want to, you know,

[1:17:43] get fancy with your implementation

[1:17:44] there, that's fine. Do whatever you

[1:17:45] want. Important thing is you test,

[1:17:47] lights are green, tests are clean. It's

[1:17:50] in the trap. You know, thing is it's

[1:17:52] locked down. So now you know as we look

[1:17:54] at this recipe name class anywhere I use

[1:17:57] this in the system I'm guaranteed that

[1:17:59] the recipe name is valid. So it's kind

[1:18:01] of a different way of looking at code is

[1:18:03] you no longer ever have to check on this

[1:18:05] recipe name throughout everywhere in

[1:18:07] your code. Recipe name is now valid.

[1:18:09] It's now a valid object. It's not

[1:18:11] possible for somebody to create an

[1:18:12] invalid recipe name.

[1:18:14] Look at another example. Get get a

[1:18:16] little bit more advanced. Um so a brewed

[1:18:19] on like when was the recipe brewed on?

[1:18:21] you know, we write a test for that.

[1:18:22] We're just going to create a new

[1:18:23] datetime, and it should give us back,

[1:18:25] you know, a datetime uh immutable uh

[1:18:28] value. So, you know, you just hold it.

[1:18:30] Datetime already does the validation for

[1:18:32] you. You know, it's going to throw an

[1:18:34] exception if it's an invalid date. So,

[1:18:35] for the most part, you're done. Um but,

[1:18:38] you know, if you want to add some

[1:18:39] business rules in there, maybe to catch

[1:18:41] edge cases and things like that, you

[1:18:42] can. You know, like, oh, you know, it's

[1:18:44] not possible because we're writing the

[1:18:45] software today for there to be a date

[1:18:47] that's less than, you know, 2017

[1:18:49] November 15th. It's not possible. the

[1:18:50] software didn't exist. So throw an

[1:18:52] exception if the date's too far in the

[1:18:54] past or you know oh maybe this we know

[1:18:55] this software is only going to last a

[1:18:57] year so we put it in the future you know

[1:18:59] things like that you know it you want to

[1:19:00] try to stop anything you identify that

[1:19:03] are problems with that uh object in the

[1:19:06] constructor

[1:19:08] another example of pounds you know um we

[1:19:11] can test that value uh like I mentioned

[1:19:13] make sure it's a float um you know it's

[1:19:16] not really possible to have a negative

[1:19:17] weight you know unless we discover

[1:19:19] antimatter weight is always positive So

[1:19:22] you can treat pounds as you know

[1:19:23] positive in your system and throw like

[1:19:26] at the bottom one here test negative

[1:19:27] throws exception you know it's easy to

[1:19:29] check that um you know value is less

[1:19:31] than zero uh may not be negative now

[1:19:35] because PHP can be screwy sometimes you

[1:19:38] want to identify like I said pounds

[1:19:39] always must be positive you want to

[1:19:41] identify a way that that makes sense to

[1:19:43] both you and the business of what this

[1:19:45] object is going to represent. PHP has

[1:19:47] this nasty thing of a negative zero.

[1:19:51] What is negative zero? It doesn't make

[1:19:52] any sense. Let's eliminate that from our

[1:19:54] domain. Um, you know, so we can just

[1:19:56] cast it to a regular zero if we have

[1:19:58] negative. That way, if they print it out

[1:20:00] and it's zero pounds, it doesn't

[1:20:01] accidentally show up as negative 0

[1:20:03] pounds and confuse the hell out of them.

[1:20:05] You know, your two string in this case,

[1:20:07] you know, maybe the breweries decide

[1:20:09] that, you know, they don't have to worry

[1:20:10] about anything less than, you know,

[1:20:11] 0.0001 ounce, you know, pounds. Do your

[1:20:14] formatting and your value objects. do

[1:20:15] your rounding. You know, you might want

[1:20:17] to hold the entire value. If it's like a

[1:20:19] long float, you may want to hold that.

[1:20:20] But when you get the value out or we

[1:20:22] display it to them, you handle your

[1:20:23] formatting here. Now, that's only for

[1:20:25] simple things, uh, like, you know,

[1:20:27] pounds and stuff like that. If you have

[1:20:28] dates and more complex objects and you

[1:20:31] need to format it, again, looking at

[1:20:32] solid principles, it's a good idea to

[1:20:34] separate your formatterers into another

[1:20:35] class or into a template, things like

[1:20:37] that. Again, those policies apply.

[1:20:41] The the thing I mentioned about

[1:20:43] immutable in the value objects doesn't

[1:20:45] mean that you can't have behavioral

[1:20:46] functions on a in a value object. That

[1:20:49] is definitely possible. The trick is

[1:20:51] though is we're going to return a new

[1:20:53] object um if you change something. So if

[1:20:56] we had 11 pound or 10 sorry 10 pounds

[1:20:59] and we want to reduce that amount by 6.1

[1:21:02] pounds, we expect a value of 3.9. Now

[1:21:04] what that is actually going to return is

[1:21:06] a new pounds object with 3.9 pounds in

[1:21:10] it. As I mentioned that that original

[1:21:12] one we 10 10 we passed it's not mutable.

[1:21:14] So it cannot change. It will return a

[1:21:16] new object.

[1:21:20] So like I mentioned biggest thing about

[1:21:22] value objects is it eliminates checking.

[1:21:25] So the pounds object decrease by

[1:21:28] function. A little bit hard to see maybe

[1:21:30] there at the bottom. Um but yeah like I

[1:21:32] said the first thing you're going to do

[1:21:33] there is new self

[1:21:37] in your object. So you're going to

[1:21:38] return a pounds object because like I

[1:21:40] said the value objects are not are

[1:21:41] immutable. You cannot change them. And

[1:21:43] you're just going to say this value

[1:21:45] minus decrease by pounds get value. You

[1:21:47] don't have to check and see if the

[1:21:48] pounds are negative or like in case the

[1:21:50] recipe name. You don't have to check if

[1:21:51] it's a string or anything like that.

[1:21:52] It's all done. I don't even have to

[1:21:54] check that when I'm subtracting, you

[1:21:57] know, say have six pounds and I try to

[1:21:58] subtract 10. I don't have to check that

[1:22:00] here because it's not possible. the

[1:22:02] constructor will catch that because this

[1:22:04] will come in as a negative value and

[1:22:06] it'll be neg3 and the exception will be

[1:22:07] thrown weight cannot be negative. So a

[1:22:10] lot of your checking and if logics and

[1:22:12] stuff like that can be handled by the

[1:22:13] the the um value objects you know like

[1:22:15] mentioned the 70 degrees if you try to

[1:22:18] subtract 400 degrees from that it's not

[1:22:20] possible the absolute zero is going to

[1:22:21] catch that you have a question

[1:22:42] >> Yeah, that that's perfectly fine. Like

[1:22:44] um yeah, if you had a weight object in

[1:22:46] and say it's you just want to deal

[1:22:47] because you're dealing in many

[1:22:48] measurements like let's say that not

[1:22:49] like a brewery where it's all pounds

[1:22:50] because it's in the US. Um yeah, you

[1:22:52] have a weight object and you're going to

[1:22:54] have to store I'm going to get into this

[1:22:55] in a second, but it's they call it a

[1:22:57] composite value object. So weight is

[1:22:59] going to contain two diff distinct value

[1:23:01] objects probably maybe in the case

[1:23:03] probably just a float just a regular you

[1:23:05] know PHP object float for the and then a

[1:23:08] string or a unit of measure object that

[1:23:11] represents the unit. So then anytime

[1:23:14] like this if you're like decrease like

[1:23:16] let's say it's kilograms you try to

[1:23:17] decrease it by pounds in your you know

[1:23:20] you can throw exceptions there and say

[1:23:22] like hey you know what the units don't

[1:23:24] match or you can do the conversion if

[1:23:25] that's business is like yeah we get

[1:23:27] stuff randomly all the time we want to

[1:23:28] do the conversion automatically be nice

[1:23:30] and do it for them don't throw an

[1:23:31] exception say oh you must put this in

[1:23:33] pounds you know build these rules into

[1:23:35] your business build intelligence into

[1:23:36] your software you know like I mentioned

[1:23:38] before the factories if it's difficult

[1:23:40] to create an object from a string or

[1:23:42] something like Feel free to build a

[1:23:44] factory if that's the way you want to do

[1:23:45] it. I mean, it's fine. However you

[1:23:47] operate, you know, building your code

[1:23:48] now is probably for the most part fine.

[1:23:50] It's mostly just naming and

[1:23:51] understanding that these value objects

[1:23:53] are going to be immutable and always in

[1:23:55] always valid.

[1:23:57] Um, one of the things I like to do on

[1:23:59] stuff is like static constructors on

[1:24:01] these value objects. Go ahead real

[1:24:02] quick.

[1:24:07] >> Yeah.

[1:24:13] Now, now PHP especially five, you know,

[1:24:18] five or 54 up objects are incredibly

[1:24:22] easy to generate. The only time you'll

[1:24:24] run into a problem is if you build um

[1:24:28] recursive

[1:24:30] like issues where okay um you know I

[1:24:33] want to make sure that the Fahrenheit

[1:24:35] object can't be below absolute zero.

[1:24:38] Well, I can't build a absolute zero

[1:24:41] Fahrenheit object that extends

[1:24:43] Fahrenheit because it's not possible for

[1:24:45] it to be absolute zero. It's just not,

[1:24:47] you know, so you end up having to make

[1:24:49] sure you kind of separate things a

[1:24:50] little bit. But objects are cheap. PHP

[1:24:53] objects are very very cheap. So don't

[1:24:55] don't be afraid of creating all these

[1:24:56] objects and stuff.

[1:24:58] Good question. Okay. Um, so static

[1:25:01] constructors and I like to call these

[1:25:02] natural language constructors. They're,

[1:25:04] you know, they're coming from the

[1:25:05] ubiquitous language. coming from what

[1:25:07] you know um somebody talks about you

[1:25:09] know maybe in the example here we have

[1:25:11] pounds but we want to sometimes we get

[1:25:12] stuff in that's metric in kilograms um

[1:25:15] you know you have a function that's

[1:25:16] static function from kilograms and this

[1:25:18] will return a a new pounds object and do

[1:25:21] the math for you now your software is

[1:25:23] just dealing in pounds not worrying

[1:25:24] about kilograms and stuff like that but

[1:25:26] we know that that weight is always valid

[1:25:30] so

[1:25:31] um

[1:25:33] yeah I mean you might have to do you may

[1:25:35] even want something like from string. So

[1:25:37] if somebody writes like 2.0 lbs, um you

[1:25:40] may have you may want to write some

[1:25:41] parsing logic there that does some reax

[1:25:43] or something fancy and does that.

[1:25:49] I think I've um you know done the

[1:25:51] temperature example here a few times. Um

[1:25:54] you get the you know the formulas and

[1:25:56] stuff like that. I was going to do an

[1:25:57] example but I think I'm going to move

[1:25:58] past that. Does everybody kind of get

[1:25:59] the idea that we're, you know, you're

[1:26:01] creating these objects, they're

[1:26:02] immutable, and um, you know, you do all

[1:26:04] the validation in the constructor? Just

[1:26:05] think everybody got that?

[1:26:13] >> No.

[1:26:15] >> Yeah. Do whatever you need to do. Um,

[1:26:16] like I was saying, like it's two float,

[1:26:18] pounds a string, something like that

[1:26:19] unit of measure. And I'm just about to

[1:26:20] go into like composits of these. So, um,

[1:26:24] but you know, like I was saying, the the

[1:26:26] units are important getting those right.

[1:26:28] You know, if you've heard stories about

[1:26:29] the Mars Climate Orbiter that crashed

[1:26:31] into Mars because they were working in

[1:26:33] miles and kilograms, you know, things

[1:26:35] like that. Um there was a the plane

[1:26:37] called the Gimly Glider that um you

[1:26:39] know, they they weighed the the fuel in

[1:26:42] kilograms instead of pounds. It didn't

[1:26:44] have enough like, you know, had half you

[1:26:46] know, whatever was less than half the

[1:26:48] fuel it was supposed to had to, you

[1:26:49] know, crash land. Luckily, nobody was

[1:26:50] hurt. Um you know, these are the kind of

[1:26:54] things you can eliminate by using these

[1:26:55] value objects. um and making sure that

[1:26:57] you know it's not possible to have

[1:26:58] invalid state in your app. All right, so

[1:27:02] composite value objects um easy example

[1:27:06] would be a brewer's name. So a brewer

[1:27:09] full name, you know, might consist of a

[1:27:11] first name and a last name. If we look

[1:27:14] at the the full name object,

[1:27:17] uh there's really nothing to validate

[1:27:19] here other than the fact that there is a

[1:27:21] first name and a last name because first

[1:27:23] name is a value object. It's just going

[1:27:24] to make sure it's not empty just like

[1:27:25] the recipe name. Last name value object,

[1:27:28] it's going to make sure it's not empty.

[1:27:29] So the full name, we know now passing

[1:27:32] that around anywhere in our system, we

[1:27:34] know exactly what a full name is always

[1:27:36] valid. It's not possible to have empty

[1:27:37] strings. And right here, we can

[1:27:39] implement the two string method of how

[1:27:41] to represent that in the system. So if

[1:27:43] later you decide to add middle names and

[1:27:45] suffixes, prefix and stuff like that, um

[1:27:47] you don't have to worry about where

[1:27:48] you've, you know, said, you know, two

[1:27:50] string or get value on a full name or

[1:27:52] formatted that. It's, you know, you just

[1:27:54] have to update the constructor and where

[1:27:55] you've used it and stuff like that. Um,

[1:27:57] but yeah, I mean, we've eliminated a lot

[1:27:59] of checking here. There's no checking to

[1:28:01] make sure first name is not empty and

[1:28:02] last name is not empty. We're relying on

[1:28:04] these value objects to compose

[1:28:05] themselves.

[1:28:07] We're going to, you know, the goal here

[1:28:09] is to encapsulate as much of our

[1:28:10] business logic in the value objects as

[1:28:12] possible. Like I mentioned, the

[1:28:13] temperature thing. Um, you can get very

[1:28:15] complex with these value objects. So,

[1:28:18] one of the things that a brewery is very

[1:28:20] concerned with is the amount of alcohol

[1:28:21] that is in a beer. Um, you know, they

[1:28:24] have to put it up on their board. They

[1:28:25] have to tell you by law how much alcohol

[1:28:27] is in a beer. And, uh, they call it ABV.

[1:28:30] If you see that up on the board, that'll

[1:28:32] tell you, you know, alcohol by volume,

[1:28:33] it's 7% alcohol. Um, you know, that's

[1:28:36] kind of a stronger beer. So, don't

[1:28:38] drink, you know, 10 of them. But the way

[1:28:41] you find out how much alcohol is in a

[1:28:43] beer, you can obviously send it out to a

[1:28:45] lab and spend a ton of money, have it

[1:28:47] analyzed, um, or you can just calculate

[1:28:49] it using some measurements. And if you

[1:28:52] know about the brewing process there,

[1:28:54] like I was telling you, if sugar and

[1:28:55] yeast turn alcohol and uh CO2 out the

[1:28:59] other side, um there's actually a

[1:29:01] chemical equation for this, but I'm not

[1:29:02] going to bore you to death with that.

[1:29:04] But if we're trying to calculate the

[1:29:05] amount of alcohol that comes out, we

[1:29:06] know we don't care about CO2 and we

[1:29:08] don't care about the yeast. That doesn't

[1:29:09] affect the amount of alcohol that comes

[1:29:10] out at all. Well, we care about the

[1:29:12] sugar and the sugar, the amount of sugar

[1:29:14] we start with and the amount of sugar

[1:29:15] that we end with. Now, like I said,

[1:29:17] yeast consumed sugar. So if we know how

[1:29:19] much sugar the yeast consumed, we know

[1:29:21] roughly how much alcohol a yeast

[1:29:23] produces when it eats that sugar. We can

[1:29:25] calculate how much alcohol is in the

[1:29:27] solution. So we get alcohol by volume.

[1:29:30] By dividing those two things um you know

[1:29:33] subtracted from each other. Now you

[1:29:35] measure that um amount of sugar in a

[1:29:38] thing called specific gravity, but it's

[1:29:39] basically the density of the sample

[1:29:41] versus the density of water. And you can

[1:29:42] do that very expensively. If you're a

[1:29:43] professional brewer, you probably buy,

[1:29:45] you know, a machine that to do that. Um,

[1:29:48] but many craft breweries and every home

[1:29:50] brewer does, and I have one of these up

[1:29:52] there here if you want to look at it

[1:29:53] later. It's a hydrometer and basically

[1:29:55] it you put it in the water or you put it

[1:29:57] in the the W that came out of the boil

[1:29:59] kettle and you measure how far it

[1:30:01] floats. And um, you know, so it floats

[1:30:04] in the solution. It has a little scale

[1:30:05] on it so you can measure, you know, how

[1:30:07] much it goes up and down. And if you

[1:30:09] know anything about chemistry, the

[1:30:11] density of something lowers as it heats

[1:30:13] up. Things expand. Like water actually

[1:30:16] grows. I think it's like 5% from cold to

[1:30:19] boiling like the volume of water grows

[1:30:21] um in a solution. So, um when you're

[1:30:25] measuring that specific gravity, you

[1:30:26] have to know exactly what temperature

[1:30:27] you're measuring that specific gravity

[1:30:29] at because um like I showed you earlier,

[1:30:32] that hydrometer has been scaled and

[1:30:34] measured exactly a certain temperature.

[1:30:36] So, in my case here, I have a 60°ree

[1:30:39] hydrometer. So, that scale is meant for

[1:30:41] 60° uh Fahrenheit.

[1:30:44] And you can look it up on a table and

[1:30:46] figure out how much to move, you know,

[1:30:48] the the temperature uh with specific

[1:30:50] gravity. Um or you can try to you can

[1:30:52] calculate it very easily. So I look at

[1:30:54] um I put a thermometer in when I do the

[1:30:56] measurement. So I know like in this case

[1:30:58] it was it's kind of hard to see there,

[1:30:59] but 66 uh degrees and I measured the

[1:31:03] specific gravity and my you know my

[1:31:05] hydrometer's set at 60. Do a little bit

[1:31:08] of math and it's actually kind of

[1:31:10] complex math but you can calculate you

[1:31:13] know what it was supposed to be reading.

[1:31:14] So if it read 1.040, we know it's

[1:31:16] actually 1.041 because the temperature

[1:31:19] adjusted it slightly. And it's not a

[1:31:21] very hard calculation to do. So kind of

[1:31:23] use this as an example with the

[1:31:24] composite value objects to do this. So

[1:31:27] the hydrometer test, you know, we're

[1:31:29] going to look at the um building a test

[1:31:30] for this first because I said like I

[1:31:32] mentioned u testing value objects is

[1:31:34] pretty easy. I just pulled values from

[1:31:36] that table and you know when the

[1:31:38] temperature is exactly the temperature

[1:31:40] of the hydrometer, everything should

[1:31:41] match up. That's an easy test, right? Uh

[1:31:44] then we do maybe a test a bit higher,

[1:31:46] put some values in there, you know, do a

[1:31:49] test a bit lower, do the same thing. And

[1:31:52] we're going to end up building a

[1:31:54] composite value object that's called a

[1:31:57] gravity or original gravity. In this

[1:31:58] case, if you're measuring it before the

[1:32:00] the yeast has eaten the sugar out of the

[1:32:03] the wart, it's called the original

[1:32:04] gravity. So, we're going to call we're

[1:32:05] going to create a value object that's

[1:32:06] called original gravity. And to read the

[1:32:09] gravity reading, like I mentioned, you

[1:32:10] read the gravity reading off the

[1:32:11] hydrometer. So that's a float value

[1:32:13] object that we've made sure is within a

[1:32:15] reasonable range. And a temperature that

[1:32:16] we know is within a reasonable range as

[1:32:18] well. So um

[1:32:21] you know, we we know that we can verify

[1:32:23] that the hydrometer, you know, class

[1:32:25] here can value object can tell you, you

[1:32:27] know, you can't read a value above or

[1:32:28] below the the scale. And you know, we

[1:32:30] can do the logic right here to correct

[1:32:32] the gravity for the temperature. So it's

[1:32:34] like I said, a big long equation. um but

[1:32:37] it's all centralized in this value

[1:32:39] object. So the business rules and the

[1:32:40] business, you know, uh the way they're

[1:32:43] they do things, we're putting as much as

[1:32:45] we can in the value objects.

[1:32:50] So like I said, we want to um find the

[1:32:52] uh gravity here, you know, the alcohol

[1:32:54] by volume. This is the formula right

[1:32:56] here. There's our readings. Original

[1:32:58] gravity is OG and final gravity would be

[1:33:01] after the yeast eats it. And that's the

[1:33:02] formula for creating it. Now we can also

[1:33:05] create a composite value object out of

[1:33:06] that. We can have a gravity range. So

[1:33:09] gravity range value object becomes a

[1:33:11] original gravity and a final gravity.

[1:33:13] Now we can make sure right in this value

[1:33:15] object that the original gravity is

[1:33:17] lower than the or sorry is lower than

[1:33:19] the final gravity because as the yeast

[1:33:21] eats sugar the amount of sugar in there

[1:33:23] becomes less. The gravity actually

[1:33:25] becomes lower. Um so we can verify that

[1:33:27] you know somebody is putting in stuff

[1:33:29] properly and that's all this object

[1:33:31] needs to be. It just needs to be a

[1:33:32] holder of you know those values perhaps

[1:33:35] and then you know the class when we

[1:33:37] write the alcohol by weight and the

[1:33:38] alcohol by volume can work from that

[1:33:41] gravity range. So this is again another

[1:33:42] value object that has a static

[1:33:44] constructor that creates itself from

[1:33:46] another value object and the formula is

[1:33:48] right in here. So I don't have to

[1:33:49] validate anything you know as far as the

[1:33:51] gravity ranges go. All that's been

[1:33:53] validated for me temperatures the

[1:33:54] readings all that stuff's validated. I

[1:33:56] just have to worry about building the

[1:33:57] formula here and doing the math and to

[1:34:00] actually calculate ABV then you know we

[1:34:02] do that final function equation there

[1:34:05] and we end up with another value object

[1:34:07] that is the alcohol by volume. So you

[1:34:08] can guarantee everywhere in the software

[1:34:10] that the alcohol by volume has been

[1:34:12] validated nothing to do no checking. I

[1:34:15] want to contrast that you know real

[1:34:16] quick with u I mentioned that brewer

[1:34:18] wall and that that's a PHP software

[1:34:20] application but if you look and this is

[1:34:22] just one class of calculations they have

[1:34:25] um you know they have ABV OG and final

[1:34:27] gravity um you know they're checking is

[1:34:30] the original gravity more than the final

[1:34:32] gravity is it a numeric value is it a

[1:34:34] numeric value you know they're doing

[1:34:35] that and if you look through that one

[1:34:37] class um you know as they do it they do

[1:34:39] it over and over over again they

[1:34:40] actually you can't see because it's

[1:34:41] getting cut off the top of the projector

[1:34:43] here but they check og greater than

[1:34:45] final gravity five times in one class.

[1:34:48] So right there um you know you're

[1:34:50] repeating code. That's one of the first

[1:34:51] things we learn is don't repeat

[1:34:52] yourself. Don't repeat yourself. Don't

[1:34:54] repeat yourself. Don't repeat yourself.

[1:34:55] Don't repeat yourself. Um it's a big

[1:34:57] thing in code. You know the is numeric

[1:34:59] checks. Not having those value objects

[1:35:00] that represent a float knowing that a

[1:35:02] final gravity is accurate. They did that

[1:35:04] 39 times in one class.

[1:35:07] Passing these value objects around you

[1:35:09] know eliminates a huge amount of

[1:35:10] checking in your software. Um, you know,

[1:35:13] you've put all of that checking into

[1:35:14] small little classes that are very,

[1:35:16] very, very easy to test. Now, like we

[1:35:19] mentioned earlier, not doing things in

[1:35:20] DDD. Some things are CRUD. Even things

[1:35:22] that are CRUD, I still use value objects

[1:35:23] a lot because it makes that stuff a lot

[1:35:25] lot easier.

[1:35:27] So, like I mentioned, you know, DDD, we

[1:35:29] have these objects. Recipe name,

[1:35:30] temperature, date brood, those are all

[1:35:32] valid. We know they're valid. CRUD, you

[1:35:34] know, like I said, strings, floats, you

[1:35:35] don't know what they are. Functions,

[1:35:36] validations testability usability I

[1:35:39] think is, you know, a lot higher. You

[1:35:40] don't have to worry. the users don't

[1:35:41] have to worry about accidentally

[1:35:42] screwing formulas up, things like that.

[1:35:45] Um, another check there. And of course,

[1:35:47] you know, we all test our code. So, all

[1:35:49] the time.

[1:35:52] No. Uh, but if it's obvious that you're

[1:35:55] not going to have time to test

[1:35:56] everything. Um, but value objects, I

[1:35:58] would say absolutely test them and

[1:36:00] because those are the like I said, the

[1:36:01] very first thing that your your

[1:36:03] application you put as much logic as you

[1:36:05] can into them and focus on them. um

[1:36:08] because

[1:36:09] when you're building entities and these

[1:36:11] are the models I was talking about,

[1:36:12] you're going to rely heavily on those

[1:36:14] those value objects. So um those

[1:36:17] entities like I said they're

[1:36:18] identifiable, they have state, they're

[1:36:19] mutable. Um but they operate on the

[1:36:21] value objects. They use those value

[1:36:22] objects in order to store values and um

[1:36:25] you know change over time. Um ideally

[1:36:28] they're storage agnostic. Now that's not

[1:36:29] always possible uh depending on what you

[1:36:31] know frameworks you're using, stuff like

[1:36:33] that. Laravel. Um, sorry. You may not be

[1:36:37] able to do that quite as easily, but if

[1:36:38] you're using Doctrine and stuff like

[1:36:40] that, um, you know, it makes a little

[1:36:41] bit easier to just keep your stuff

[1:36:42] storage agnostic and then do mapping

[1:36:44] later. But, um, do as much as you can in

[1:36:47] the value objects. Put as little as

[1:36:48] possible in the entities. Your entity

[1:36:50] should just be storing values and

[1:36:51] holding state. Um, you know, use those

[1:36:54] doctrine mappings, doc annotations. Lar,

[1:36:56] if you're Laravel developers, I'm sure

[1:36:57] there's a few of you in the crowd.

[1:36:58] Nothing wrong with that. Um, you'll do

[1:37:00] this a little bit differently. I'm going

[1:37:01] to show examples in doctrine. Um, but

[1:37:04] Laravel, you probably will use your ORM

[1:37:06] objects to hold state. So, you're going

[1:37:08] to pass those to your entities and hold

[1:37:09] state. That way, your entities can kind

[1:37:12] of worry about business logic that's

[1:37:13] associated with it. So, you're still

[1:37:14] going to you're going to map in and out

[1:37:15] of value objects in order to do your

[1:37:17] mapping um through the OM

[1:37:20] behavior first, storage second. So, like

[1:37:23] I made you guys do the event storming,

[1:37:25] thought about modeling, we weren't

[1:37:26] worried about data and stuff like that.

[1:37:28] entities again I mentioned earlier

[1:37:30] single entity aggregates contain other

[1:37:32] entities just to kind of um you know

[1:37:35] keep those two in your head the code

[1:37:37] behind them is almost identical it's

[1:37:39] just that the aggregates store you know

[1:37:41] multiple entities and if you're doing

[1:37:43] transactional stuff um your transaction

[1:37:46] boundaries are going to be around the

[1:37:48] greater aggregates so when you save a

[1:37:50] recipe you want to save all the hops and

[1:37:53] grains associated with it all at the

[1:37:54] same time um if you have a recipe and a

[1:37:57] brew session together and you're

[1:37:59] operating those in the same controller

[1:38:00] because you've done too much in one

[1:38:01] place. That happens, you know, has to

[1:38:03] happen sometimes. Persist the recipe,

[1:38:05] then persist the brew session. You could

[1:38:07] do that as all one big transaction, but

[1:38:08] put each one in its own transaction as

[1:38:10] well. Uh if possible, it'll just make

[1:38:13] your life easier because you're already

[1:38:14] dealing with enough. Um like I

[1:38:16] mentioned, uh you just how you make an

[1:38:18] entity. It has an ID. Again, recommend

[1:38:21] using EU ids. has functions like change

[1:38:24] name, change email.

[1:38:27] Um, it's going to be mutations on that.

[1:38:29] So, we're going to try to avoid setters.

[1:38:31] Now, these are kind of like setters. Uh,

[1:38:33] but I'll kind of get into some more

[1:38:34] behavior that we're going to have. Um,

[1:38:37] if you look at the constructor of a

[1:38:39] brewer, you know, what is required for a

[1:38:41] brewer? You need a username, a full

[1:38:42] name, an email address, and a password

[1:38:44] maybe to store it login or something

[1:38:46] like that. You we don't have to validate

[1:38:48] any of this. This is basically our um,

[1:38:50] you know, our entity. We've we've

[1:38:51] validated it. There's nothing to do

[1:38:52] here. We know the full name is valid. We

[1:38:54] know the username is valid. Um, your

[1:38:56] entities become quite simple. They're

[1:38:58] just storage contain, you know, storage

[1:38:59] of stuff.

[1:39:01] And like I mentioned, centers are bad in

[1:39:03] entities. Um, we want to avoid uh what

[1:39:06] they call anemic modeling. Um, if you

[1:39:08] look at an ORM, like I've written one in

[1:39:10] the past, it's terrible, but um, Cropel

[1:39:13] is a good example because, um, more

[1:39:15] people know it. So you know you say new

[1:39:17] book and then you set title set price

[1:39:20] you know new author set set

[1:39:24] at no point you know do you know exactly

[1:39:26] when the book is in a valid state you

[1:39:28] know if you if you don't have you know

[1:39:30] is price required like you don't know

[1:39:32] like until you go to persist to the

[1:39:34] database you know is this book in a

[1:39:36] valid state your entities should always

[1:39:37] be in a valid state if possible now

[1:39:39] there's going to be some times where you

[1:39:40] can't do that necessarily and you need

[1:39:41] to try to contain that as much as

[1:39:43] possible but you know in the case of a

[1:39:45] book If it requires a title and a pi

[1:39:47] price, put those in the constructor of

[1:39:49] that object and have them be valid

[1:39:51] object value objects so you know that

[1:39:53] it's a valid title, a valid price. Um

[1:39:55] there's no reason to like have this be

[1:39:56] in limbo anywhere throughout your app.

⚡ Saved you 2h 16m reading this? Transcribe any YouTube video for free — no signup needed.