Coding Blocks - Software Architecture – Aggregate Roots, Factories, and Repositories

Episode Date: June 13, 2017

Stitcher is back and so are we as Michael proves he doesn't have a career as a rapper, Allen can't type on his phone, and Joe tweets with famous authors as we continue our dive into Domain Driven Desi...gn talking about aggregate roots, factories, and repositories.

Transcript
Discussion (0)
Starting point is 00:00:00 I think we need to do a wrap eventually. You are now about to witness the strength of street knowledge. Wow. Or not. That's the show. That's it. We're done. You're listening to Coding Blocks, episode 61.
Starting point is 00:00:19 Subscribe to us and listen to... No, we're not redoing it. Keep going. You're listening to Coding Blocks, episode 61. Subscribe to us and leave us a review on iTunes, Stitcher, and more using your favorite podcast app. Visit us at codingblocks.net where you can find show notes, examples, discussion, and more. Send your feedback, questions, and rants to comments at codingblocks.net. Follow us on Twitter at Coding Blocks or head to www.codingblocks.net
Starting point is 00:00:46 and find all our social links there at the top of the page. With that, I'm Alan Underwood. I'm Joe Zack. And I'm Mike Wellall. Yeah, that intro joke didn't really come out the way I wanted it to. I loved it. You should do like a booming bass voice and some distortion. Yeah, I don't have that.
Starting point is 00:01:05 No, no. Yeah. Logic has everything. So you're racing against the clock to wrap up three projects, prepping for a meeting later in the afternoon, all while trying to tackle a mountain of paperwork. Welcome to life as a freelancer. Challenging?
Starting point is 00:01:21 Yes. But our friends at FreshBooks believe the rewards are so worth it. The working world has changed. With the growth of the internet, there's never been more opportunities for the self-employed. To meet this need, FreshBooks is excited to announce the all-new version of their cloud accounting software. It's been redesigned from the ground up and custom built for exactly the way you work. Get ready for the simplest way to be more productive, organized, and most importantly, get paid quickly. The all-new FreshBooks is not only ridiculously easy to use,
Starting point is 00:01:53 it's also packed full of powerful features. Create and send professional-looking invoices in less than 30 seconds. Set up online payments with just a couple clicks and get paid up to four days faster. See when your client has seen your invoice and put an end to the guessing games. FreshBooks is offering a 30-day unrestricted free trial to our listeners. To claim it, just go to freshbooks.com slash coding and enter coding blocks in the how did you hear about us section.
Starting point is 00:02:26 All right, so let's kick off the show here. Let's start off with our usual podcast news. So the first up is our iTunes reviews. And in that we have Coulter Cotton, Conservative Programmer, RW Cheese, Sean H. Sean H. Wow, my eyes just went blurry Cece Kessler Marv the Robot And Alex 11132 And Citrus back up So we've got some extra reviews here this week
Starting point is 00:02:54 Big thanks to Rip Adam Whitehurst Alan is clearly the best Only Bavarian beer is beer Clegg89 Denifia God's Short Bus Dubstylee The Eye of Brows, and Edgar Da Bunny.
Starting point is 00:03:09 Dude, those are some stellar names. The Eye of Brows, God Shortbuss. Oh, boy. That's so wrong. You're not even going to mention Alan is clearly the best? Well, I mean, there's nothing wrong with that one, right? I mean, there's nothing funny about that. Ego much?
Starting point is 00:03:33 No, not at all. Hey, so guys, seriously, thank you for the reviews. By the way, Edgar the Bunny, I do want to call his out just a little bit because he hit on what has been most important to us when we started this podcast was making information that people can use, right? And you can go back and listen to again and again and continue to use and learn and just revisit. And that was awesome that somebody, you know, saw that that's what we're doing. And, and we really try hard for that. So thank you very much for pointing it out.
Starting point is 00:04:08 Thank you all of you for your reviews. I mean, very much enjoy them. So thanks. And for the full shows, make sure to go ahead to the website and visit cooking box.net slash episode 61. Yes. Oh,
Starting point is 00:04:22 so we're on Slack in our amazing Slack group. And hopefully you've noticed that our sound quality has improved drastically probably what in the past 10 episodes. I don't even know how long it's been now. But that is in no small part due to Aztag, who put together a template for us. He's an audio engineer and a software developer. And he put together a template for us, who he's an audio engineer and, and a software developer. And he put together this template. So things sound great. And he hit us up the other day and he was like, Hey, check out this, this app that I put in the iTunes store. I was like, Oh really? Cool. Awesome. So we're going to have a link in the show notes here, but really other than just giving him a shout out and having you guys spread the word, if you know any dentists that have tools, the air tools specifically that, you know, are expensive to maintain, or if you are a dentist and for some reason you're interested in software development, go check this out.
Starting point is 00:05:16 But here's the cool part. What I really liked about this is the whole purpose of the application is to find out when a tool might be failing or when it needs some maintenance because it's not operating at its best efficiency. And if you've ever been to a dentist's office and you hear that high pitch whining noise as they're getting ready to cram some sort of device in your mouth, that's what we're talking about. These things that have really fast moving parts. He approached this totally different than what a lot of people would. So basically he even says it in the description on the application that they listened to the harmonics, the sound of the instrument itself. Now it has to be an air driven tool,
Starting point is 00:05:55 but they inspect that to find out is this thing operating the way it should be. And if it's not, then there'll be a warning. And all you have to do is hold your iPhone up next to this thing, have it listening to it, and it'll tell you if it's in good operating standing. So the cool part is this thing's like 18 bucks, US dollars, I think $17.99. And what he said is the reason the whole idea came up is typically you have to have a really expensive like laser tool that will identify whether or not the thing's operating properly, and they're usually a couple thousand dollars or more. So this would allow doctors to use their iPhone that they already have,
Starting point is 00:06:34 pay $18, and potentially have something much cheaper and easier to use. Yeah, I don't want anything breaking in my mouth. Or as the patient, you could double- you know, double check the doctor before, hopefully before he starts putting those tools on your teeth. Oh, that's amazing. Yes. Everybody go buy this and just have this thing sitting next to your face as they're grabbing the device. I feel like it's important that we support our community. And since he's a part of the community, we should definitely buy this. And, you know, next time you go to the dentist, just, you know, check your dentist's equipment for him. Yep, definitely so uh huge kudos to him for putting it out there awesome and you know again
Starting point is 00:07:10 hopefully you guys will share that and go take a look at it so it's really cool approach for solving problems too like when you first mentioned i initially thought like maybe tracking the usage and then you know looking at some stats to figure out if it's time to maintain it but that's a total different way of solving a problem yeah and i was thinking iot right like putting some sort of sensors in the device so that it would know when parts were wearing or whatever but it just goes to show that people who work in different areas think about problems differently so it's just amazing to me i loved it yeah very cool uh one thing i want to mention on the last episode i actually tweeted eric ev, who wrote the book,
Starting point is 00:07:47 Domain Driven Design, and asked him about some open source examples of domain driven design that we can maybe take a look at. And he actually wrote back, and I thought it was really interesting to say that he said most open source projects are highly targeted towards kind of one domain. And so he didn't really have any great examples
Starting point is 00:08:04 for us to look at. And so I thought that was really interesting to look at or to think about. And so I guess this is, it ties more into what we've been talking about in the sense that you would use domain driven design more for like business or just kind of the normal, like absolutely right for work and not so much a one-off open source projects. But I just thought it was kind of interesting to draw a line of distinction there between the types
Starting point is 00:08:28 of things that are open source and the types of things that aren't. Also, let's keep in mind, you tweeted somebody and he replied back to you, right? This wasn't just, hey, some dude down the street. Yeah, we're living in the future. It's insane.
Starting point is 00:08:44 30 years ago, you couldn't pick up the phone like, hey, Stephen King, I had a question about it. Why do you not like clowns? That's right. Yeah. Now nobody likes clowns. Thanks, Stephen King. So next up, what I had.
Starting point is 00:09:02 Man, so this is somewhat random, somewhat related to what we do. We've talked about phones in the past and technology and how some of it's all the same or whatever. So I got a new Galaxy S8 Plus, basically because they were just doing a killer sale on it, and I was like, whatever, fine. Man, I loved it, and i straight up hated that phone for a month and i hated that phone because that keyboard that ships from samsung is the worst
Starting point is 00:09:35 piece of garbage i've ever used man like i seriously got so mad at it that I would stop replying to people because it like I would feel this this bile rising so I finally got mad enough to where I was like I can't take it anymore I have to change it so this should have been a tip but Gboard it's the Google keyboard that they've redone it is so good it you know how like Apple's keyboard is just really good in terms of mobile devices? Well, I was going to bring that up because that's one of the things that we talked about in the last episode related to the laptops was that was one of the things that they were touted as getting right on the iPhone so many years back was that they got the keyboard on the iPhone correct. That's what helped drive its success. It's really good. I mean,
Starting point is 00:10:25 the iPhone's good. And surprisingly, if none of you guys have ever messed with it, Windows phone keyboard, one of the best ever. It was, it was done incredibly well. So I'm actually excited to say that the G board keyboard that you can get download for free or whatever works extremely well. I don't want to break my phone in half anymore. So anybody out there that picked up a Samsung Galaxy S8 or S8 Plus or any of those, man, disable that Samsung keyboard and go download the Gboard.
Starting point is 00:10:56 It's also available for iPhone. Oh, is it really? Mm-hmm. Excellent. It's kind of cool too. I don't know that I love this or i hate it but when you're typing it will also somewhat inspect what you're reading and maybe give you relevant google articles that you could literally just paste into or click and say hey make this part of my message at least
Starting point is 00:11:16 on iphone i know that one of the things that they uh like how does like one of the features is being able to do a google search inside of the keyboard with whatever app you're in yes it's it's pretty cool stuff i haven't messed with that feature as much i was just so happy that the spacebar worked well it was it was aggravating so anyways yeah i know like even on i remember like uh on the nexus i wasn't a fan of that built-in or that that stock keyboard yeah either it wasn't great and that was also a google keyboard but it was better than this and like seriously the samsung one i don't know how anybody uses it i really don't but anyways so that was interesting so i want to touch briefly on the laptop before you go there yeah yeah sorry just want to hop in there real quick and let you
Starting point is 00:12:01 guys know you know we we talked about tweeting we're talking about cell phones. So I went ahead and tweeted Stephen King and gave him the next idea for his next book or movie, a cursed cell phone that subtly manipulates the text messages by making the user angry. Did you really text him or tweet him? I DMed him and I asked for a commission. So what's the standard cut? He hasn't replied yet. Yeah, maybe he'll give you a byline
Starting point is 00:12:28 in the credits i'm also not sure this is actually stephen king or you know some other the the tweet name or handler is the stephen king yeah all right cool so the laptop update i want to do it briefly here just because maybe some of you aren't going to, you know, this is where you're going to get the information. So as mentioned previously, I picked up the HP Spectre X360, the 15 inch with 512 gig drive, 16 gigs of Ram and the dual core i7. And then I also picked up the Lenovo Yoga 720, also 15-inch, both 2-in-1 convertibles, 512 gigs of SSD, 16 gigs of RAM. And this one actually had a quad-core CPU, and it had the NVIDIA GTX 1050, whereas the Spectre had the 940MX.
Starting point is 00:13:22 So I spent a couple weeks with both of these these things and honestly, they're both good. Like, like seriously, they're both good. And wait, do we, do we want to say how he's right? Yeah, you were right. You were straight up, right? Like, so at the end of, at the end of all this, what it boils down to is first off in the back of your mind, like when you know something slightly wrong, you can't help it, right? Like it's, it's going to chew away at you. So the specter having the lower end graphics card and having the dual core processor instead of the quad core plus the higher end card, like it, it seriously, it mattered. I mean, it mattered a lot to me. And the interesting part is here's what I'll tell you though. If that's the thing, man, like seriously, the specter, if, if you're going to be doing just standard development work, like if you do visual studio stuff and, or any other ID, you pick your
Starting point is 00:14:17 choice and, and your use case is browsing the web, checking your email, listening to music, all that perfect device for all of it. It'll get it all done. If you want to tinker with machine learning or you want to play video games on your device or any of that kind of stuff, like it just makes way more sense to jump up to the, to the yoga seven 20. It had the quad core I seven, it had the Nvidia GTX graphics, and I'm going to be putting these videos together but you're saying jump though i mean it wasn't like a huge price difference it was cheaper the lenovo yoga was cheaper okay i thought that was the one that was more expensive
Starting point is 00:14:56 no it was cheaper and that's the thing if you want oh but it didn't it was cheaper but it didn't come with the pencil or the it didn't come with whatever they called the pen it didn't come with the pencil or the, it didn't come with the pen. It didn't come with a pen. So I'm trying to remember. I think the, the HP Spectre was 1399. The Lenovo yoga was 1350 maybe, or it might've been 1299. I don't remember exactly, but the pen was $27.
Starting point is 00:15:20 I bought the pen on Amazon. Here's, here's, I will say this for the creative person, for an artist, for somebody who wants to use this to draw and stuff, the Lenovo destroyed the HP. Like, you could take the pen on the HP and drag it across the screen, and it might not even register it. Right? Yeah. And so you'd have to put a little bit of pressure on it.
Starting point is 00:15:43 And if you've ever used these digital pens, as you put pressure, like the, the ink will get thicker or whatever. And so it was really hard to do like hairline, you know, lines on the page. You take the yoga pin that was on it, you drag it across it. You have just a hair thin line. Okay. Now let me ask you this, because one thing that you've heard a lot about recently is the iPad Pro with the pencil, ever since they introduced that last year, right? And that's supposed to be an amazing paper-like thing. How did that compare? Because I know you have the iPad Pro with the pencil.
Starting point is 00:16:17 I do. So if you are the creative person, so the thing that's super cool about the pencil that I made fun of before I actually used it. The name? Yeah, the name, before I actually used it. The name? Yeah, the name. Because I'm like, what? Really? Well, everyone else calls it a pen. Right.
Starting point is 00:16:31 So here's what I'll say. When you're using the iPad Pro, it's super slick. So you don't have that feeling like there's friction. Like if you're writing on a piece of paper type thing, right? So there's that. But you can lean that thing and you can shade things. Like if you were truly doing it on a piece of paper type thing right so there's that but you can like lean that thing and you can shade things like if you were truly doing it on a piece of paper so in that regard like a pencil right hence the name so if you are the true artist and that's your goal like the ipad pro is really
Starting point is 00:16:58 good like super good if you're trying to use something that's going to be your all-in-one device you want to do development on it and you want to do artistic things like the yoga was excellent like the the feel of it it had a little bit more friction to it so it felt a little bit better it tracked better that kind of stuff was good so so that aside the artistic thing aside gaming on it dude i i loaded up arc you can play Arc on the 720. That's impressive. Huh? That's impressive. That game is a beast.
Starting point is 00:17:28 Dude, so check it out. You can even play on high settings on that 720. You put it on high settings. You drop the resolution down to 1080. Nobody's gaming on 4K on a convertible. Okay, but can you get a decent game of Who's Your Daddy going on it? I don't know that game. What?
Starting point is 00:17:50 You've never played Who's Your Daddy? It's way down in Florida yet. Oh my God, you've got to check this game out. I'll leave it to you to go find. But basically, it's a two-player game. One person is the father and one person is the baby. You're basically... Okay, fine fine you're making it weird so let me let me finish this explanation then
Starting point is 00:18:11 one person is playing as the baby and is trying to die and the and whoever's playing as the father is trying to keep the baby alive so it's like like real life. Yes, pretty much. Okay, got it. The screenshots are amazing, by the way. Who's your daddy? Yeah. Very cool. So I will just throw out a few things. Like one of the interesting things is 1080p high settings on Arc on the 720,
Starting point is 00:18:38 30 frames a second. And if you tweak some of the other settings, you can get it up close to 40 frames a second. Totally playable, right? On the Spectre... Some gamers might have just choked when you said that, but yeah, go ahead. I mean, 60 is what you want for playing, right? But no, it was smooth.
Starting point is 00:18:56 It wasn't jittery or jerky or anything. I'm sure if you had 20 dinosaurs on the screen, it was going to slow down. But I mean, I'm talking about, like I wasn't just standing out by some rocks. I was standing in a bunch of trees and jumping in the water and that kind of stuff on the specter nine nine frames a second nine and that's on high if you wanted it to be playable on that one you'd basically have to turn it down to low settings drop the resolution i mean it is what it is.
Starting point is 00:19:25 Like, it's not a gaming video card. It's one that would increase your ability to do some things, but it would help you out in Photoshop. It would help you out in those things. So all that said, keyboards, both of them amazing. The HP was a little bit better than the Yoga, but neither one of them would you complain about. They both felt great.
Starting point is 00:19:43 I mean – Which one are you going with? So the yoga is basically, so here's the thing, and I feel kind of like a jerk. I didn't keep either one of them. Oh, my gosh. So I'm not right. So here's the reason why, and it had nothing to do with the fact that I didn't want either one of them. I actually want the yoga. The problem is on their site,
Starting point is 00:20:06 they have a one terabyte version of that same SSD for like a hundred bucks more. And so it's like, you can't go buy a one terabyte SSD for a hundred dollars more. Right. So that's the only reason I took it back. And these were M.2, right?
Starting point is 00:20:20 These were M.2. Yeah. These are fast. You definitely can't go buy one of those for a hundred dollars. No, man, you're going to spend 400 bucks on that thing. You know, bare minimum. So at any rate, that's the only reason I actually have been looking at it because it was out of stock the other day. But that, I think that's actually what I'm going to do is I'm going to go pick that because I wanted the two in one. And I did find that even that 15 inch size wasn't too big. If
Starting point is 00:20:43 you're kicking back in a chair and you wanted to read or something, size wasn't too big if you're kicking back in a chair and you wanted to read or something it wasn't too big so uh that's like best buys worst nightmare by the way like someone comes and buys two really expensive laptops yay uh they return both and buy them online from amazon man and dude honestly if they had had the one at best buy they straight up do not sell the one terabyte version. It's not online. You can't get it in the store. And I was like, well, doggone it. You know, so I do feel better selection and cheaper prices
Starting point is 00:21:12 on the internet. Actually, it's pretty tough to compete with. But this is from Lenovo site. This isn't even from Amazon. This is literally you have to go to Lenovo to get this particular model. Well, your comment on the $400 for the one terabyte, I may be kind of curious because I have been recently buying some equipment here and I was
Starting point is 00:21:29 like, well, no, no, no, no. It's a little bit more than that, right? Is it really? So if you wanted the Samsung 960, which is the latest iteration of their NVMe SSDd not the pro version okay right the one terabyte that one's 480 so you're talking about closer to 500 if you wanted the pro version you're jumping up even higher and that's basically what comes in both of these so yeah all right so you're gonna have a full video though right yeah i'm gonna have i'm i'm going to have two separate reviews on the two machines, and then I'm going to have one comparison of the two. So that's the plan. I'm going to be working on those this weekend.
Starting point is 00:22:12 So, yep, quick update on that one. And so now it's time to start getting into some things. So I said before the show, I feel silly. Every time I hear the word invariant, I'm like, man, I need to go Google that because I can't remember what it means, right? feel silly every time i hear the word invariant i'm like man i need to go google that because i can't remember what it means right and i didn't feel too bad because both of you were like hold on let me google that so how you spell that right so i thought it was worth at least bringing it up because it is a programming and mathematical term and it has some relevance to today's show. So I guess let's sort of break it down
Starting point is 00:22:48 to the various different things we found. So an invariant, when you're talking about it, will always be true at the beginning and the end of an iteration. And Joe, you found something on this. Yeah, we should probably say that it should be true at the beginning and the end of an iteration. And one example that we saw online on Stack Overflow, and we probably say that it should be true at the beginning and the end of an iteration. And one example that we saw online on Stack Overflow, and we'll have a link in the show notes, is that a binary tree, and that's one where the children to the left are
Starting point is 00:23:15 always less and the children to the right are always to the right. The greater children are always to the right. The parent node will always have more children than any child node. And that's just something that kind of makes sense intuitively. But you can use like a checksum to make sure that there's not some sort of other problem. Another example would be like if you have an order with order items, like, you know, Amazon cart, something like that, then the line item totals should add up to the order total. So those can be examples of invariance. And invariance can also be things like constants, which are defined at compile time. But they can also be these kind of wishy-washy things.
Starting point is 00:23:53 And they can represent variables and represent concepts. And you can use them to kind of check things. But I just thought that was kind of an interesting distinction between constants and invariance. And you found something else that I thought was a good summation of it with the assertion, right? Oh, did I? Yeah, but I don't remember what it was now.
Starting point is 00:24:17 It was just saying that, how did I find it? It's kind of like the checksum thing, right? Where you add up the items and the order items, it should equal to the order total, right? So you can use's kind of like the check something, right? Where you add up the items and the order items that should equal to the order total, right? So you can use it kind of like a check sum or you can basically assert that these things are equal. Yes. And they should be in if there's not,
Starting point is 00:24:32 that there's a problem and you should probably bail out because you're in an inconsistent state. It kind of went to the whole notion of like unit testing. You're asserting that something is true and they should always sort of stay in that state, at least in terms of what you expect them to be in. So Eric Evans in his book on domain driven design, he actually had a really nice summation of how they use it in the domain driven design paradigm. So in chapter six, page 128,
Starting point is 00:25:00 in the first paragraph, invariance are consistency rules that must be maintained whenever data changes. So going back to your order total thing, right? Your order line items must add up to the order total. If not, it's not in a consistent state. And then that's a problem. That's an error. So I thought that summed it up pretty well. And you have something else here oh yeah just to like wrap up our news section here so did you see the new samsung chg90 so if you thought that your widescreen monitor was nice they just proved you wrong with the 49-inch curved super ultra-wide gaming monitor. Yes, sir. I think you could see, like, if they show a picture of it,
Starting point is 00:25:53 there's one picture that I see from Business Insider where they have Excel opened up. Because if you're really going to show off the amazingness of a monitor, Excel is your go-to program and i think you could see every column that excel will allow you to have i've seen some sheets that's true what was that you've seen i've seen some sheets hey do you know how much is going for i do not it's on amazon is it already well it's not being sold it says it's going to be released on June 30th. It's $14.99, so it's not insanely ridiculous.
Starting point is 00:26:30 Well, here's the thing that I also kind of I found humorous about this is that like, you know, we've talked about having an ultra-wide monitor already, right? And those are typically a 21.9 aspect ratio. This thing is 32 to 9.
Starting point is 00:26:46 That's ridiculous, man. But it was also kind of humorous too because it was like, oh, it's an ultra wide. We have ultra wides and now this is super ultra wide. And it's like, hey, when are we going to just
Starting point is 00:26:58 adopt some other way of describing this stuff where it's like, I felt like this was going the same path as like standard definition high definition ultra high definition super ultra high definition yeah yeah you said something just a second ago joe you kind of broke out what'd you say double wide hey yeah my wide screen is 16 by 9 so man yeah i mean once you go to the ultra wide it's hard to get away from it is really
Starting point is 00:27:25 cool though because even looking at some of the specs on this thing this is using the same like super high-end technology that they use on their nicer tvs so like this isn't just a a gaming monitor like this thing's it's loaded to the hilt with features yeah the the verge calls it half a tv oh that's amazing man all right it's okay i love it all right so what's what are we on next is it the actual show sure here we go yes so let's move into what we're talking about today with domain driven design and we got three things and we're doing this a little bit differently we each research one of these topics so that two of us will be ignorant and one of us will know what we're talking about at any given time is that a guarantee not a guarantee probably all three of us won't
Starting point is 00:28:14 know what we're talking about at any given time but we'll try our best so and there is a theme between these three topics we're basically focusing on the life cycle of complex objects and relationships in domain-driven design. Yep. So where we're going to start is with aggregates and aggregate roots. Because really when you start talking about domain-driven design, this is where the important stuff really starts coming together when you're defining your models and how these things work. So a few definitions. The aggregate root is the entry point of an aggregate where the work should be done, and this ensures the integrity of the object graph. An aggregate is a cluster of associated objects that we treat as a unit for the
Starting point is 00:28:57 purpose of data changes. This is basically the graph of the objects there. And we'll help clear that up here in just a minute so we say i'll sentence one one second one more time say which one the last one yeah a cluster of associated objects that we treat as a unit for the purpose of data changes yep yep so would that be like something like an order that kind of wraps or is made up of order items? Very similar to that. So really, the problem is your aggregate route. And I don't want to get in too much of an example just yet without describing some things.
Starting point is 00:29:32 But yeah, your order might be your aggregate route itself. And an order item in there might be another aggregate. Because this could contain things like prices and quantities and some other things, right? So it's definitely interesting. So let's dive in here a little bit. So objects within an aggregate boundary can reference each other, but not outside the boundary, unless it's to another aggregate root. So in the book, he talks about a car and, and this kind of sums it up. It should be pretty easy for people to visualize. So you have a car and on your car, you have, you have tires and you have wheels and, and you might even have an engine, right? Might you hope you do. So there, there are
Starting point is 00:30:22 different aggregates that can exist there. An engine could be an aggregate itself because there's parts and stuff that belong on an engine. The car itself is also an aggregate because it contains a lot of things that can be operated on there. But then you have to decide what is my route? What can operate on these things? Tires themselves don't really matter outside of knowing that it's a car. Like if, if you say that there's a tire, it has no relevance outside of the fact that it's on your car or my car. So that's not an aggregate. That is something that belongs in the boundary of the car. So when you look at the entire boundary of the car, it's your aggregate at the entire boundary of the car,
Starting point is 00:31:09 it's your aggregate route. You're going to have tires inside that boundary. You're going to have wheels inside that boundary. And you might even have the position of the car inside that boundary. Those tires and wheels cannot reference anything outside the boundary of car itself, right? Car knows about them and can reach down there and do anything it needs to with those, like the wear on the tires or anything like that. It can know about all that, but the tires cannot do anything outside of that car, right? So you would say the tire didn't run over a nail, the car ran over a nail and the car is responsible for routing that where it needs to go. Correct. And if that tire popped because of that nail, then the car is responsible for knowing about how to push that down, right? Because it's what has to make sure everything stays in a
Starting point is 00:31:56 consistent state. So that's one of the most important things about the aggregate route itself is it is, when we talked about the invariance a minute ago it is what enforces those invariance i feel like it's a weird way though to explain that though because as you were describing some of that i'm thinking like well in an event world right as the tire ran over the nail the car doesn't know then that it ran over the nail the tire knows doesn't know that it ran over the nail, the tire knows. So the tire would like bubble up the event. Hey, this just happened. So you could totally do that. And the aggregate could be the thing that's aware of it. But basically that event could not. So if
Starting point is 00:32:36 you wanted to go that route, that event could not route outside the car, right? It has to stop at the car. Nothing else can reach in and know about the tire on that car. It has to go through the car to get there is basically what it boils down to because what they don't want, the whole purpose of the aggregate route is to maintain the state of whatever's inside it, right? And as soon as you start letting other things outside of that aggregate route reach in and see stuff inside it, you can no longer maintain that state properly. You want as little touching that stuff as possible. Everything should go through that car. So I had a different takeaway from what you're describing then is like the you know how to consider like if this is a candidate for being
Starting point is 00:33:27 an aggregate root or not in your car versus tire example and it really kind of made me think it more closely kind of goes back to the order and line item example but as i when i heard it it made me think of like cascading deletes but it it was like, if you, when you delete the root, does it need to delete the associated things with it? Yes. Right. And that's what, that's part of it too. That's actually one of the rules. So if you delete something, it has to occur at the aggregate. It's what has to trigger it. And then it is responsible for making sure that everything that should have chained down that cascade delete has to happen at one time so it is responsible for that like one example i was kind of thinking of is like if you are you've got a shopping cart system
Starting point is 00:34:16 order order items like we're talking about right and now you've got the requirement to build a coupon system with a 10 off coupon one way to build that would be to build like a separate coupon system and take in the order items and just go ahead and lop off 10% off each one and kind of set the total. And what we're saying here is that would be a bad way of doing things because it should interact with those items via the actual order. And it should maybe tell the order that the price needs to change. Yep, totally. And if you think about that, if you take it a little bit further, like when you think about breaking the coupon out into its own thing, that's kind of how we would do things in the old way. You'd think about, oh, there's this coupon object that operates on items, right? And the problem is that could get more complex as time goes on. And now you end up with some spaghetti code.
Starting point is 00:35:05 If you place that thing within the boundaries of what that aggregate root is, the order, you know exactly how that thing needs to operate within that order on those order items. So you are localizing any kind of state changes and you can be fully aware and control and verify those state changes. Okay. I like that. So here's another thing going to this whole aggregate route thing. And this one is kind of key. When you think about aggregate routes, they are what have external IDs. So if you're thinking about something that's stored in a database or anything like that, the car has a VIN. It is globally identifiable. The things inside it, probably not. So for instance, a tire, that's not, it's just a tire, right? You bought four of them. They're all
Starting point is 00:35:56 probably the same unless you've got a car with a different rear end and front, but it's just tires. You have four of them on there. Now let's just talk about from the perspective of if you are a car salesman, right? If you're at a car dealership, the car is important to you. The tires are not. If you're a Toyo or you're somebody else like that, you might have a different domain, right? Because there probably is an identifying number on that tire. But for the purposes of the domain that we're talking about, that tire has no ID that you're going to get to right now, it'll have properties. It'll have an ID within its boundary that says, this is the front left tire. This is the front right tire, whatever, but it's not going
Starting point is 00:36:35 to be something that you can access from outside it with some sort of identifier. You're going to have to go through the car and say, give me your front right tire, right? Something like that. So that's one thing. He did point out the engines could have been a separate aggregate as well because they also have unique identifiers. Like there's typically some sort of serial number on an engine, that kind of thing. So that could have happened. But for the purpose of this, we'll leave that one alone. But it's, I think, important to say that aggregates can contain other aggregates, right? No, no, no, no. I'm sorry. An aggregate root can contain other aggregates.
Starting point is 00:37:14 Okay. The root can. The root can. So the root is really the only thing you can ever interface with and, and, and act on, but with some exceptions. So you're saying like an aggregate root can't contain another aggregate root. Right, right. An aggregate root is your top level thing because that's what's maintaining the consistency for everything within its bounds.
Starting point is 00:37:33 And so it would be kind of weird to have one surrounding another boundary and it would get kind of nasty, right? And now you're back into that whole complexity thing that the whole reason for domain-driven design is simplifying your use cases really is what it boils down to. Do you ever feel like domain driven design is really just kind of how to object oriented program? You know what?
Starting point is 00:37:55 For complex needs, I think so. I think that's why I'm really enjoying this is because it's a different way of thinking about the problems that we've been solving for years because a lot of times you'll say these are my database objects these are my classes right and then all of a sudden you get into these situations where like oh man this is getting really hard to manage when you break it down like this you write more code but it's way easier to reason about. So I think so. I think it's almost like a good path to follow for trying to simplify managing complex business needs.
Starting point is 00:38:37 I mean, it kind of means too, it's like if you have a hard time talking about your code, then maybe you've got some design issues there. It seems like it's really tightly coupled that's about it's um highly related to the uh the the language that we've talked about that ubiquitous language between uh the domain so talking about the problem that you're trying to solve and your code and trying to keep those as closely aligned as possible yep these are some really good guidelines for helping you do that. Yeah. I mean,
Starting point is 00:39:07 I think as we've gone further along, it starts to come together. I mean, this is a big topic, right? Like there's, there's nothing small about this, but it really does all start to click and you start looking at it. You go, man, that makes sense. Why, why have I never thought about it that way before some of the terminology, like the aggregate roots and all that, you're like, eh. That's the part that gets me. The terminology is so, like you don't talk about aggregate roots in your daily life as a developer. Right. No one's going to ask you, hey, I need to talk to you about these requirements, but what ubiquitous language are you going to use? Right. So that we like, so yeah, definitely the terminology getting on board with it is,
Starting point is 00:39:46 I think one of the hurdles to, to this book. I totally agree. That's one of the parts that when you're reading, you're like, man, it's almost like when you read a novel and they introduce 50 characters at the beginning, you're like, man, it's going to take me forever to keep up with this stuff. Right. And that's sort of what this feels like. But as you get into it, it really starts clicking. So to hit on the entities inside the boundary, again, they say they only have local identities, even if they might have something that exists in the database in terms of your domain, they only exist inside that thing. Nobody else is going to reach in and grab them. Go ahead. Well, I was just thinking, going back to our order example, like you as the customer might know your order number,
Starting point is 00:40:29 but you don't know or care the ID, the primary key of that line item on that order. Correct. That's not exposed to you in any way. Right. And before anyone starts talking about the SKU, that would be part of the description of the line item, not the primary key. Exactly. So now here's where things are a little bit weird. So you can transitively access some of the inner properties. So I mentioned like the car tire,
Starting point is 00:40:59 right? If something else needed to find out what the wear on that thing was, you could ask the car, what's the status of your front right tire, right? And so it could, it could transitively give you access to that for a moment, but you're not supposed to hang on to that reference. Like it's literally just, Hey, go get some information about it and then you're done. So that's how it's supposed to work. Any questions? I guess that kind of makes sense. Well, no, I mean, I'm thinking that that's really how it works too. When you take your car into the shop, right? They, you know, they just plug into the ECU. It gives it some information. Like this is the status of whatever that check engine light is, or depending on, you know, some cars you can just take the key in.
Starting point is 00:41:39 Right. And the key will, you know, have, have the information about like, oh, you're due for an oil change. Yep yep so that's interesting and it makes sense right like this is all about encapsulation right like this is another form of encapsulation is what we're talking about because as developers we know about variable encapsulation and the privates and the publics and all that kind of stuff this is business logic encapsulation is basically what this boils down to. Yeah. I was thinking about, um, we talked before about, um, the rule and independent about, uh, mutually dependent namespaces and why that is even a thing. And,
Starting point is 00:42:11 and really what it's telling you is that you've got some, you know, some concepts that are overlapping and it kind of sounds like it's, that's one way of kind of detecting or talking about, um, overlapping aggregate routes. Yeah, totally. And it'd be awesome if we if we actually were to put together an application, I bet and depend would show up beautifully, right? Like you'd have all these nice clean separations on everything. This is another interesting byproduct, which I believe you're going to get into here in a little bit is only the aggregate
Starting point is 00:42:41 routes can be obtained directly with database queries. So I'm not 100% sure how this flows through yet because I haven't read you guys' stuff on this yet. But my guess is because it is what's responsible for maintaining the state, this is where it all flows through as well for filling it, updating, all that kind of stuff. So all the operations should happen at the aggregate route. I'm just imagining scary N plus one problems that we like, you know, say your UPS and you're like, how am I tires doing? Like, okay, well, first, let's go get all the trucks. And then
Starting point is 00:43:14 let's go through each truck and get all the tires, you know, it just seems like that's kind of an inefficient way to query. But I could, I could see how in a domain that makes sense. It's just from a performance standpoint, like anything like that always scares me. But you know what though, to that point, probably what you'd have though is if you're talking about your trucks, then let's say that you had some sort of domain for your trucks. Let's say that the tires were an issue, like some sort of problem that needed to be solved. you might come up with your own domain for the tire maintenance, right? Like if all of a sudden that did become your
Starting point is 00:43:51 bottleneck, then maybe it became important enough to where you would create another domain for that. So I guess that's what I'm saying is like, it's just like any software, it would evolve over time and you'd have to address those needs. So, you know, maybe you create something that goes directly to the tires instead of having to spin up all these objects for that use case. Yeah, it's reporting services. Yes, there we go. So here's another thing. Objects within an aggregate may contain references to aggregate roots outside of it. So that tire inside this thing could reference, you know, the manufacturing plant.
Starting point is 00:44:32 If that was some sort of aggregate route out there, they can reference another aggregate route. So the top level things, uh, you said this earlier, when you delete something, it is responsible for making sure that the delete happens and it happens all at once. I'm still trying to keep my, still trying to keep wrapped around the idea of the difference
Starting point is 00:44:53 between the aggregate and the aggregate root. So I was thinking like, well, I know that you said that maybe engine is a special case, but let's pretend that it didn't have any kind of ID on it. And so an engine could be an aggregate. Yes. But the car is the aggregate an engine could be an aggregate. Yes. But the car is the aggregate root for it. Yes. Right?
Starting point is 00:45:10 And meaning that, because you said that the, you referred to the aggregate as a cluster of associated objects, and that's why I call it the engine, because we can all think of that as having a bunch of parts, unlike a tire, right? So there's a lot of parts associated to the engine. And that's just one of the pieces of the entire car. Yep.
Starting point is 00:45:31 And the engine would have things like needs oil change, right? Or whatever the case may be. So yes, it can totally be inside the aggregate route. And one of the things that I did find interesting and a little bit confusing when I was first going through this is they somewhat use the term entity versus aggregate in some situations. And I think an entity is just a thing, right? It could be an object. I don't think it's a property. I think something like a property is not known as an entity. So an entity would have its own set of properties. So an engine might be an entity, which would be its own aggregate possibly. I may have misread that or didn't understand it completely, but they, it seemed like they
Starting point is 00:46:13 interchange those terms a lot. Hmm. So this is one thing that is super important when the data inside the aggregate boundary changes. So anything within that car changes, the invariance on the aggregate must be satisfied. And it is the job of the aggregate route to do so. So this was this was one of the things that was really kind of interesting is define all your aggregates at once, right? Figure out exactly what your aggregates are, what things kind of, you know, compile
Starting point is 00:46:45 functionality or properties. And then once you've done all that, figure out which one is the root that should sort of encircle them and put a boundary around the other ones. And that's kind of what you do in a lot of situations. So if you have the orders, you have order items, you might have, I don't know, fulfillment or something like that. You'd look at all those and say, okay, well, the order is the largest, you know, that, that makes the most sense to be up here at the root. And that's, that's sort of how you end up doing it. And then I do want to point out, so we were talking about orders. One of the things that I thought was interesting is he went into something that was real life and really present
Starting point is 00:47:26 several problems. And it's the purchase order problem. So on a purchase order, you have the amount that you're allowed the limit for your purchase order. So it could be $1,000. On that purchase order, you're going to have somebody adding to the purchase order or modifying the purchase order. And on the purchase order itself, there's going to be items that have some sort of cost associated with them, right? And so one of the things that he pointed out was this is a fairly complex business situation. So let's say that me and outlaw are working on the same purchase order at the same time. And that thing has a maximum limit of $1,000. Well, if I add five items that are 100 bucks each and you add four items that are $500
Starting point is 00:48:09 or that are $200 each and we both do it and there's no sort of locking on that particular purchase order, we could get into a state where we've gone over the $1,000 price mark, right? And so now that's an issue. Well, how do you solve that? Do you lock the purchase order? So if I'm touching it, you can't touch it. Do you lock the
Starting point is 00:48:30 items so that they can't be added to a purchase order until somebody else is finished with them? Like it really opens up a whole world of problems. And then what if somebody changes the price on a product while you're working on a purchase order, right? But I don't understand how this goes back to the aggregates and aggregate roots problem. I mean, this seems like purchase orders sounds like a special type of domain that you're already in, right? So I'm losing the analogy a little bit.
Starting point is 00:48:55 So he took it from the perspective of if you just had an application that had no domain, right? You just did it like everybody always does it. You pull a PO out of the database and you start working on it. Somebody else pulls it. You started with the database first and you created some object to represent that row in the database. Exactly. So now you have two people working on this thing. Somebody saves it, updates it, and now there's $500 in there. Somebody else saves it right after or right around the same time. And now it's gone up over a thousand dollars. Unless you introduce... Or they overwrote the previous cash changes. Or they overwrote the
Starting point is 00:49:24 previous, but you know, chances are they just updated someote the previous question or they overwrote the previous, but you know, chances are they just updated some line item, right? They, they up the number in there. So it was this whole concurrency and this whole locking state type thing. And, and so this is where the domain comes in is, Hey, let's talk about it from the business perspective. So he came up with, with a few rules., parts are used in many POs. There's high contention for parts, right? There's a lot of people that are accessing parts. There are fewer changes to parts than there are to POs.
Starting point is 00:49:55 So you're not going to be changing the price of the part all that much, but you could be modifying POs a lot. Changes to part prices do not necessarily update the PO because it only matters at a certain state in the PO, right? Like if you're in draft mode, it probably doesn't matter, whatever, right? Until this thing starts to go live. So these were the three business rules that came up. And so now what you can do, if you're doing this in a domain driven world, you can say, okay, these are the business rules I know about. Okay. So now the PO is going to be my aggregate route because it has a limit that I need. It's my invariant, right? Whatever that
Starting point is 00:50:30 limit is, you can't go over it. And within there, now I'm going to have P I'm going to have line items within that PO that people are working on. And so those things have to be in a consistent state. So if somebody accesses this one PO and they want to make changes that has to be done atomically before somebody else can access it and do that, do any modifications to it. So the PO becomes your aggregate route. It is what is responsible for the invariant state of the object itself. And so now you're in, you're in a pretty good situation, right? You've now locked down the control that way. So it's not just people willy nilly accessing things and updating things.
Starting point is 00:51:10 It's all got to flow through that particular piece of domain logic. Yeah. I was kind of thinking that it would be, um, up to the, the domain objects responsibility to know that like, you know, part of his part of its business rule is to know whether or not something needs to know that like, you know, part of his, part of its business rule is to know whether or not something needs to be, uh, lock, you know, to disable concurrency. Right. Yep. So I was going, I was kind of thinking back, like, as you were describing, going back to the car example, right? Like you can't have two people fill up the tank at the same time. So there's got to be a lock done to let one person fill up the tank. And then the next person can go back behind it and say like, Oh, it's already been done or it still needs to be done and the cool part is
Starting point is 00:51:49 because you know about the need for that you can handle it at the aggregate root level whereas if you just had a bunch of objects in your system right now you're gonna have to say oh do we lock the parts so we lock this and now you're gonna end up with deadlocks because you have all these things trying to lock things and if you haven't ever had to deal with locks, you know, fortunate for you. But if you do, you can easily get into a state where you lock this, something else is dependent on that. And then you end up locking that. And so now you get into the state where, where things can never, you know, recover. So doing it this way and going down, making the PO your aggregate route, it handles all that for you.
Starting point is 00:52:26 It knows that, hey, somebody's working on this one. I need to make sure that these things are consistent. So, yeah, I mean, that's pretty much what I've got for the aggregate routes. And, I mean, hopefully that made a little bit of sense. Yeah, it sounds really good. It really dovetails into stuff that I was reading too, which is coming up here in a sec. Do you hate being distracted by production support issues
Starting point is 00:52:51 when you should be working on new features? Well, if you do, you should take a look at airbrake.io. It's a service for alerting and monitoring so you can spend less time debugging and more time writing great code. That's right. And airbrakesupports.net, JavaScript, Node.js, Java, Go, just about any programming language or platform you can think of.
Starting point is 00:53:13 And you can see all of them on their GitHub page. And there's also a free trial, which thanks to your feedback, no longer requires credit card numbers. So you can check it out risk free at http colon slash slash get airbrake.com slash CB. Again, that was get airbrake.com slash CB. All right, now we're back talking about factories. So when you're creating these complex objects or aggregates, things can get really sticky because a lot of time there's these complicated rules. There's these invariants that we're talking about. And so it's, we have to maintain these invariants, not only when we're changing data, but also when we're creating it the first time, which if you're familiar with the
Starting point is 00:53:54 design patterns that we've covered before, then it's a good use of factory. And I found a quote here that I actually thought was really funny because this is something that we kind of joke about a lot, but the whole quote's a little long, but I'll go ahead and blast through it. Much of the power of objects rests in the intricate configuration of the internals and their associations. An object should be distilled until nothing remains that does not relate to its meaning or support its role in interactions. This midlife cycle responsibility is plenty this kind of ties back to something that we talk a lot about especially our buddy john where um objects when you you tend to do them the right way they end up not really doing a lot and so you end up
Starting point is 00:54:34 with a lot of interfaces a lot of dumb objects and a whole lot of code that doesn't really do anything and you end up kind of zipping through in the debugger and trying to figure out where the actual behavior lies and a lot of times it's kind of spread out so i thought it was kind of funny that like something that we complain about is uh in a way kind of the goal here meaning that we're complaining about it being solid right and so and that's kind of a something that we talk about. Sometimes it's like, you know, solid is great and it's maintainable and it's easy to understand. But it also makes for a lot of disparate and just a lot of code in general. You know, you get kind of a class explosion when you do things this way. And so I just thought it was kind of an interesting point to bring up. But you know what? In that same statement, what I was trying to wrap my head around and I think yeah that it should be boiled down to you know or distilled down how did it say it yeah the intricate configuration of their
Starting point is 00:55:32 internals so basically oh yeah it does not relate to its meaning or support its role in its interactions this is one of the key parts of domain driven design that I really like so going back to the old way that we do things where you have a database and then you have a table and then you represent those in classes, right? Like typically you have all the properties from that table on that same class, right? Because you need it to come in and out. When you're doing domain driven design, you don't care about any of that. You care about what you're trying to accomplish. And so if there's a hundred properties in that table, you might only have
Starting point is 00:56:05 five in your domain object because you only care about doing certain operations. And I love that right here. Cause that's the thing that when I read that, I was like, Oh, that's, that's really cool. Cause that's really what we're trying to get down to is what is the business behavior or functionality we're trying to do everything else we don't need but i'm sure there's been times when you look at some code and you're like oh every class i look at all it does is call another class all it does is delegate all it does is delegate all get does it delegate here i finally found a class that does something and it you know updates a bit field which can be frustrating as a programmer but also you know the we're talking about the reasons how we how we end up there and
Starting point is 00:56:43 why we do that and i thought there was a strong correlation there with the solid principles that we talked about for more of a micro level. And so the idea here is to abstract away those complexities and abstract even the creation of these aggregate roots or complex objects into one spot. And another quote they had in the book is that you don't create the car and drive the car at the same time.
Starting point is 00:57:11 Although I've worked in some places that absolutely do that. But I just like the idea of breaking the stuff. I'm thinking about it just like these higher level concepts the same way you think about code. And so the idea is to have the factories know about these rules of these complex objects and also know about these invariants so that they can enforce these invariants. Right.
Starting point is 00:57:35 And so in this case, we are building classes that or methods that manage these, these intricacies, even though they're outside of the aggregate route, which is something, it's kind of in contrast to what we just talked about, which was having the aggregate route do everything. And they kind of go into that a little bit. And that's definitely the point that they're very aware of in the book here, and they kind of talk about how we can manage to keep those lines clean.
Starting point is 00:58:09 So let me make sure I'm fully understanding what you're saying. So instead of having the aggregate root be the controller of its own domain, you're saying now that the factory, some of that responsibility is leaking out to the factory. Right. And that's the thing. So there's a couple ways to handle that and a couple ways to deal with the problems there. And one method is to not actually mess with those internals, but just to delegate to that aggregate route.
Starting point is 00:58:36 And that seemed like the cleanest to me. Another way to do that is to have the factory know a minimum amount of the rules and invariants, which is pretty gross. But it seemed minimum amount of the rules and invariants, which is, it's pretty gross. But I, I seem to me like the, um, the example that you have there about delegating was the best way to go.
Starting point is 00:58:51 So it was everything still being managed through the aggregate route. Uh, but you know, it's, it's tricky. So that's like, that's losing me though. Because if I'm going with our car analogy though,
Starting point is 00:59:03 now the car, like I think, okay, cars on an assembly line in a factory there's the factory that's creating the car let's not but now you're saying that the factory is telling the car how to make itself yeah it's like hey car throw on these wheels hey car here's a windshield so i i am a little curious though because typically when we talk about factories, we're talking about creators, right? So hammer factory factories. That too. I guess my question is, how is it, does the factory need to know this business logic in
Starting point is 00:59:39 order to create the car? Or is it doing something with the car after it's already been created? It's fully in charge of creating the car in the first place. It's the car or is it doing something with the car after it's already been created it's fully in charge of creating the car in the first place it's the car factory you know it's the one on those wheels those that windshield it's stamping the vin number on there it's doing all that stuff okay so it's literally we're talking about we're talking about business logic that the factory knows about in order just to create it once Once it creates it though, the aggregate sort of on its own doing whatever it needs to do to maintain its invariance or no. Yeah, absolutely. So this is actually kind of a step in a side direction here because the factories are totally, they're not a member of the domain, right? They're not something that
Starting point is 01:00:21 the customer understands. They're not something that knows well. And it kind of runs counter to all the stuff that we talk about, about trying to align everything up with this ubiquitous language. Now we introduce these factories in and they're basically helpers that help us manage stuff. And in order to do that, we've got to kind of cheat some of these rules. And so we've got some guidelines here that kind of help us avoid the worst parts of that cheating and kind of stick to the best practices there. Okay. Yeah. And so by having this stuff in factories or a factory,
Starting point is 01:00:52 then we're bundling the knowledge in one place, which is good, right? So we're not spreading out all the information to create a car in multiple different places. And they give us two good criteria criteria for creating good factories. And when I say factory here, we are talking about like a factory class as well as factory methods. Like if you've got like, say a car class, you could say, you know, car dot create, and give it the information it needs and have it create. So it doesn't necessarily have to be its own class. The first rule is to always return an object in a consistent state. And that's where we talked about managing those invariants.
Starting point is 01:01:34 And that's where some of that business logic comes in. It's like sometimes you have to know what those invariants are if you're going to make sure to create an object that's in a consistent state. You don't want a factory that's going to return something other than a fully functional car, right? That makes sense. Okay. The second one I thought was really interesting. They say they want you to abstract to the
Starting point is 01:01:55 type desired, not the class. That's an example where if you've got a car, you may have a factory for a Porsche, you may have a factory for a Ferrari, you may have a factory for whatever, but it should always just return a car. And the same thing with the factory method, which is where things get a little weird.
Starting point is 01:02:14 You might have a Ferrari class, and you may have a factory method on that says Ferrari.create, and it should create a Ferrari, but it should return a car. Okay. And that's so you can use it abstractly. Okay. Wow. So this is where my hammer factory factory joke was going extreme now, because now you'd have a factory, a tool factory, and you're like, create a tool, but I want a hammer. And so that factory is like, well, secretly behind the scenes, I'm going to call whatever hammer factory is necessary to return back a tool.
Starting point is 01:02:51 Yes. Yeah. Factory is all the way down. Okay. So this makes sense then. Now I understand why we're talking about the business thing, because we're saying in order to create this car in a way that makes sense for the invariance, that factory might need to know about what those invariants are in order to return this thing into a proper state, right? Like, like you couldn't have a factory just add three wheels to the car because then it's not going to be a car. Yeah. The factory needs to know that there's three wheels or 18 wheels or, you know, four wheels on the bottom and one on the back. Okay, I get it. I don't know how you get past that, but that makes sense.
Starting point is 01:03:28 Yeah, it's definitely a conflict with the aggregate routes, and that's why it spends a long time talking about this particular pattern because they're like, this kind of conflicts with some of the ideas here, but it's still a really good pattern because it's better than the alternatives. And so they give us, in the next section here, a few guidelines for arranging and organizing our factories to kind of minimize those downsides. So one method that they suggest is actually having
Starting point is 01:03:55 the factory method on the aggregate route. So that's what we kind of talked about, like car.create. And so that way your logic for creating is close in proximity to the actual car itself. So we're talking about a static method in our aggregate route basically. Yeah. Okay. Yep. And another suggestion they give is a factoring method on a similar spotter.
Starting point is 01:04:22 And I thought it was cool that to use the word spotter here um in in the car example um i think a good one might be you already have a ferrari a ferrari factory and now ferrari wants to come out with a new you know ferrari se that's got an upgraded engine and a cool new spoiler right it might make sense for you to just kind of tack that on to the ferrari factory and uh you know either give it another method or maybe take some different arguments or something in order to uh be able to create slight variance but you're not going to want to do something totally different here it's just for um this is an option for when things are really similar okay you said something a moment ago though About the factory and the aggregates
Starting point is 01:05:06 But I was kind of thinking that The aggregate though is just a collection of the instance There right The aggregate is a collection But the aggregate root is the one that kind of owns it So this factory is creating the aggregate roots Well and any aggregates creating the aggregate roots. Well, and any aggregates within the aggregate.
Starting point is 01:05:28 Yeah, it's still a collection. That aggregate root is still a collection of the instances. Yep. Well, it's the root node on the kind of the hierarchy. I mean, I guess the only thing that I think that makes me say not necessarily a collection of instances, the aggregate route might be a one and only thing, right? Like the aggregate route might be the Ferrari is what I'm getting at. Like it might not be that this is a collection of cars. But it's a collection of aggregates, which are all an instance of like a tire, a steering wheel, a seat, an engine.
Starting point is 01:06:05 Yes. Okay. Yeah. Right? Yeah. Yep. Another example they gave was just kind of having a separate factory class. And then we've got some tools like dependency injection or whatever for configuring different things like that.
Starting point is 01:06:21 But it's really just kind of having it on the side there. And they also give the example of just having a plain old constructor, but and even the factory class, having a standalone factory class to kind of warn you a little bit about like they definitely have a preference for the factory method for keeping things, everything there, because by having stuff in a separate class, you it's really hard not to duplicate those rules and you know out of sight out of mind if you're going to do a constructor here's a couple things that they told you to keep in mind which i thought was really interesting um like for instance this is maybe a good option if
Starting point is 01:07:01 you really don't care about the object hierarchy which is kind of a tough thing to tell a programmer like this is uninteresting it so don't worry about it but it's for really like um you know there's some situations when you know that you're really not going to be doing a lot of fancy stuff so you know car is a terrible example but um i don't know what's a small piece on the car that no one really cares about well hold on a second though so yeah floor mat so you're saying though the constructor we're talking about the constructor on the ferrari class itself right yeah in the aggregate root class and we're saying that hierarchy there's a few cases where you might want to consider a constructor,
Starting point is 01:07:46 but in most cases you don't want to. But here are the guidelines. I know we've talked about constructors just getting nasty because of all the parameters you might have to add before. So you would have a static method that's like create, you know, for our ESE, right? As opposed to... Well, not even that.
Starting point is 01:08:02 I mean, if we go back to clean code, though, we talked about like reducing the number of parameters that you'd pass in so then you might have like some kind of a configuration object right yeah you could do that pass in okay all right go on please but basically it's a really boring class that doesn't matter then constructor may be a valid option and no one will ever care okay um another example was maybe the client actually cares about the concrete class that you're using. And that's an example of maybe like a strategy. Like maybe it cares how you're creating that class or that car. Maybe it, you know, I like to think of a little chess game I made where I had different, you know, I had like the chess master AI.
Starting point is 01:08:40 I had the random AI. I had the random AI, I had the crappy AI. And so maybe the client, the client doesn't necessarily mean the website or client code, but just anyone calling that code may very specifically have a reason for creating this particular class, like it wants a Ferrari, I got you instead of having a car type coming back, it actually needs that specific concrete implementation of that class. Right? One thought that I had, though, is that you're saying that, you know, the preference, back it actually needs that specific concrete implementation of that class right one thought that i had though is that you were saying that you know the preference eric had the preference of he and i are on a first name basis um he had a preference to the factory methods over the factory
Starting point is 01:09:19 class but i was thinking that well if you wanted to support like an abstract base, then you'd have to have really a both situation. You'd have to have the factory class that you would call and say like, hey, create this car. And this is the specifications for what I'm looking for. And then that thing would decide, oh, well, he wants a Ferrari. So I'm going to create the Ferrari andari and return back a ferrari but the type that is being passed back as is just the car the abstract car right so there might be like a ferrari.create method that's being called inside of the factory class so a factory class calling a factory method yep yeah that's that's legit i, because how else could you handle that abstract case then?
Starting point is 01:10:07 Yeah, like my initial thought is like, oh, you just have an interface and then you have your car factories, like your Ferrari, whatever, implement that interface that has create method that returns a car. But you can't do that because the factory methods I generally think of as being static methods, which can't implement interfaces. So I guess you could have some sort of abstract car class that requires a, you know, like a, what's called a virtual factory method that returns a car. That would be one way to kind of enforce that relationship, but it's not great. One thing to consider here too are, are there any attributes that are hidden from a client? Like if there's private variables that need to be set or maybe internal package properties that need to be set then that's not something you want to turn over to a client it's just not a good candidate for using a constructor and another way is construction simple this is something we've talked about with those
Starting point is 01:10:59 parameters growing you don't want to be be having clients in charge of creating complex objects, right? That's why we create factories in the first place. So not a good candidate for constructors. And another one is if there are invariants that we care about here. So if there are little rules that a client needs to take care of things that, you know, where the, um, the conditions for these different properties matter, like maybe you can't, uh, you know, set numbers higher than this, if some other parameter set, or maybe you can't have, um, three tires on a Ferrari, um, then that's probably not a good, uh, candidate for, for a constructor because you're going to want something that's going to know those rules and be able to enforce those rules.
Starting point is 01:11:52 All makes sense. Yep. So we do have two guidelines for actually designing your factory classes. The first is that each operation must be atomic, which means there's one method, one result. There's no new of a factory. Now we add some configs, we do some stuff, we add some more configs, we make a decision, we do some more stuff. It's a one and done. Arguments go in one end, output out the other and uh my initial thought there was like if i i've never really done it factory any other way but um if i had i probably would have called it a builder because
Starting point is 01:12:34 that's the kind of thing i think of where i do some kind of like additive conditional stuff that's a little bit more complicated but to me a factory has always been kind of one and done as a singleton. Yeah, well. My boy singleton. Another one is to keep in mind here is that the factory is always coupled to its arguments. So be careful with complexity and stick to predominantly lower level classes
Starting point is 01:13:02 and also stick to abstractions if possible so deal with interfaces deal with um higher level objects so lower level classes but higher level objects what do you mean the factory is coupled to its arguments though so um anything that you uh any classes that the factory knows about like if it takes in a wheel class, a tire class, I don't know, an engine, I guess just be saying object, if it takes in a wheel object, a tire object, an engine object, then it needs to know about all those intimately. And so you are increasing the things that it cares about. You can imagine, I don't know, maybe a more better design would be to take iModules or something to the sort that it can just kind of add. But that doesn't really make a lot of sense for a factory that needs it now. I guess where I'm getting confused, where I'm getting lost in this description then is, are we talking about, when you say the factory is coupled to its arguments, are you saying that the creation of the factory itself
Starting point is 01:14:05 or the factory is coupled to the arguments for the things that it's going to create? And so that in order to create the car, it has to know about the tires, the floor mats, the engines. That's what it sounded like, right? Like the more arguments it has, the more knowledge it needs to have of what it needs to be doing.
Starting point is 01:14:24 Which goes back to the clean code version where it needs to have of of what it needs to be doing which goes back to the clean code version where it's reduced the number of parameters that you're passing into these methods is that what we were saying yeah absolutely and when i say um stick to higher level objects i mean take a tire don't take the rubber and the hub and the rim and the nuts and the bolts and you know and uh the little cap that goes on to keep the air from going out the valve the inner tube what do you call that the little valve that goes on that um but no it's just uh you want to stick to kind of higher uh higher level abstractions so if you can take a set of wheels that would be great um so it just uh it's just kind of a warning there to let you know that these factories are pretty gross, and they tend to touch a lot of different things, and you want to try and minimize that if you can.
Starting point is 01:15:12 And then moving on a little bit, we talked a little bit about invariance and what to do about that. One solution is duplicating the logic. You could have your factory checking to see if you've got four tires, and you might also have your car checking to see if you've got four tires and you might also have your car checking to see if you've got four tires which is you know kind of gross so the tire thing not not such a big deal but you can imagine that getting a little crazy if you're talking about like orders and order items you know there can be some pretty specific rules going on um and you don't have to be duplicating that so another object or another, um, maybe even getting too caught up in our car example though.
Starting point is 01:15:48 Cause I was thinking about like going back to how long ago was it that we talked about the builder pattern? Uh, that was definitely a long time ago, but you know, I'm thinking back to like you, like you just said, tires don't matter. And then I was like well you know i can kind of see the case for let's say we keep talking about ferrari but let's let's change it and say that we talked about toyota for a moment right and you might say uh if you had a toyota class with the static uh factory method on it or let's say if it was a builder you know and maybe
Starting point is 01:16:19 you'd have like a create dot tundra or or i'm sorry sorry, Toyota.create tundra or Toyota.create Supra, right? And in which case those different factory methods would have to know the specifics of, this is the things that make this car unique, right? So this is the specific type of tire. One's going to be, you know, a low profile, more sporty tire versus one that's going to be a larger uh more beefy off-road tire right so and um there are a lot of dependencies between the two too so if you like say get the extended cab maybe you have to get a certain type of uh seat or maybe you have some other options that open up because of that and so the car thing is definitely a rough example because it really lends itself more to like a kind of a builder.
Starting point is 01:17:05 And even just thinking about how cars are made, there's typically like an assembly line where you kind of add, add, add, add. And so it's not as simple as a one and done like the factory is. And the factory is very concentrated in this kind of atomic operation where you give me the config and then, you know, I do it. In this case, in the case of a car, you would probably want to have some sort of whole other process that allows you to kind of plug and play those parts and validate them. And then you would pass off that completed and verified configuration to the factory who would be in charge of putting everything together and putting it out, the Tundra in a consistent state.
Starting point is 01:17:44 Yeah, I'm definitely getting lost on the car example. I mean, if you went to the order example, though, I mean, it's a similar type thing, right? Because you're going to set up your order. So if we're talking about the aggregate routes, right? So we're talking about a factory method to create your order. So there's going to be some sort of identifier, an order number that it's going to use to create your order. So there's going to be some sort of identifier and order number
Starting point is 01:18:05 that it's going to use to create that thing. And with that, you're going to have, you know, totals, shipping amounts, taxes, that kind of stuff. Right. And then it's going to need to know how to build up probably the order items underneath it. So that factory pattern or that factory method is going to need to be able to push all that stuff together. So, so I think the whole thing is, do you do this at the order level? Because it's going to need to make sure everything's consistent. Those invariants are met at that point, right? When it happens. Whereas if you do it in the external factory, you're going to have to know about all that stuff. You're going to have to know that, okay, the line item total needs to match what the order total is and, and, and, and all this
Starting point is 01:18:47 kind of stuff. So that's basically what we're getting at though, right? Is if you move it into the object itself, it has more of its, its domain knowledge that it can, it can take care of for you because it's already built into that aggregate route versus if you, if you keep it in your factory method, that's abstracted away, you're going to have to duplicate all that logic, right? Yeah. And duplicating is bad because that's how mistakes are made. Right. And you'll also get right. You'll get inconsistent conditions too, because if somebody came in and updated the order class and said, Oh, you can have this rule, but then they didn't
Starting point is 01:19:25 realize that they needed to update that factory class. Now, again, so it goes back to what you say. It creates bugs because now you've got two different places that are trying to dictate the same thing, but they're doing it probably differently in the first place. Yep. And so the three kind of options that they presented in the book were basically one, you could just duplicate the logic. Don't do that. The second was moving the logic completely into the factory, which is just a little bit scary, but it's kind of like saying instead of the car knowing that it has to have four tires, you just say all cars forever must come from this one factory. And this one factory knows how to make them and no one else knows the rules for what it takes to put them together, which is also a little them and no one else, you know, knows the rules for what it takes to put them together.
Starting point is 01:20:06 Which is also a little scary if you think about, you know, taking that car and getting maintained or, you know, maintenance or having some changes made to it by an external object. And like suddenly, like what? It doesn't know the rules? Right. That's what I was going to say. Now, at that point, you've moved all the valuable invariant logic out of that that car and so it doesn't even know what's right anymore so literally the only thing that could ever maintain its state was that factory which is one and done right when it creates its hands off after that yep and uh so
Starting point is 01:20:38 the third option they gave was basically to have it delegate um to the product and program being basically the uh the aggregate route so you would have the car add the wheel and you know you could ask the car like do you have enough wheels or maybe you know how many do you need so your factory would basically be like um car.addwheel or it's gonna it's basically gonna try and spin it up by calling all the the methods on the aggregate route itself all right but it still needs to have some knowledge like it needs to know that you know the car even needs wheels in the first place and so there's definitely um some some blurred lines here which is pretty gross but if you kind of stick these guidelines and um kind of ask yourself the questions that
Starting point is 01:21:17 we presented here about different attributes and the different ways of creating factory factory methods and hopefully you're going to be creating factories in the most sensical way to fit in with DDD. Yeah, it sounds like I definitely like the idea of the factory method inside of that class because then you're keeping, like you mentioned before, Joe, you're keeping the logic close together. You're keeping the internals close together, right?
Starting point is 01:21:42 But like I pointed out, it sounds like there is a place for the class, but that's where you should, to avoid the factory class from knowing too much, just use some interface or abstract base class or whatever to be able to pass in like as a container of the specification details for those various objects, but let the actual factory method deal with the internals of that thing. Right. And that way, you know, it's kind of like marrying everything that we learned about clean code with
Starting point is 01:22:13 DDD. Right. Yep. And we'll get clean DDD. Cleaned. Cleaned. Cleaned. I love that.
Starting point is 01:22:23 They definitely have a preference for the factory method, and after reading this, I do too. But you do have to keep in mind that we are absolutely in violation of the separation of concerns. Like we have a class that knows how to create itself and then how to actually be itself, which are two different things. So, you know, there's trade-offs. There's no perfect.
Starting point is 01:22:42 OLED. Yeah. Do you have another question for you, though? What about reconstituting stored objects? So, like, deserializing something from JSON. What do you do if the JSON is invalid? Those line items don't add up to the total. You throw an error, right?
Starting point is 01:23:00 So, that's what would normally happen, right? If you were trying to kind of have the factory put this stuff together and you would just throw an error if you don't have enough wheels or whatever. But they also mentioned in the book, one other option is actually just to fix it, which is not appropriate in a lot of cases. But for something like an order total, it might be. But, you know, I'm sure there's someone working in accounting right now that has a fit about changing any sort of total in code
Starting point is 01:23:25 without having to run through the formalized processes because it may not add up on a ledger somewhere. That's a good point. But it also sounds like that gets dangerously close into the repository area. Yeah, and we're definitely leading into that yeah well you know it does give two guidelines go ahead no go ahead i'm sorry i was gonna say i'm the only thing about uh the the uh the only other thing about reconstituting store objects that also advise you not to assign a new
Starting point is 01:23:59 tracking id to use the one that's been serialized with and if it hasn't been serialized with one then it should have been. And you're really at this point implementing the prototype pattern where you're creating a copy of something. So ideally, your serialized object is going to have any sort of identification that it needs already. Assuming that you can read the ID.
Starting point is 01:24:18 Yeah. I'm going to hold my question that I have because I think it's about to be answered in the repository thing in a minute. Oh, alright. Well, on that bombshell, I'm going to hold my question that I have because I think it's about to be answered in the repository thing in a minute. Oh, all right. Thanks, sir. Well, on that bombshell, let me just say that if you have already left us a review and you're one of the many names that we have called out in all of these episodes,
Starting point is 01:24:40 we super appreciate it. It puts a smile on our face, you know we can't say enough how how happy we are to read those and if you haven't already left us a review we would forever be grateful if you would head to www.codingblocks.net slash review and there you can find links to itunes or stitcher where you could leave us a review and just know that you'd be putting a smile on our face before we get into your yeah sure your favorite part of the show my hey uh so the review yes also we give away tons of cool stuff uh you know monetary tons of free stuff as well as just cool tips.
Starting point is 01:25:25 Well, now you're making it sound like we gave away money. So let me clarify that. Let me correct him. Things that have value we give away on our mailing list. So if you're interested
Starting point is 01:25:35 in, you know, winning some cool stuff and having some fun interactions, definitely go up to our site. And if you're on mobile, it's probably down towards the bottom of the page. But if you're on a computer, it's off to the the right sidebar just go over there and sign up for our newsletter
Starting point is 01:25:49 you know we uh we are pretty good about just giving away tons of free stuff in a fun way most of the time we may ask you to vote for us for things sometimes though like about five percent total we did ask for a vote. But everything else has been a giveaway, but it's not 100%. Just wanted to put that out there. We probably need to change the name of it, but I was going to say we should change the name of it to a giveaway letter, but then Joe, I guess he kind of took the wind out of those sails and said that we couldn't call it a newsletter.
Starting point is 01:26:21 We don't always do a giveaway, So I guess we have to call it. There was one when we didn't have a giveaway directly tied to it. Yeah. But mostly, mostly it's cool stuff. So at any rate, yeah, I wanted to just throw that out there and definitely join that.
Starting point is 01:26:35 And, uh, all righty. Now it's onto your, right. Join the giveaway letter. All right. So,
Starting point is 01:26:41 uh, time for my favorite portion of the show. Survey says. You know, we actually got feedback on me specifically saying it like that. Someone really liked that. Yeah. So I got a kick out of that. So in our last episode, we asked,
Starting point is 01:26:59 what's your headphone style of choice while coding? And your choices are on ear, great sound in a compact shape. Over ear, sweet pillows of sound. In ear, I need all the sound in my head. Or earbuds, because the pain is worth it. All right. So I think Alan went first last time, so I'm going to go with you, Joe.
Starting point is 01:27:27 What say you? What's your choice? In ear at 37%. In ear, 37%. You're wrong. All right. Wrong. You think it's 80?
Starting point is 01:27:39 I'm going to say over ear at 33%. All right. In ear at 37% versus over ear at 33 all right in ear at 37 versus over ear at 33 right all right well i will say this alan did have the more popular choice and by price is right rules he is today's winner sweet i even came in under yep wow yeah over ear i mean really i think that my description there pretty much summed it up it was the sweet pillows of sound as you could see uh yeah 44 of the vote i i mean when i used to do the headphone review things every request was for an over-ear set of headphones. And honestly, from a developer standpoint,
Starting point is 01:28:29 the reason why I think this makes more sense, have you ever been sitting in an office when you had stuff in your ears and somebody comes by and taps you on your shoulder, you're like, hold on. Right. Whereas with the over-ears, you're just like, what do you need, dude?
Starting point is 01:28:44 I don't even think it matters if you're a developer that the the in ears especially depending on the tips that you have on them like if you have the comply tips you know the soft uh squishy foam ones where you got to like roll it up and then stuff it in your ear and then it expands i mean those are those sound amazing but they're annoying if you have to have any conversation with anybody or if there's even a chance that you might have to have a conversation with anybody else. Yep. So, I mean, in fairness, that's kind of what I was thinking is a lot of people are working in an office environment,
Starting point is 01:29:18 and it's just kind of a pain to pull them in and out, whereas with just a set of headphones, you'll just pop them off your ears and throw them around your neck. Well, I was thinking of a plane environment, so I wasn't thinking of an office. Because I used to travel with the in-ears, and any time a flight attendant would come by and ask me, I'd be like, wait, what? Hold on.
Starting point is 01:29:37 And then you'd have to do that same thing. We used to have to do that with the over-ears. And if you get a phone call, you just click a little button, and now you're talking volume up, volume down, like right here. Over-ears have that, too. It fits in your pocket. When you go to Publix. Over-ears have that, too, man.
Starting point is 01:29:51 We're not in 1980s. Come on now. No, man. If you go around walking around the grocery store with over-ears around your neck, you're like... Oh, dude, that's actually a thing, though. So if you look around... If you're 16. Dude, that's actually a thing though. So if you look around. If you're 16.
Starting point is 01:30:05 Dude, that's what I'm saying. Like people actually like headphones are like the new, you remember Nike's back in the day? Like that was like if people was wearing a set, if they were wearing a set of Air Jordans, like that was their status symbol, right? Nowadays having that Beats logo on the side of your head, like that's part of the getup.
Starting point is 01:30:24 Have you seen me i would look ridiculous walking around beats in the grocery store like buy my freaking like fiber one whatever dude those are horrible but no do you care to take a guess at what you think second place was uh in ears yeah 25 if it's earbuds it's only because people got them mixed up with in years there's no other solution so so you're gonna go from in ear to earbuds for a second place yep do you want to put no no i'm gonna stick with in here sorry in here oh oh okay so both of you guys have the same guess then 25 it's going to come down to the percent alan says 25 what's yours 18 18 all right well you both you both were
Starting point is 01:31:15 wrong we went over it was earbuds no man only because people were confused about that's in the ear and earbuds yeah because nobody likes earbuds i know i you know what i think you're wrong i think that i i mean it was the strongest it was a strong second place too at 39 man that's what it is people don't know because no no because you made such an effort to explain it last time i think that it's not a matter of people didn't understand what the question was i think it's just that it's either convenience or laziness or just frugalness that you know it was the easy choice right right now i will say i have not tried the new whatever comes with the iphone i hear that those are pretty good but the ones that came with like the old ipods that were like the size of a speaker that you would cram into your
Starting point is 01:32:05 no one of the new ones called ear ear pods ear pods or something yeah the new design is just as awful as the old design in my opinion man look i i almost feel like this should be you know like save a child like save some ears i feel like we should start some sort of like some for less than a cup of coffee a day yes we can save your ears so anyways all right well that means that we have to have a new survey for this episode so i thought it would be funny uh when we said invariant earlier did you know what it meant? Your choices are yep or nope. Do we want to give a don't care? No, you can't do that. It's got to be yep or nope.
Starting point is 01:32:53 You either knew it or you didn't. If you were like the three of us and you had to look it up, you're in the nope. I totally felt better when you guys were like, hold on, let me, I was like, oh, okay. Well, it felt good to know that I was in good company. I don't know if it made me feel any better to know that I didn't know it.
Starting point is 01:33:10 Hey, honestly, the first time you heard item potent in the past couple years, were you like... You mispronounced that. Don't talk to me like that. No. No, why are you talking to me? Why don't talking come over here and say that all right we're i want to do i want to do one quick uh google feud though oh yes yes one
Starting point is 01:33:37 quickly we this was you guys really enjoyed this one last time, so I thought, okay, we've got to do it one time. How to program blank? Minecraft. Minecraft. That's a good one. Man, that kind of hurts me. How to program for iPhone? Both good
Starting point is 01:34:01 choices. Number one Google suggestion is Adreno not for me what no how to program adreno no mine says up is how to program raspberry pi was number two for me hey listen i'm the guy calling out the question here okay we go by my computer oh man what the third one is hilarious because it's how to program the DirecTV remote to TV. That's ridiculous. Apparently, their DirecTV remote is ridiculous. It's got a few buttons.
Starting point is 01:34:36 Oh, oh, oh, oh. Speaking of, I have to do this because it's not at my tip of the week. So I went to streaming only, and this is completely random. So I dropped DirecTV. I looked looked at my bill and it made me mad i had no idea i was paying that much every month right so i dropped it so i went to streaming only you had no idea no i didn't i mean that's the thing when you have things auto pay you're just like okay i have no money i don't know why but but at any rate so so i so I switched over to two PlayStation view, which I'm pleasantly surprised with until I left my house and I tried to turn
Starting point is 01:35:11 it on and it's like, oh, you're not on your home network. You can't watch this dude. I was mad, like straight up mad. I'm like, man, I, this is a problem. One of the reasons I wanted to stream was I can go anywhere and do it. They check to make sure that you're on your network. So here's a little pro tip for you. If you have a decent router, a pretty nice one, a lot of them have VPN built into them. So you can basically set a set of keys, put them on your phone, put that VPN client on your phone, VPN into your house, and stream just like you're at home. So if you get mad like me and you buy something like PlayStation View that won't let you stream outside of your home network,
Starting point is 01:35:57 VPN back to your router, and it will use your internet connection at home to stream back to you. It's beautiful. That's a lot of work to watch the Real Housewives of Kennesaw. It not that bad man it's really not that bad it's got to be secure it's really not that bad you know i've been a sling customer for a while and i haven't had that problem with sling so it is it is going to vary by does and now there's a hulu has just recently announced their new live TV streaming. And YouTube is supposed to be coming out with theirs here later this year.
Starting point is 01:36:30 And you know the beautiful part about this is, so first I went with the PlayStation because it had a really good set of things that I was interested in. And their device support was about the best there was. Outside of it, of course, they're not going to do the Xbox. But outside of that, it worked on basically gonna do the xbox but but outside of that it worked on basically every device and i was like cool but what i like about this whole thing is unlike cable you're not locked into some crazy term contract if if youtube comes out with theirs
Starting point is 01:36:56 next month hey guess what i'm gonna stop this one i'm gonna go try that because it's not like you have this contract you just say oh i'm done with it right yep that's so sweet so but yeah that was something i found out about the playstation view after i got it was oh no it locks you into your home network but not if you have a router with vpn right so anyways sorry sidebar this episode is sponsored by Linode. Cloud hosting for developers with high-performance SSD Linux servers for all your infrastructure needs. For $5 a month, you can get a gig of RAM, one CPU core, 20 gigs of SSD space. That's more than what most other hosting competitors offer for the same price.
Starting point is 01:37:41 They have nine data centers across the world, including Asia Pacific, North America, and Europe. Linode has simple control panel for managing your hosting, and they even have an API for your automation needs. Go to www.codingblocks.net slash Linode, that's L-I-N-O-D-E, to get started with Linode today. All right, so let's wrap up our conversation tonight with repositories, right? So there was this one statement that he has in the book about repositories represent all objects of a certain type as a conceptual set, and it acts as a collection except with more elaborate querying capability. And I found that to be a curious statement. Like I didn't, to be honest with you,
Starting point is 01:38:32 like when I read that, I'm like, what? No, because like we've talked about the repository pattern before, right? And when we've talked about the repository pattern before, did anything I previously said, did that register with you? No, not really. Because it's usually just some sort of transport object, right? Or a transport method is what you're thinking about.
Starting point is 01:38:55 Yeah. I mean, I guess if I had to put it in my own words, I would think about it as like it focuses on the CRUD portions, right? Yeah. So yeah, I had a hard time kind of like wrapping my head around parts of this, at least from this approach, right? But then I think I later came back to being like, okay, I think I'm, I think I'm on board. I think I'm better, right? So when we talk about repositories, you know, as I, as I kind of alluded to with the CRUD operations, we're talking about objects that focus on persistence.
Starting point is 01:39:30 They care about the persistence. This allows your client to be focused on the model. It doesn't have to worry about what's needed to retrieve the objects. It doesn't need to worry about what's necessary to retrieve the objects. It doesn't need to worry about what's necessary to persist the objects. It just has to worry about, you know, the objects in general and how it might want to use those, right? And the repository is going to retrieve whatever requested object, and it's going to do so in a way that's going to encapsulate any of the machinery behind the scenes, right? Anything that's necessary to query to get that data, as well as, and this is what I found really curious, mapping the data back to an object, all right. And kind of, you know, going back to what Joe was saying, right? The repositories can
Starting point is 01:40:30 use factories to do the actual object creation. But when I think about the mapping of the data, if we talk about, we talked about possibly creating like some kind of a specification object or a configuration object that would, um um i really want to stay away from the term specification at least for this portion so you know if we pass in a configuration object to that factory that factory method right that thing knows that like hey whatever data i got from this particular uh record or column it is supposed to represent this particular type of thing or this particular property of whatever my final object is. So, you know, going back to our car example, maybe this particular column represents the engine size. This particular column represents the car color, things like that, right? And generally, we would just have our repositories implement a
Starting point is 01:41:30 common interface so that those CRUD operations are kind of consistent among the repositories, right? And we might have multiple repositories spread out throughout the application to create this specific things. And when you're talking about the interface, we're talking about things like create, save, or maybe save, get, update, that kind of stuff, right? Those are the common interfaces we're typically talking about with the repository. Your method names may vary, right? Like if you wanted to just, you know, create, read, update, delete, or you could do add,
Starting point is 01:42:09 save, update, whatever, you know, change, you know, whatever. But yes, it would be some basic set of operations that would exist across your repository. So you, you know, again, you might have multiple repositories, right now, but this was another one of those points where like, it took me, it took me a moment to grasp what he was getting at, because I said you could have multiple repositories, but he goes on to say like, you could have multiple repositories for each type, but not necessarily each class. And I was like, well, wait a minute. Wait, what? A class is a type what do you mean well how can you have multiple repositories you can have a repository for every type but not a repository for every class which sounded at first like it like kind of a confusing statement but what he was getting at though is that you might have repositories at like an abstract level or a base class level that they don't care about the
Starting point is 01:43:08 individual's specifics, right? So, you know, carrying on with the car example, you know, you might just have a repository for like a read car or say, you know, update car. Right. But it doesn't, it's not going to read in, you know, you don't need a class, a repository class specifically for Ferrari. You don't need a Ferrari repository dot get car, right? You just, the car repository could be generic enough. And then specifically in this portion of the book, the examples that he gave was related to stocks. So you might have like a, a trade order and that's the base for a buy order or a sell order. So your repository is the, uh, trade repository, trade order repository, and it doesn't care if it's a buy or sell.
Starting point is 01:44:08 So then once I kind of grasped my head around that, it kind of made a little bit more sense what he meant about a repository for each type but not each class. And then your repository can offer many ways to query for a specific type of... Yeah, and I was going to ask you about this when you talked about implementing common interface with basic reads. It's like, well, what if I said, I wanted to be careful about the use of the word specification as it related to this portion, because he brought up this really interesting
Starting point is 01:44:53 concept. It was at least new to me. I hadn't seen this elsewhere, but he did reference, you know, many other places where they talk about, you know, I think there was like a Martin Fowler example that he referenced, you know, from, you know, I don't know, more than a decade ago, that I hadn't heard about. But basically, it was you have this specification kind of type or language, that you can use that to define what it is you want, without actually hard coding a query into your code. So he gives this example of where you have this criteria object, and in your criteria object, you would say criteria.equal, and you would pass in what I assumed to be an enum value,
Starting point is 01:45:41 and then what the actual value of it was that you wanted. And then you're allowing your repository object to actually be responsible for the construction of the query, because it's the only thing that should know the actual internals, right? Because, you know, going back to what I said before, it's encapsulating the machinery to do that query, right? So I thought that was an interesting concept, too, because, you know, I mean, you know, guilty, How many times have we talked about, or how many times have you just like wrote a query to do that? Right. Instead of the specification. Yeah. This repository is basically your translation layer at that point. Right. Yeah. Yeah. Yeah. But when we've talked about repositories in the past though, I kind of pictured them more generic than what the level he was getting to in here. And so that part was a little bit more of like,
Starting point is 01:46:28 oh yeah, that, that makes sense that you, you might have many repositories, um, you know, for each of the different things. So,
Starting point is 01:46:36 so going back to our order, uh, e-commerce example, right? You'd have an, uh, an order repository that would be responsible for knowing how to query. And if you wanted to, to get a specific query, I mean a specific order ID,
Starting point is 01:46:51 uh, you know, you might have a, a specification object that you could pass in where you could say like, uh, you know, where the criteria is, you know, equals, um, order dot ID and then some value. Right. Um, so I thought that was, that was a pretty interesting approach and I actually want to follow up more, a little bit more on that specification, uh, idea. It sounds like an I queryable, like what, it sounds similar to that whole notion when you look at like entity framework, that kind of, no because iquirable is just chaining it together there right right and then yeah so that's what the reason why i think about it like that because you can keep adding to an iquirable i'm sure that the specification
Starting point is 01:47:35 object's a little bit different you meant just the fact that you could have the specification object and just keep spat yes um you're basically just adding in additional portions to the predicate yep and then your repository would be responsible for taking that and translating it into whatever query language needed to go get either from a relational database or some sort of document db or whatever
Starting point is 01:47:56 but yeah that's kind of what happens in my head is I'm like oh well that'd be amazing if you could just say.where and.where and you know yeah that's what I'm kind of imagining. It's like you have a specification object, you know, like.addFilter, right? And you say, you know, model. And then, you know, you have even one for like a one for the qualifier.
Starting point is 01:48:16 So you could say equals or like or greater than or less than. And then you have the actual value that you pass. But I think I like your way of saying it even better where you can kind of use those um those link style methods uh to do those afters or wares or whatever which is really nice to kind of chain those together and have like a fluent style interface which is just a nice way of nice implementation detail i guess yeah and you know another advantage to doing it that way though too is that uh you know if you just had a hard-coded string, there's no type checking on that. Whereas at least if you were to do the specification,
Starting point is 01:48:51 you'd at least have some type safety around what your logic is trying to do. Now whether or not the repository implemented it correctly, that's up to you, I suppose. But yeah. I like that. Yeah. i suppose but uh yeah i like that yeah so um yeah so so by doing this there's some benefits to using the repository pattern right you allow your client by going through this repository to talk in what he calls an intention
Starting point is 01:49:22 revealing language right which going back you know we've already made a comparisons back to to talk in what he calls an intention-revealing language, right? Which, going back, you know, we've already made comparisons back to the Clean Code series. This is right up there, right? Like, you have a method that would be named kind of similar to what you're wanting to get, right? You might have, you know, I mean, going back to the order example, that's a simple enough example. You might just have one that's like order repository get by order ID, right? We've seen those kind of patterns before. Customer.get by customer ID or something like that, right? Or customer repository.get by customer ID. So before we go too much further on this part, I just want to make sure I totally understand this. So when we're talking about the repository pattern in terms of this domain driven design, we're
Starting point is 01:50:10 really saying though, this repository is responsible of building up the entire aggregate, right? So as opposed to something like entity framework, if you just had these, these regular models that you had, right? Like, so let's go to the order and the order details type thing. Typically, if you just had your ORM, you'd say, give me the order, it would go load that information into a model, right? And then if you wanted to get the order line items, then typically, probably go back to a repository and say, load up the order line items. It sounds like these repositories are a little bit smarter, right? Like these aren't just, hey, let me hydrate these objects with some information. This is, oh, you want an order aggregate?
Starting point is 01:50:54 Okay, I'm going to get you that information and all the sub-aggregate information that belongs inside that object as well, right? Yeah, that's the way I took this. This is not like, and that's where the intention-revealing language comes in, right? This is not saying like, you know, Ferrari.create something. This is saying Ferrari, you know, create a California. Right. Right? Like you're more specific in this type of example, right?
Starting point is 01:51:26 And that's where like you're promoting your design decisions in this repository. So let me back up then. So what you just said means that what we're saying now is this repository gets a request. It's going to then call a factory, which is going to hide hand or factory would probably typically call a factory and create this route. Is the repository them responsible for filling in the details? Or does it pass any information along it needs to the factory? Should all be in the factory. Okay, so it's all in the factory. So this repository is really responsible for going and getting all the data that's needed for the factory to do its job.
Starting point is 01:52:09 It's getting the data, but it's mapping that data to the things that the factory needs to know. Okay. Right? Like, the repository knows how to read off of disk a particular piece of data, and that that data is supposed to represent the engine size, but it doesn't know how to create the engine necessarily. So it can use the factory, but it doesn't have to necessarily.
Starting point is 01:52:34 So this kind of makes sense then. So it is very similar to the repository pattern that we've talked about in the past, except that it might need to get more data than what it typically would have for any particular thing because now it's gathering the data for the aggregate root. That's where a lot of this DDD discussion that we've had so far goes back to where we kind of started this whole series
Starting point is 01:52:58 where we talked about how we did things in the past and that we might just create some table and then create some object to represent that table. Whereas this is saying, and at that time too we might have created a repository for that specific thing that specific table but this is going more high level than that and saying like okay your repository is going to be creating something that might span tables right that that data could span tables to create but it's going to know what it needs in order to, you know, where to get it, how to get it, and the mechanics behind it. Okay, beautiful.
Starting point is 01:53:31 Right? Yeah, it scares me though. Why is it scary? I hate that he was saying like, hey, give me the, you know, the latest thousand orders and it going and going and fetching all the order items and maybe the tax info and all sorts of other stuff I don't care about. But I guess in that case, I would create some sort of like order server summary object that might have its own repository. That's a little lighter weight. I don't think you'd use it that way though. I may be wrong, but it sounds like you're almost talking about, well, let me,
Starting point is 01:53:57 let me rephrase. I guess it depends on the use case, right? Like the whole purpose of this domain, this order domain is to do something on the order. So you only load up a thousand orders if you needed to process the payment on them or something like that, right? You're not going to load it up to just view it on the screen because that's not the use case for it. The use case is you might use a regular DTO just to get report stuff on a screen. You're only going to load up these, these domain specific type objects when you're trying to get a particular behavior done, right? Yeah. So when do I, where do I get that DTO from? Is there a, is there a repository for the DTO? So this, I, this goes into a later chapter. I, And I only cursory know a little bit about some of this stuff,
Starting point is 01:54:46 so I might even speak a little bit wrong on this. But basically, you'll still have your standard DTOs that might map to database objects, right? Because those are still useful in applications. But then there's a translation layer, and I forget what they called it. It was a bizarre name. It wasn't the consistency or something like that. But at any rate, I mentioned it in the last episode,
Starting point is 01:55:13 and I can't remember what it's called right now. Yeah. The anti-corruption layer. There you go. So basically what would happen then is if those orders needed to get in, they could come across just from a true, the repositories that we've known in the past that literally are just kind of getters, right? And it would throw it into these objects. And if you needed to do any behaviors on that,
Starting point is 01:55:36 you would have this anti-corruption layer that would transfer it from that DTO into this domain model object. So I hope that kind of paints a little bit fuller picture in that these domain objects that we're talking about are created to do specific. It's we've said it several times. It's just focused on the behavior that you need it to do. Whereas the other stuff that we've all done in our entire careers and a lot of patterns that everybody sees is it's literally just, Hey, let's move it in and out of the database and we'll do any kind of stuff that we need to down here. This is more, what do we need it to do? And so there are translation layers for that.
Starting point is 01:56:12 But also- Yeah, if I'm reporting- Yeah, go ahead. If I'm doing some sort of report or something and seeing the last, let's say the last thousand unpaid orders or something, I don't want to manipulate that stuff. I don't want to give that DTO a change of value
Starting point is 01:56:24 and try to save it again. It doesn't make sense to have a repository because it's not really meant to be used for that. So that makes sense to me. And so if I think of the repositories as being lighter weight than pulling back thousands of records or doing ETL type stuff. Well, let's go back to what we've talked about before,
Starting point is 01:56:41 which is that you might have similar named objects, right, but in different namespaces that serve different purposes. So, you know, your order summary or, you know, you might call it something else, you know, is probably better than having, you probably wouldn't want or need to pull back the entire order object at that summary level for what you're talking about. Because they actually talk about like you know some of the common problems around that around this is like maybe pulling in too much data and he gives an example of uh one project where they had a a method that returned all objects and they couldn't figure out why their web sphere environment would only run a couple hours before it would run out of memory and they eventually found that oh this all objects
Starting point is 01:57:24 you know method was getting called and so they were basically loading the entire database into memory and you know everything went sideways at that point right so you know you'd probably have a different type for that you you wouldn't use the same order repository as where i'm going with that yeah yeah and in doing the reporting thing, like just thinking about that a lot of times you're not even the DTO. So somebody told me this a long time ago because I used to stress about this thing, right? Like, man, I don't want to create some sort of object just to do a report on the page because then I'm spinning up a bunch of objects. But, but guys remember anytime you're pulling, at least in C sharp world, and I'm sure in all other worlds, if you're pulling back a data table, you're still creating a bunch of objects, right?
Starting point is 01:58:09 It's an enum of objects. And it's got a bunch of type information on it, whether it's the data type, the length, all that kind of stuff. So we have a tendency to think about, well, I don't want to create all these objects, but even the mechanisms that we're already using do it anyways. Yeah. Gotcha. So, you know, just continuing along with the benefits of this pattern is that, you know, you're going to promote your separation of concerns here, right? This is the one thing that knows about how that data has persisted. And this kind of goes back to where I said, Joe's example that I can't remember right now where he is going, oh, the JSON,
Starting point is 01:58:51 I believe it was a JSON example, the deserialization, right? Where it's kind of getting into a gray area because really the repository is the guy that should know that that thing is coming from JSON, right? And it should be the repository's pattern to be able to do the mapping back to say like, hey, this is the piece of data that's supposed to represent the order ID. This is the piece of data that's supposed to represent the customer's name or whatever,
Starting point is 01:59:17 right? Right. And by doing this, this also promotes testability within your application too because you could actually have your repositories return back dummy objects. Right? Mock data. Love it. You could swap them out because they're driven off interfaces, right? He doesn't really get into that part in terms of dependency injection
Starting point is 01:59:39 or anything like that. Okay. But just the fact that because you don't know the mechanics behind what's how the data is being created then you could have a repository that just returns back some kind of dummy data that would allow you to do testing on it okay so you know there was a quick summary of of the last two portions here of, you know, the repositories versus the factories, the factories were responsible for creating the new objects. Whereas the repositories are responsible for finding, uh, and updating objects, right? And
Starting point is 02:00:19 the repositories can use the factories to create the objects. And then, you know, as I said before already, the factories don't deal with the persistence of the object, but the repositories do. That's an excellent summary. So, yeah, I mean, in large part, like the repositories that we're talking about here are, you're more more this was an easier section to kind of comprehend it was more you know in in regards to like the repository
Starting point is 02:00:51 patterns that we've already talked about except instead of being at the granular level that we may have thought about them in the past this is more higher level well i think the factories and the repositories really sort of put together what that aggregate route is supposed to be, right? Like these things are taking care of all the tertiary, the side stuff. That aggregate route just cares about its behavior, right? And so these are facilitating that so that you can literally keep all your code clean, right? Your logics down there, your aggregate route, your factories are creating these things and your repositories are hydrating. And that makes it a little bit easier, at least for me,
Starting point is 02:01:31 to comprehend and know how all these things come together. So that pretty much wrapped all these, right? Yeah, I think it pretty much ties it all up. We talked about the lifecycle of objects, where they come from, where they go, how are they maintained. We gave a couple guidelines and talked about some right ways to do things and talked about some kind of overlap with some interesting patterns that we are already familiar with. Yeah, so we'll have in the resources we like section, we'll have several links to, there's some great Plurals site courses on this topic. There's, of course, the book itself by Eric Evans, as well as his site for this topic, domainlanguage.com. And then there's the dddcommunity.org.
Starting point is 02:02:18 So with that, let's get into Alan's favorite portion of the show. It's the tip of the week. Yeah, baby. All right, and I'm first this time, and I wanted to talk to you a little bit about SonarQube. It's an open-source static analysis tool that's easy to plug into your pipeline. It's so easy, in fact, that a lot of tools like VSTS
Starting point is 02:02:39 or even GitHub has some nice integration where you can kind of checkbox it if you want to run it. And it is an open- open source project but if you're going to be running on their servers then you're probably going to end up paying something but they've got really nice support for Java, C Sharp C++, even JavaScript however that works and it even
Starting point is 02:02:56 gives you cool stuff like debt estimates like we've talked about before with Ndepend and you can check that out at sonarcube.org Excelente Alright so I've got two today only because And you can check that out at sonarcube.org. Excellent. All right. So I've got two today only because one's really a tip and the other one's just some information.
Starting point is 02:03:15 So multiple stops on the same line. I just noticed this the other day. So Chrome debugger, if you crack that thing open, you put a stop point on a line. And in the past, if you had like object chaining where you had something dot something dot something dot something it would basically just skip over the entire line or just run whatever that last function was on the line right maybe or so if you were like f11ing into it it would typically just hit that last one well no let's let's let's be careful it would you would get one blue line yes and if you had like uh some object dot get method dot get method dot get method you would go into all of them but you couldn't get to the last one directly okay okay that's what it was
Starting point is 02:03:57 now it will actually put little blue arrows all across it at each one of the dots so that you can you can either skip over it or you can step into it or what it's just amazing or you can just move like whichever one is the darker blue is where it's going to its first stop is going to be and the lighter blues are the ones that it will eventually get to you can move the darker blue it's beautiful like yeah how do you do this so what this is in 2017 no no no this is in chrome developer tools chrome all right yeah dude it's sweet so if you put a break point in there his hand his response was like chrome who develops in chrome what's this thing no no it's beautiful so a lot of people will still do alerts and all that kind of stuff like you're really
Starting point is 02:04:44 selling yourself short use the break points and whatnot in, in the developer tools in the browser. If you're doing web development, I mean, I, the Chrome developer tools just get better and better like all the time. So at any rate, that, that was an awesome one that I just stumbled upon this past week. And then the other one that maybe some of you people out there will get excited about is Docker Linux images on windows. So it was actually released a couple months ago at Docker con that there is this thing called Linux kit that's being released for Docker that will allow you to run Linux based Docker images on Windows Server or on Windows. People are already doing it on Windows 10. So this will open up an incredible world of possibilities when you start thinking about being able to, I mean, Microsoft
Starting point is 02:05:40 has come a long way, right? The fact that they're even embracing this stuff, but there has been the ability to run Docker images in a hyper V setup, but that means that you have to have bare metal access to do it. This opens things up a little bit further to where you could even have a window server running in a VM and then potentially be able to run your Docker images in your window server that are linux based so i i wanted to share this because it's really cool they have i have the links to the github thing here that will give you directions on how to create these docker images that you can run in the various different places i i haven't really gone and played with it enough but I don't think it's 100% production ready yet, but super cool. That's nice.
Starting point is 02:06:29 Go ahead, Joe. No, all you. You mentioned Linux on Windows and it already being there maybe for Windows 10. And it brought back this thought related to the build keynote that came out about now your different distributions of Linux being available in the Windows store. Isn't that crazy? We've talked about the Windows subsystem for Linux. Oh, that reminds me. The laptops on the review, the thing that was annoying,
Starting point is 02:07:02 they both came with Windows Home you can't run docker on windows home it has to be on windows professional well it drove me crazy i tried to set it up so at any rate just know that if you're trying to do a development machine windows professional has all the features that you need to be able to do that kind of dockerization and linux and all that kind of stuff so you didn't just upgrade it? I didn't know which one I was going to keep, but I didn't want to go through that. Not for burner laptops. I thought you were just going to blow it away
Starting point is 02:07:30 and install Linux on both of them. Oh, man, too much work. Use that as the host operating system and Windows as the VM. KVM in it, or use ESXi. So here's a nice little tip for you. Shallow cloning with Git. So if you ever have to get like a large repository, sometimes you don't need all of that old history. So when you do your clone, you could just do a git clone dash dash depth one and then the repository URL,
Starting point is 02:08:08 and you can just get the most recent head of that repository. And it's going to be a much faster pull for you. Especially if you've got gigs of stuff. Yeah, that's nice. Yeah. Now, I will say that depending on your version of Git, this functionality was more limited in versions prior to 1.9. So if you are behind for some reason,
Starting point is 02:08:33 one, what are you doing? Upgrade. And yeah, so just know that. Excellent. I've got to say, though, I'm still in love with the idea of wiping your repository every year. So once a year, have a code forgiveness day. Get drunk.
Starting point is 02:08:48 Check in whenever you want. Get rid of all history. Bye bye repo. Yeah, that'd work well in large scale git repos like Windows. Alright, well, with that, we thank you for listening. Be sure to subscribe to us on iTunes, Stitcher, and more using your favorite podcast app. If you haven't already, be sure to leave us a review by visiting www.codingblocks.net
Starting point is 02:09:18 slash review. And while you're up there, check out our show notes, examples, discussions, and more. And send your feedback, questions, friends to the Slack channel, codingblocks.slack.com. And follow us on Twitter at codingblocks. Head over to codingblocks.net and find all our social links at the top of the page. I think Joe's being held up by his microphone right now. It's ridiculous. I was yawning at like 6 p.m it's because i had pizza man i broke my diet i had pizza oh you shouldn't have done that man it was good though it was
Starting point is 02:09:53 real good shame you're gonna have to take the walk of shame now just walking down the the uh the sidewalk shame hey your birthday was the second, right? Yeah. Did you eat cake and all that too? No, I didn't. You didn't? Dude, my birthday, it was bad. Yeah. It was bad. The way he's saying that, you just picture like there he is on the floor.
Starting point is 02:10:20 There's like cake all over his face. His fingers have icing of all kinds of different colors. He's just passed out from a sugar high. Were you there? It wasn't too far off. I'm still reeling from my bad ice cube impersonation. Oh, is that what that was?
Starting point is 02:10:42 What? I didn't know. It's his birthday coming up. Oh, is that what that was? What? I didn't know. What? I didn't know. It's his birthday coming up? I got nothing. Come on, man. Come on, man. I feel like, how is it that that album cannot be part of your history, man. It probably was, but I couldn't tell you anything about any album
Starting point is 02:11:11 that was part of my history, right? I mean, I know I made some mixtapes for some girls back in the day, but that's about it. Mixtapes? Yeah, man. Sit there in front of the radio for hours like, oh my God, this song's got to play eventually. Yep.
Starting point is 02:11:29 Man, kids got it easy nowadays. You want to make a mixtape, you just go to Spotify. No, they don't even do that. They just go to YouTube. You send a link. Man, we had to work for it back in the day. Here's a playlist of YouTube videos I put together. I mean, someone else put together, but it really in the day. Here's a playlist of YouTube videos I put together. I mean
Starting point is 02:11:46 someone else put together, but it really expresses my mood.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.