Coding Blocks - Software Architecture – Explicit Constraints, Processes, Specification Pattern, and more
Episode Date: July 10, 2017Know what Joe and Waldo have in common? We can't find either, as this week, it's just Allen and Michael to continue the dive into Domain Driven Design....
Transcript
Discussion (0)
You're listening to Coding Borbs, episode 63.
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 our 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 and find all our social links there at the top of the page.
With that, I'm Alan Underwood.
I'm Michael Altborb.
And I'm also Joe Borb.
I'm filling in.
Unfortunately, Joe is out this week.
So we'll eventually get back to a full crew and maybe
one more episode right i think the borbs got him yes they did this episode is sponsored by
fresh books the all-new fresh books makes ridiculously easy accounting software that's
transformed how freelancers and small business owners deal with their day-to-day paperwork
it's been redesigned from the ground
up and custom built for exactly the way you work. FreshBooks provides the simplest way to be more
productive, organized, and most importantly, get paid quickly. Getting started on FreshBooks is
extremely simple, even if you're not a numbers person, especially if you're not a numbers person.
Now when you email a client an invoice, FreshBooks
can show you whether they've seen it. This puts an end to the guessing game. The new notification
center is like your personal assistant telling you what's changed in your business since you
last logged in and what should be dealt with like overdue invoices. This lets you focus on what's
needed to get done and help you get back to your work
faster. FreshBooks is offering a 30-day unrestricted free trial to our listeners. To claim it,
just go to freshbooks.com slash coding, that's C-O-D-I-N-G, and enter coding blocks in the
How Did You Hear About Us section. All right, so let's get into the very first thing that we
always like to do, and that's the reviews, and thank everybody that's done that. So I've got
the iTunes reviews this time, and starting off, it's Polymorph Chrism, Vijay Dvuri, Sounds Need
Work, Brett Santori, and Bisrael Walter. So very. Thank you to you guys for leaving us nice reviews on iTunes and rounding out
the stitcher reviews still use for useful for JS,
which is an applicable name to this podcast.
It is.
So as always for the full show notes,
you can visit www.cuttingblocks.net slash episode 63.
We have incredibly detailed show notes, so go check that out.
We have a little bit of news this time, not a lot.
Actually, Chris S. wrote us, and we kind of glossed over this last time when we were talking about the aggregate routes and how to deal with certain things.
So the whole thing came up about if you had like an order processing aggregate route,
then you'd have your business rules in there, you'd control your invariance there.
And then Joe brought up the fact that, well, what if you had to process a thousand of those
things?
I just feel like it would be non-performant.
And I just kind of said, well, you'd probably create another domain for that, right? Like you'd probably have a different domain set of classes that you'd set up. And Chris was like, well, that's kind of interesting. Like, you know design is you can enforce in a way that makes
sense complex business rules, right?
So when I said that you could probably just create like another domain, like let's call
it order batch, right?
Or something like that.
You could do that, but I don't know that you necessarily want to get away from using the
other domain because you're going to have logging set up in there, maybe audits, you're going to have all kinds of business rules that
have to be enforced. So I guess in my mind, and I'm curious what you think is when he wrote back
about that, what I was thinking is you'd probably have a more efficient way of handling that kind
of stuff, right? So instead of just having a collection that you loop through,
maybe there was a way to where you did async calls to be able to handle multiple orders at the same time, you know, basically something to where you could do things in parallel.
So that's kind of what I was thinking was, you wouldn't necessarily want to repeat all that
logic because you've created it once, but you might create a more efficient way of doing things. Maybe it's not even another domain. Maybe it's just a, you know, some sort
of app that you've written that can parallelize that, that kind of thing. Yeah. I mean, if I
understand what we, what we've discussed so far, then really this would be the domain objects would be more about the way the expert.
What was the term for the expert domain users?
You know, the language that they would use.
Right.
So if they're not talking about orders in like these batches, right, or this list view
of them, then I guess maybe you wouldn't have a domain object for that
yeah does that sound so we're kind of like there's that line of like okay here here are the objects
that we just need to get the job done you know these are the mechanics of of the overall
application and then there's the the model that has the domain objects and this is part of the overall application. And then there's the model that has the domain objects. And this is
part of the ubiquitous language, right, that we're talking about with the domain experts.
And if they're not talking about, hey, I need a summary, an order summary, or order list or
something like that, then I feel like that just is one of the mechanics of the application.
Yeah, that's I'm kind of in that same ballpark because we've said it, I think, probably on just about every episode.
Domain-driven design isn't for everything.
It is for when you have complicated things that need to happen, right?
And they end up becoming spaghetti and unmaintainable over time.
And we're not talking about just because there were bad practices.
We're talking about because it's a complex domain. And so I think that whole batching
of orders or doing summaries or something like that, I think that's just another set of classes
that you might have in your application that can handle that kind of thing. Not necessarily domain
driven or anything like that, but just, you know, either workers, like if you needed to process a thousand of these things at a time, you literally write an
application that would take advantage of that domain that you've already done. Or like you said,
an order summary report or something like that. That's, I see that as a different entity.
Yeah. One, one idea that kind of came to mind while I was thinking about this was like,
um, in the case of let, let, let's go back to our, our canonical e-commerce kind of example here.
And so you have some warehouse, uh, and there are people out there that are fulfilling orders and
they're going through and picking all the items out and putting the orders together. And, you
know, they might work with a batch of orders.
So that might be part of, you know, that ubiquitous language
that applies to that specific need.
And this is where we've talked about how, you know,
different namespaces may have similar looking class names, right,
but serve different purposes and different features and functionality, right, but serve different purposes
and different features and functionality, right?
So maybe it wouldn't necessarily be for display purposes,
which is, if I remember right, that's where the email was coming from, right?
As it was talking about display, or that's where the conversation was,
at least at the time, when Joe brought up the 1,000 orders,
if I remember right.
Yeah.
Or at least somehow that got stuck in my head
that we were talking about it for display purposes.
And so, you know, I guess the answer is, yeah, it's not no, it's just maybe.
Right.
It depends on if there is another domain
or if you're just trying to aggregate some stuff to show.
Yeah.
So I thought that was interesting.
Oh, also along the lines you and i
worked on a project at one point several years ago just thinking about the whole parallelism
type thing like there was a we had a project where we had to process you know hundreds of
thousands of images right and there had been a process written that ran that took what four hours
eight hours i don't even remember it
was ridiculous well it depends yeah it might have been how many and by simply turning that thing
into something that would run in parallel using async operations because it wasn't something to
where you needed like image one to be processed before you could do image two before image three
they were literally one offs.
And so we turned this thing into a parallel thing and it finished in what,
like 20 minutes, maybe, maybe even less. I can't remember exactly, but you know,
that's maybe something that we need to do an episode on here sometime in the
future is just talking about thinking through problems in something more than
just a serial way. So anyways, that was an aside.
And then the next thing I wanted to say, and I bring this up because we do it at our job,
and I feel like it's highly useful. And it's be a thought leader in your company, in your group.
And I don't mean you go shout to the rooftops
about the way that things have to be done, but talk about the way that you're implementing things
and doing things, especially with your other team of developers, because A, people will learn things
that they didn't know. B, you'll learn things you didn't know. And C, you'll find out things about probably even the software that you're working on that you didn't know existed.
I know that when we're giving talks within our company, I learn things all the time.
Your thoughts?
Well, I like it.
But I don't know if I consider it a thought leader from that kind of perspective as much as I just consider it like simple knowledge sharing and letting others know within your organization.
Hey, here's some neat things.
Here's some neat tricks, some neat patterns that we have out there that exist that you can use too, or just even if you look at it from like the selfish perspective of,
well, the more people I tell about this thing, then the less I'm going to get hassled about it.
Right. Like I no longer become the, the single point of contact for that particular feature
or whatever it might be right now, there are more people that know about it. And so, you know, I can get a decent night's sleep or, you know, I can go to lunch undisturbed or whatever it might be, right? Now there are more people that know about it. And so,
you know, I can get a decent night's sleep or, you know, I can go to lunch undisturbed or whatever,
right? You know, I mean, your environment may vary, but I mean, that's kind of the way I think
about it. And if that translates into being a thought leader, then, you know, that's great.
But not maybe my primary purpose.
Yeah, I think by the thought leader, I just mean, if you guys aren't already doing something like
this to where you're sharing information, because I've definitely worked in groups where it's almost
like a bunch of silos. Be that person that steps up and says, hey, I think we should do this,
right? Like, even if it's a 30-minute thing once a week or once every other week, do this, right? Like even if it's a 30 minute thing once a week or once every other week,
do it because it will help people out and you'll find that your code will get better. You'll find
out that people stop repeating things as much because they didn't even know they were there
in the first place. Like there's just a lot of benefits to it. And then what will actually make
you feel really good about it if you haven't already been sold yet is you know that brand new project or a set of classes that you created that you're super proud of that's super awesome and does a really neat thing?
Well, if you tell other people about it, then they'll know to use it.
And so now it'll get more buy-in and more traction because now more people are going to start using it.
So now your awesomeness is known.
Yeah.
And it might even get improved upon if it's possible, right?
I mean, it might be so awesome.
Come on, Alan.
Come on.
You're saying the awesomeness has to be improved?
It might not.
It may be impossible to improve the awesomeness.
But yeah, so I just wanted to say that because I feel like a lot of times, you know, a lot of programmers just do the job and go home. Right.
And I feel like they can make their lives and other people's lives easier if, if everybody
would just kind of share some information. So, you know, that's all we have for the news.
Well, no, it's not. I got one more for you. Do you like money? How about, do you like $200,000?
A little bit.
Yeah,
a little bit,
right?
We all do,
right?
So we've talked about gaming many times,
right?
Dream hack Atlanta is coming.
Have you heard about this?
No,
I have not.
So,
I mean,
e-sports is now a thing,
right?
Like it didn't used to be,
but it's now a thing and it's a big thing.
And so this is, they're having the Halo Championship Series here in the Atlanta area,
July 21st through the 23rd. And the, if I remember right, the grand prize for the Halo Championship
is the largest prize ever of $200,000 for the team. That's ridiculous. It's going to be
awesome. Yeah. Hey, and our buddy Spoon Raker should check this out too, because they've even
got a Rocket League championship. I was about to mention that. Yes, they do. Yeah. So you need to
be in the Atlanta area. They're providing the consoles. You have to bring your own controller and your own, uh, USB micro USB cable for your, your Xbox controller.
But, um, yeah, it's gonna be awesome. And so not only are they going to have a Halo, uh, team-based,
um, you know, championship series, which is the way that the e-sports typically go or team-based,
uh, events, but they're also going to have a free for all competition, halo competition.
And I think that the, if I remember right, the, if I remember reading it correctly, the limit,
the prize for that one was like five grand or something like that. So, you know, big difference,
but still, but hold on, would you take five grand for playing a video game? I mean, come on.
Well, no, no, no, I don't. Don't. Hey, I'm not, don't get me wrong. It's amazing. It's amazing.
This can even be a thing. I'm just saying like, it's a big drop, like from the, you know,
the team-based prize to the free for all for a prize. Cause if you think about it,
a free for all match, man's hard that's that's kind
of rough but yeah so i'm really curious so yeah i'm gonna be i'm gonna be attending that definitely
uh this is gonna be fun to see and it's supposed to be like 24 hours if i if i understood it right
it's 24 hours a day for those three days i don't't know, man, it's going to be, it's going to be crazy. Yeah. So I might, uh, I might need some coffee the next day. That's fun. All right. So
now let's get into the meat of this. So continuing with this series, oops,
continuing with this series of talks that we've been doing on domain driven design,
we wanted to dig into some of the,
I guess, more detailed pieces of it. We've hit a lot of broad strokes and, and we've talked about
a little bit in depth, like about the aggregate roots and that kind of thing. And there's little
sort of just edge things that, that help make it all come together. And we wanted to hit on
some of that. So the first topic of order here is explicit
constraints. Yeah. So these are constraints. There was a quote that, that, uh, you know,
constraints can often emerge implicitly and expressing them explicitly can greatly improve
your design. And it helps to think about like, well, okay, what is a constraint though? Like, what
does that even mean? And I was thinking about this and like the most, the simplest example that I
could come up with would just be like a simple boundary check, right? Like if something's greater
than or less than, less than or equal, greater than or equal, something like that, right? Like
those are simple boundary checks. So we've all seen this, we have it, you know, you have it 1000 places in your code, where there's some if conditional
statement that says, if this is less than that, go do something, right? And, and maybe you followed
Uncle Bob's, you know, patterns there, his philosophy is there. And, you know, in that if condition, when it does go to execute,
you know, to do some other logic, it's a nicely named method. And that method, you know, is very
expressive about what it's doing. But you still have this constraint inside of your if that is right uh so the the idea here is all about let's give let's give that constraint also
some name let's name it which i couldn't help but think of like
game of thrones when when i was reading this part and i was like the constraint needs a name. It seemed fitting. I mean, this goes back to, it ties in just like you said about Uncle Bob
Martin, back into clean code. You know, take chunks of code and turn it into something that
makes sense just by giving it a name. And it seems so like, why do I need to do that? Why do I need to put, you know, if this is greater than 10, then don't do it. Well, what does greater than 10 mean, right? Like, having something that says, does overflow bucket makes a heck of a lot more sense than greater than 10, you know? Yeah, and that was another, there was a really great point that he made in the book
in this chapter where he was saying that like,
okay, by giving this constraint a name, right?
Now it's something that you can discuss.
You can talk about it with other,
with domain experts.
You can discuss it with other developers,
whoever you need to discuss it with.
It's now something you need to assess
because if I just walk up to you, Alan, and I'm like, hey, man, if I is less than 10,
what's your day like? Right? There's no context about that. That's meaningless to you. You have
no idea what we're even talking about in that regard. But if you're given an expressive name,
then you can. Yeah. And it's like they said, if you give it an expressive name, you don't have to care about the implementation, right?
Not unless you're having to modify that thing.
You can literally look at it and say, oh, I know what this is supposed to be doing to my model.
And at that point, that's all you care about. There was a statement that was made today at work that the cognitive,
there was too much cognitive stress trying to figure something out, like the way that something
was done in code. And if that happens, then you're going to create problems. You're going to create
bugs because if it takes mental exercises just to figure out a simple thing, people will make mistakes.
Yeah. And there was this kind of premise that he had in here, which kind of, in my mind,
went back to, there was a lot of parallels between this and Uncle Bob's clean code.
But by giving it this intention-re intention revealing name, he called it,
then, you know, other people will understand its purpose without caring about what its
implementation is. Right. You could just immediately see the name. You understand
conceptually what it does, what it's supposed to be returning. If it's supposed to be returning
something and you don't care to dig into it, you don't need to dig into it to find out like, well, wait a minute, what is this thing actually
doing? Right. And to take it a step further though, maybe you don't want to dig into it
because that's not what you care about. You see what it is, but maybe that is the piece you're
looking for. And now it's obvious, right? Now it's, hey, where do I do this overflow check? Check for overflow.
Easy.
Okay, I know that I need to go there.
And you're not sifting through lines and lines of code to find where this one logic bit is.
So either which way, right?
Whether it's something you can look at and say, okay, I can move on.
That's not what I'm looking for.
Or wait, that's exactly what I'm looking for.
Either way, you've saved time and you've helped the person out who's looking at the code behind you, as well as if you ever need to talk to a domain expert. And I think one
of the things that I really liked in this when he was talking about this stuff was he said,
a fundamental concept in model-driven design is that it's easy to see relationships in the model.
And so when you name these things and you give them explicit names and boundaries,
you get to see these things. It's easier to visualize. And that's important.
Yeah. And we've kind of mentioned this in regards to, you know, and maybe you'd have this as a
method in your class, but you could, if necessary, if these things are very complex or it's obscuring the object's main point or its main responsibility, you could factor that all out into its own individual class.
So maybe it's some kind of a validator type class.
I was trying to think of a real world example where there might be such a thing, and I'm drawing a blank.
I know there is one. The example that they had in
the book, and I highly recommend, like when I first started looking through this book, and I'm
going to be brutally honest here, like I felt like it was very verbose. There was just a lot of words
and it was easy for me to lose focus. As you start getting into the meat of some of these topics,
like these right here, he references back to certain things that start to kind of pull it all together.
And one of the things that he talked about was the shipping cargo, about how if you're a shipper, you'll take in, you know, you have X amount of capacity for your cargo.
Let's call it a hundred percent, right? What they'll typically do on shipping lines is they'll book more like 10% over what their capacity is because it's
inevitable. They get cancellations, you know, leading up to the time that the shipment's going
to go out. And so one of the rules, one of the things that they have in place is you can overbook
your capacity up to 110% or to 10% over.
And the way that they ended up doing this was by what you said,
they broke the class out.
So instead of, you know,
add cargo to your shipment and then having a bunch of if else's in that add
cargo thing.
Now they did,
they use the strategy design pattern and then they could just swap in like through DI or whatever, dependency injection, and swap in this thing that says, okay, you know, this is a cargo validator, we'll call it, right?
And as long as it's under was, the strategy pattern,
uh,
out on Wikipedia.
I think we've talked about it in the past.
Um,
but yeah,
I don't,
yeah,
I don't,
if we haven't done the strategy pattern,
I feel like we did.
Uh,
I think we have.
Yeah.
If not,
we should do that one.
Yeah.
I'm going to look it up real quick while you talk.
But he also gave some criteria so that you can determine how to know that your class is distorted by constraints or too many constraints.
How do you know when it's time to refactor that out? And there were a couple of quotes here that he has that I really liked where First is evaluating a constraint requires data that does not otherwise fit the object's definition
So if you have some uh going back to your your cargo ship example, like, you know is shipful
You know method or something like that and that method needs to reach out to a lot of other
uh types within your your system that aren't necessarily really related to that ship object, except in maybe this one particular case.
Then that's a candidate for getting that thing out of that class, right?
Right.
And reducing the dependencies of that class. If you have related rules that appear in multiple objects
forcing duplication or inheritance between objects
that are otherwise not a family.
We've talked about duplicate code before,
but now we're thinking about code duplication
as it relates to constraints.
I was just thinking of an example, like if you had a switch statement
or a bunch of if statements together, where you're trying to change something to decide,
you know, Oh, well, what type of object should you use? And we've kind of talked about in the
past, like, Oh, well, you should just use a factory, uh, instead for that. Maybe that's
like another example where, uh, you know, this constraint fits in, right? Like you're letting, you know,
in that particular case, the factory is deciding based off of some kind of constraint logic,
what kind of things should be created, right? Yep.
Another, the last one was a lot of design and requirements conversation revolves around the constraint, but in the implementation,
they're hidden away in procedural code.
I thought that was a weird one.
Cause I was trying to think of like a real example where like,
I mean,
I'm sure it's come up where we've talked about constraints,
but then not implement it explicitly.
Yeah. I can't come up with one, by the way, we did do the strategy pattern. but then not implement it explicitly.
Yeah. I can't come up with one, by the way, we did do the strategy pattern.
It's been a, it's been a minute. Oh, okay.
So I got a good reason for not remembering. Yeah. Episode 16. So if you,
yeah, if you want to go back and listen to it, that that's been a while back, it's in the backlog, you know, but it will help. And again,
we will have a link in the show notes.
So processes as domain objects, right?
So should we have procedural code in our model?
Yeah, right.
Well, not exactly.
So the easiest way to think about this one, this chapter was to think of a service,
right? Like we've talked about in the past, like microservices have come up in conversation before,
you know, web services, like, you know, having that service in your system,
which, you know, may be small, may be big, but whatever that is,
could be an example of your process as a domain object.
And by having that service explicit like that,
it allows you to express that process explicitly and encapsulate its complex logic within it, right? And so nothing else needs
to know about how that process works except for that service. Yeah, I mean, the whole key here is
when you're doing your domain model, you want to make sure that you, there's been a lot of talk
and a lot of what we've read, it says that you don't want an anemic model,
meaning that your model needs to express what it is,
what it does and all that.
And so this is a key part of it.
You want to make sure you keep that stuff in there.
What do we got up next?
Oh, make the algorithm.
So what if it can be done in multiple ways?
You can make the algorithm or a part of it, its own object, right? Which that almost goes back to what we were talking about with strategy pattern before, right? Break that thing out.
I'm sorry.
No, go ahead. Well, I was trying to think of an example, like when I was going through this, this chapter in the book, and when we got to this section, I was trying to think of like an example in, you know, I mean, we keep harping on this e-commerce as our canonical reference,
our canonical example here, but I really felt like the credit card processor kind of fit here,
right? There's, there's this payment process that could be a service, right? And there's multiple
ways that that thing could be done, right? And there's multiple ways that that thing could
be done, right? And depending on whether or not it's a credit card payment or a PayPal payment
or pay by an Apple Pay or Samsung Pay or whatever, right? Each one of those could have their own
complexity about them. And each one of those processes are a different strategy that you don't want them tied together.
It's kind of like your peanut butter and your chocolate.
You don't want it mixed.
That's kind of how your PayPal logic goes with your credit card processing logic.
You want to keep that stuff separate.
I think I got that right.
I don't know, man.
If you ask my wife, she might argue with you about the chocolate and the peanut butter. But I think the reason why it's easy to go back to the e-commerce thing,
though, is when we talk about domain-driven design, it's for complex business problems.
And e-commerce systems are incredibly complex, right? Even like you said, the payment instruments,
we've both seen it. A lot of
people have seen it. If you have, if PayPal, then do this, if credit card, do this, you need to be
thinking about refactoring that because at some point, as Michael said, now you've got Apple Pay.
Now you've got Samsung Pay. Now you've got Amazon, now you've got, you know,
what other type of payment instruments are you going to put in place? And how incredibly
impossible is it going to be to maintain that code over time?
Yeah, in the e-commerce world, I mean, we keep using that as the canonical reference,
but it's also, it's easy, I think it's easy for us, for everyone to be able to conceptualize because we use it every day
you know yeah or well i i probably shouldn't but i've seen our slack channel people people are are
as bad addicted to it as we are especially amazon so yeah so how how to tell when a process should be made explicit, right?
Yeah, I like this one.
The whole, you know, do domain experts talk about the process?
That's key.
That's, I mean, that's almost calling it out.
If somebody that's not a developer is telling you, hey, we need this particular blah, blah, blah to be done, then you can say, oh, okay, that needs to be something that we call
out in our model. Right. And this goes back to the ubiquitous language. If the domain experts
are specifically talking about whatever this process is, you know, like the container ship
being full or not, like then putting a name to it makes it clear. It's something that you can
talk about.
And clearly it's important
because they're already talking about it, right?
So don't try to hide it.
And this was a simple one.
This question about how to tell
when the process should be explicit,
there's two choices.
If they talk about it, make it explicit.
But if they don't,
and it's just part of the overall mechanism of your application,
then keeping it hidden within that model is not bad.
Maybe even preferred.
Yep.
Because then it won't confuse anybody when they go to have that conversation.
The ubiquitous language won't be muddied up at that point.
Right, because the last thing you want to do is talk to a domain expert trying to get more
information. And you start bringing up a conversation about something that they have
no clue what you're talking about. And it's just a deer in headlights. Look, that's not helpful to
anyone. That's never happened. I'm pretty sure I may have explained something once or twice or a thousand times.
This episode is sponsored by Airbrake.
Hey listeners, do you hate spending time checking logs, running ad hoc queries, or searching your emails for clues on production support issues?
It's especially bad when the customer tells you about the problem.
If so, then you
should take a look at airbrake.io. It's a service for alerting and monitoring so you can proactively
address issues and spend less time playing catch up. Airbrakesupports.net and all the major
programming languages and platforms which you can see on their GitHub page. There's a free trial
which thanks to your feedback, no longer requires a
credit card number. So you can check it out risk-free at getairbrake.com slash CB. That's
getairbrake, A-I-R-B-R-A-K-E.com slash C-B. All right. So let's talk about the specification pattern. I'm fond of this one. Really? Yeah. So a little funny story
about this one is I don't remember what I was looking for. I, I, I might've just been flipping
through the index or not the index, the, the table of contents. And I wanted to know implementation strategies, right?
And I came across these things and I read the specification pattern
and I was like, I can use that right now.
So I don't know if you recall or not,
I sent out a tweet late one night when I was sitting there looking
how do you validate things properly in a model
or in an object or in a domain? Because that's one thing that's always bothered me is just
validation practices usually suck because there's not enough information for you to really be able
to do a good validation. And I tweeted out something that Martin Fowler had said that was something along
the lines of, you can't do validation in a vacuum. There has to be some context around it. And it was
one of our most retweeted tweets ever. And I guess it's because it rings true with a lot of people,
right? Like it's easy to inform validation on something, but when you're trying to validate
something that's complex, you know, what might be valid right now, isn't valid, you know, 10 seconds from now, or if something changes just slightly,
right, it might have totally different rules. So this particular pattern I'm, I'm excited to talk
about. So, so let's talk about how things are typically done because kind of how going back to the
how we did things bad episode, this is something that I see that you'll typically find in your
code is you'll have this class with some complicated validation of business rules and you'll start
baking that into all the methods in your class, right?
Like if this, then you can't do this. If you right? Like if this, then you can't do
this. If you're this kind of user, then you can't do that. If you're this kind of user,
then you can, and it just starts getting incredibly messy and it's hard to reason about.
And so then what, what people will do is they'll think about that and they're like, well, this is
muddying up my class. So let me bring it out a layer, right? And then you pull it out a layer and you say, okay, now I'm going to validate all these
objects down below it.
So you pull these things out, but now this creates the inverse problem in that now you
kind of have this bag of properties, which is what we call like the anemic model, right?
You have almost like this DTO at that point where there's no logic in it.
And so it might as well not be much more than just a simple POCO or POJO or whatever your
language is.
And now the problem too is, is your model is not expressive.
What you said earlier when we were talking about the explicit naming and all that kind
of stuff.
Now you literally just have properties that mean nothing other than the fact
that they belong to this object. And that is how people typically do things. Did you think though,
the way, like the way you first described that though, it made me think back to aspects though
at first, like it almost, it almost sounded like that's the direction we're going. Cause you're
saying like you have this class, it's got a lot of complicated validation or business logic in it and you know you have this stuff this these
this validation and business language sprinkled throughout the methods within your class
and you can't reason about in it right so like these methods are unreasonable or you know
unreadable and it really made me think back to like, oh, well, we're talking about aspects, right? Because that's the same kind of like sales pitch for an aspect, right?
Maybe, except I typically think of aspects a little bit more generically, right?
Like a logging aspect or a retry aspect or something like that.
Something that's not aware of the domain that it's working on, I guess is how I typically think of an aspect,
something that's more of a cross-cutting concern. Whereas, you know, if you think going back to this
whole ordering processing type thing, if you have a customer service agent that's working on a
particular order, there's certain things they can do that a user can't do, right? Like they could
modify the price of an object.
Well, in a class, you might have this thing that says,
if user type is customer service,
then they can modify the price of the object up to 10%.
If the user is of type customer service manager,
then they can modify the price up to 20%.
If the user type is just a person ordering, then they can't modify, you know, and you have all
these if conditionals, and I don't know that that fits into an aspect, you know? So I see these more,
more, um, maybe class specific, whereas I view an aspect more of, Hey, this is truly a cross
cutting concern. This is something where I want logging all through my system, or I view an aspect more of, hey, this is truly a cross-cutting concern.
This is something where I want logging all through my system, or I want retries, or I want
null checking, all kinds of things. So I always view aspects as more generic and general
use-based type stuff. So at any rate, yeah. So that is in my mind, that's how I've seen things happen.
That's how I've done things throughout my career, right? Like let's try and get some of these things
brought out a little, a layer so that, so that we can get some of this nastiness out of the
business object, but then it kind of turns a business object into this sort of dumb thing.
Business object into a dumb thing.
Yeah, it really does.
So this is where you start seeing these key things is the business rules do not fit the responsibility of any obvious entities or value objects.
And that's a quote out of the book.
And that's so true. When you start seeing these things,
like so the order processing thing,
what I was just talking about,
or the like modifying the price of a product,
you might be in the order class,
but now you're looking at the user, right?
Like that doesn't necessarily have anything to do
with the order class or the product or any of that stuff.
And so now you've got these, these jumble of things that, that it's reaching out outside of what it typically does to get more information. And that, that kind of leads you to believe that
this, Hey, this is not part of my entity or any value object I have.
That make a little bit of sense, I think, hopefully?
I know I'm personally a little bit lost on, because like where the, okay, so there, let
me back up for a minute.
There was a definition in the book for the specification that states that a specification
states a constraint on the state of another object which may or may not be present right yes and so using
that as the the building blocks let's go from there as it related to your your order example
because i kind of got lost in the order example because i was thinking like immediately i was
thinking like oh god why would you have that in the order class? No. Yeah, I agree. I guess what I was thinking was, you know, typically, I guess to sort of bring it back
around. So it will make sense for anybody else who might be confused is, you know, you have an
order, you place an order as a customer, you can't go modify the price of a product right before you
place the order. But let's say that there's some sort of problem with your order,
the customer gets it, you can call up customer service, and the customer service representative
might be able to go into your order and knock 10% off the price, just because you had a hassle,
right? But you're really mad and you want to be escalated to the management of the customer
service department, and they're allowed to give you up to 25% off to the management of the customer service department and they're
allowed to give you up to 25 off so that's kind of how i was thinking about it in terms of the
order was just you know the customer placing it versus what somebody internal in the company can
do if you were to call up about that same order so the the world use case of, of what that was that tied in a hope.
Yeah.
The weird thing about this though,
is like,
I was trying to think of like,
what's a real world example of,
of the specification pattern that we,
we see that we use every day in our code without realizing that that's what it
was.
And I couldn't come up with any.
And when,
when I look for like examples of
specification patterns, it reads more like part of the predicate of a SQL query. But yet my
understanding from the book was that querying is not, specification is not querying.
No, it's not. But so I'll see if I can explain this a little bit better. I had not seen this
in practice, by the way, before I'd come across it in the book. And before I'd actually implemented
it on my own, I hadn't seen it used like I've, as long as I've been programming, I'd never seen
this particular pattern used. So basically, the gist of it is this.
You take, you create a specification class and it's going to extend an overall generic type specification that can be and, or, or is satisfied by, which is what you were talking about, the
whole query looking language, right? The and and the ors. So the general case is when you have this
specification, it can be made up of different heterogeneous objects, right? So in the case of
the order that I was talking about, you could have literally a user, you could have the order,
and maybe you even have a product. And the problem is those are three different things. So this this particular specification or this test, this validator doesn't really belong in any one of those. So you break it out into its own. And then what you can do is you can like typically what they'll do is they'll create a factory that will generate these specifications for you. And then what you can say is, all right, this specification is satisfied by, and that's actually a method call on it.
And then you'll pass in your order object, or you'll pass in the customer object or whatever
it needs in order to make this specification be able to work. You pass it into it and then it will return you back a Boolean.
So, um, you know, you say, Hey, is this thing spec or is this order is satisfied by, so can increase 10%, right? Let's say something like that. Let's say that you have can modify order
value by 10%. You might have a specification for that.
And then you'd have a dot is satisfied by.
You'd pass in the order and potentially the customer or the user who's doing it.
And it would tell you based off the information that's passed in.
It would do the check to see, are you a customer service agent?
Yes or no.
Is this order available to be modified? I mean, there might be checks
inside that specification that say, hey, it couldn't have been modified previously or
something, right? Whatever the business rules are. But that is a specification pattern. You
literally have a separate class out there that is doing the validation checks against whatever you
can give it. Does That make any sense?
I literally have not seen this in the wild before until I,
until I went into this and I actually found some people who had done some
open source things to where they make it kind of nice.
Like there's a, there's a C sharp version of it.
I think on code project where not only do they follow that,
that particular pattern with ands orss, and the is satisfied bys,
but they allow you to do fluent syntax as well. So there were some nice things there.
And to pile on on top of this, so the is satisfied by makes sense, right? That's basically saying,
hey, did this pass the specification or the test? And you'll get back a true or a false.
Now this whole and or or
thing, and it meant I'm jumping all over the place here as far as our notes are concerned.
There is, okay, so there's, there's three purposes of it. There's this to validate that an object is
ready to fulfill some need. That's what I just talked about. The dot is satisfied by.
And that seems to be a naming pattern that's used pretty much whether you're in Java, C Sharp, whatever.
The other use case, there's two other ones.
There's one that is to select objects from a collection.
So let's say that you have a bunch of items in a collection. You can use this specification.
You can say dot is satisfied by
condition one and then dot and, and then use another specification. So one of the samples
that I saw, I think on that code project thing is they had mobile phones, right? These mobile
phones would have manufacturer like Samsung, LG, Apple, and whatever else. And then they had
properties, things like was a smartphone or was just a basic phone. And so the specification tests
that were created were things like, is Samsung? That would have been a specification. Another one
was, is smartphone? Could have been another specification. Another one was, is smartphone, could have been
another specification. And then that way, when they wanted to pull items out of a collection,
they could have an entire collection of cell phones. And then they could say,
is Samsung is satisfied by, and then pass in the collection or the phone from the collection.
So you're basically iterating over the collection. You pass in the one item from it. It'll say, yeah, it's satisfied by it. It's
a Samsung phone. Yes. It comes back true. And then you do a dot and, and say, is it a smartphone?
And then you pass that into that as well. And it comes back. Yes. And so basically you're getting
this chain of Booleans. And if they all evaluate to true then you could basically take that and say okay this is what i'm looking for i'm looking for
smartphones by samsung and so it's a way to to sort of have these explicit ways of saying pull
things out of the collection that meet all these specifications i'm looking for but this is where
this is where i had confusion with this part of the book though. Because going back to
what I said a few months ago about specification, this is not part of querying. But yet the example
that you just gave kind of sounded like, okay, we're trying to query these objects to determine
if it's a smartphone that's made by Samsung and has a touchscreen or
whatever, right? That sounds like querying. Yeah. And when I think specifications, I think about
like, hey, I want to build a house. I need the specifications on how to build that house. Right. So when I think about
the, the, the term specification doesn't necessarily, I don't think about, you know,
querying something either. So like the terminology was kind of throwing me off.
Yeah. I think specification here is, does it meet this criteria? So I guess the reason why it sort of doesn't blow my brain up is when
you look in a lot of like, uh, when I was doing some angular app stuff back in the day, uh, there
was one, I think it's, uh, it might be Jasmine. I can't remember what the test framework is for
JavaScript, but basically you name your test specs, right?
And that is, it just kind of made more sense to me for that reason.
Wait, you're talking about Cucumber?
No, no, this was a JavaScript one. I think it's Karma with Jasmine, but they name their test.spec, right?
.js or something like that.
So the specification is literally just saying, does this meet the specs, right?
That's really all it boils down to.
And so you can use it to query out of a collection by just saying,
are these specs satisfied and these specs satisfied or are these specs satisfied and these specs satisfied or these specs satisfied. And then that way you can get that item out of the collection based off your
criteria. And so it's literally, if you think about it as specs, as you know,
so it's a tester is what we should, how we should think about it.
It's not for querying objects out of something like a, you know,
a database or a list or some in-memory collection.
But it is a tester that can be applied to that list.
Yes.
And there could be all kinds of crazy business logic in it, right?
And that's the thing is it hides that complexity in the spec itself.
But like you said, you're not querying out of the
collection. You're going through every item in the collection and checking it against each spec
that you care about basically at that point. Right. And so the whole and or and the ors that
you can do in the in the specification is, is just like a query clause.
If this meets this spec and this spec and this spec,
then you can do something with it if you want.
And you could even or it to something else and say,
or if you're a super user, then you get it.
Well, another part of the value that I understood, though,
from that was the ability to chain these together.
And that's what I'm talking about.
So like and, dot, and, dot what i'm talking about or dot and dot not
yep yeah exactly and so i'm going to i actually found the page there is the c sharp project that
i was talking about that they have it's excellent you probably have to sign up or put in some sort of account
information to be able to download the code but in there they have the entire class layout to
show you the specifications and this is where they had the mobile phone example stuff and their
examples that they have in the code is really easy to follow oh is this the code project when you
said yeah um let me put this i got it right here, you've got it as well. All right, cool. Yeah. So that if you download
that code, it'll make a heck of a lot more sense because inside there, you'll actually see where
they do the chaining. And again, it's like you said, they're not querying out of the collection,
but they are testing items in a collection. And then if it passes all those tests, then they do something with it, like maybe add it to a new collection.
It feels like this is where when we talk about like a SQL statement, right?
And, you know, technically that select part, that's the query part.
And once you get to the where part, now you're into the predicate territory. And so like, we're kind of splitting hairs here because this is, uh, this specification pattern is in the
predicate territory of that SQL query. If we were to think about, you know, use that as an analogy
here, right? Right. Only difference is you can't create the collection from this thing like that.
It won't work right where the SQL query is actually creating your collection based off all the stuff that you provided.
This will just allow you to test items in an existing collection that you already have.
So that's really the key difference there.
And then there was one other thing here. with the constraints and I had to bite my tongue was, you can use it for specifying when creating a new object for a specific need, right?
So you could use a specification to determine whether to create one type of object
or another type of object.
So it's a similar type thing based off business rules.
So instead of burying a bunch of complex business logic in a factory, maybe
use some of that logic in a specification that can be used to create an object. So those are
the three use cases. I think probably the first two are the most common. But again, I've never
seen this in the wild. It was something that I was really excited to read about
because I actually had a situation where I was like, I can use this thing and I did implement it.
So we talked about, you know, dumb objects a little bit, right? Unfortunately, in one of the
projects that I've worked on, there's a lot of DTOs, a ton of DTOs, and they're literally nothing more than mappers from a table, right, or a stored proc or something like that.
And the problem is I needed some logic around some of the flags and some of the features on this DTO.
I didn't want to code that information into the DTO. I think we even talked about on the previous episode
that, you know, there's ways to, to sort of push it forward to where it's not so bad. So for
instance, you make all your, all your sets private, and then that way you can't mutate the state of
that thing. In order to do that, you'd have to create methods on that DTO, but then it's no longer really a DTO, right? Now you're turning it into some sort of model that's got some
knowledge. But my problem was the DTOs have a lot of information in it that I don't necessarily
want wrapped around with business logic, because now you're trying to maintain state on something
that anybody can jack with. I didn't want that.
So what I ended up doing is I created like a mini domain object that wrapped, adds the DTO as a property to it.
And then I have these specifications that I defined that take in a user type and the
other data I needed.
And then I can make decisions based off, hey, does this user have super user rights?
Does this user have this right? Does this user have this right?
Does this user have this right?
And then that way I could toggle some of the flags on this DTO using the domain wrapper.
So essentially the business rules live in my domain thing.
And then it modifies the properties on a DTO and then hands it back.
Like people can say, hey, give me the DTO back.
And then it'll have all the data set. And that was kind of my stepwise way into getting into a state
where this thing's more maintainable, because if I had gone about it the other way, it would have
been that nasty mess of, if the user can do this, then toggle all these flags. If the user can do
this, then toggle all these flags. And you just get into this nasty mess of if else, if else, if else. So yeah. And it's hard to visualize because it's not
a simple topic, but I hope if nothing else, you'll go Google this pattern or click or come to our
show notes and click the links and download that sample code and see it because it really will clear it up. And you'll go,
I cannot believe I've never done validation or,
or checking this way before because it's just so easy to follow.
Yeah, this was one. I still, I'm going to, I want to dig back into this i'm gonna dig into this
code project to try to better understand this pattern because it sounds like a very neat pattern
but yeah there was another statement where it was talking about using factories to create or
configure the specification and then that way your factory will know of these sources or these dependencies,
you know, let's call them what they are, right?
And you can keep the rest of your domain clean.
But then when I think about the specification in that term,
then it kind of doesn't jive with what you were saying about like the you know it being part of like this this
predicate to like how you're going to test a some other object right so so it works that way because
what you'll do is you set up your factory and let's say that factory takes in two different
types of objects
no matter what type of spec that you're trying to create maybe the user object because it's
going to have different you know privileges that it can do and then maybe your order object let's
just keep with that so you'll have a factory that could create a ton of different type of
specifications right like can modify order price, can drop shipping
charges, can, um, can get free shipping, can do whatever, right? Then that factory, if, if you
need to check for any of those, then you might say, give me a, uh, free shipping spec equal
factory dot get free shipping spec. And then you pass in the user and then the order.
And then you might also say, hey, give me a discount spec.
And then you pass in the same things calling that factory.
So think about it like you have your variable declaration set up.
So you have var spec one, two, three, four.
Those were all done calling the factory.
Then down below that is where
you'd actually use them. So you'd say, you know, go ahead. I think, I think I just had an epiphany
that came to me. I'm sorry. But I think it started to make sense because then in that example with
the factory, what the factory could be returning would be just a simple DTO or in DDD speak, this would be a value
object, right? That, that represents, um, some piece of data. So going back to our canonical
e-commerce example, uh, a tax specification. So you might pass in here the items that that are in the cart.
Here's the billing address. Here's a shipping address, right things you so you have a bunch
of different sources of information. And then this this tax specification factory
would take all this different data and it could return back a tax specification
like this is what maybe but the point being is that like it's it's it could return it could
it's taking all this other data and it could return back it's returning back
some other object that's just a simple value object just simple dto there's nothing there's nothing
crazy about it there's no logic in it you know it's not it's not yeah no because it's not returning
back a value object it's actually returning back your validator your tester so the tax thing is a
little bit hard because typically if you're thinking about that you're
saying hey what tax rate am i going to get that's not what the specification objects do
those basically return you back bullions is satisfied by is the primary method that comes
out of a specification object so you might say is taxable right Let's say that you have a taxable specification.
You call your factory, you pass it in the order, the address, the items, you know,
you pass in all those things, then you're going to get back a taxable specification.
And at that point, you'll say is satisfied by, and then you'll pass it in, um, you know, the order or something. Um, so basically
it's your tester that you're getting back from the factory. And then you can apply that to any
order you have, right. That, that meets those specifications.
It's not a value object though, because it does have logic in it. This is satisfied by
is your business logic to determine whether or not it's
true or false when you call it.
But I don't want to belabor it too long. Cause it's probably,
if it's confusing you, it might be confusing other people too.
Well, yeah.
So it definitely sounds like some, a pattern and like i said i i want to dig into this
code project one and better understand uh what this thing is and how how i could better use it
though yeah it's it's what it's truly one of those things that without seeing code it's a lot harder
to visualize but if you do go to that
code project one, whether you're C sharp or.net or Java or whomever there, the code examples
in that link are excellent and they're super easy to follow. And if you're familiar with any type of
OO, you'll be able to, you'll be able to go along with it and see what they're doing.
Cause see here, here's where like this whole section of the book kind of felt contradictory to me because like there's a,
cause as soon as I thought like I was starting to understand what the specification pattern was,
then something else would come along and like, oh, well it's, it's totally not that. So,
you know, we talked about it not being query related, right? Like, and there was this,
this, uh, section in the book where it's talking about what the
specification isn't, right? And it says that it's not a filter for pre-existing objects, that's
querying. And it's not a test for an existing object, that's validation.
So you see my confusion on it? When I saw that that i was kind of confused by it too because really
in the examples it is it's does it meet these requirements right and that is validation to it
i guess you got to draw the line between validation right like his first name required or is it not
that's slightly different than are you allowed to do x y and z because you
have these privileges and i think that's that's i i don't know if it's a semantic thing that they're
that they're trying to do there but but yeah this was confusing to me when i saw both of these points
especially when you see how it's used yeah Yeah. So again, what is it?
It is a whole new object.
We don't have it.
It is.
And I, so just for the record,
I plan on doing a YouTube video to kind of show this from beginning to end
and the different uses for it so that it will make a little bit more
sense because I honestly this is one of those patterns that when I saw it I was like this is
super valuable because it can really clean up your code and that was to me that's almost one of the
most important things if you could it's like we talked about earlier if a developer has to really
you know like crawl through code then then it's too complicated, right?
And this can simplify things.
So what is it?
It's a whole new object or set of objects that are created or configured to satisfy a specification.
A specification is nothing more than a test.
Do these things all, you know, do these requirements line up for this particular use case?
Oh, so, all right, this kind of, now that I've gone through and confused the heck out of you,
and hopefully this will be clarified.
Well, that didn't take long.
No. This brought something to me though, that, that I find myself struggling
with and I'm sure a lot of people do. And I, and I want to get your take on it. This whole,
do you put your business logic in your database and stored products or do you put it in your
application and why? I mean, I feel like we might as well talk about tabs versus spaces
if we're going to get into this holy war.
I feel like we need to.
I think that this is worth the small holy war that it will create here
only because the tabs versus spaces is a preference thing.
There's not a ton of value to be gleaned from. If you watch Silicon Valley, you would know that it's an efficiency thing. There's not, I mean, there's not a ton of value to be. If you watch Silicon Valley,
you would know that it's an efficiency thing because it's one tab.
I love that. I totally forgot. I think, I think it depends on who you ask this question,
what the answer you're going to get. If you ask a data engineer, then they're going to come back and say what they know best.
They're going to talk about their wheelhouse,
like what's comfortable to them.
And so their answer is going to be like,
well, let's keep this logic in the database, right?
Are you a data engineer?
And, well, no, but that's beside the point.
So now ask me if I'm an application engineer. Are you an application engineer? But that's beside the point. So now ask me if I'm an application engineer.
Are you an application engineer?
But that's beside the point. So if you ask the application engineer, they're going to feel more
comfortable in that because that's what they know. That's what their wheelhouse is. I think
there's something to be said that there isn't a one size fits all. There's different types of business logic. So
there might be some business logic that's just related to the data and how to get the data and
things of that nature that seem like a natural fit in the data storage tier. And then there's
other business logic that's, you know, maybe more broad in scope related to the application or the application's function
that belongs in that set of code. So I don't feel like it's a one size. I feel like it's a both.
Now, again, I'm neither an application nor data engineer, so I could be completely wrong.
That's so I do want to probe a little bit further here. And I just realized I never hit the record button on the video recorder. So there will be no YouTube version of this one.
Or there can be, and it'll just be hand drawn figures of us.
Oh man, I hate that. Um, so I wonder, let's, let's see if we can take it a step further.
All right.
Let's take it to a complex business rule to where can somebody modify the price of an item?
Where should that logic live?
Should that live in your application? Should that live in your application?
Should it live in your database?
Just you, what do you think, where's the right place to put this?
Or even order processing, where does that live?
Does that live in your application or does it live in your database?
And I have my thoughts and i'll share
them i mean the order processing one is definitely like wait what are you calling order processing
now if we talk about the the the very minute very first question you know very granular first
question which is about it's basically a permission issue is what we're describing. Like where does the permit,
who owns the permission, right? We're talking about changing data.
It could be more complex. So just to be clear, it might be that you can only modify if you're
a customer service agent, it might could only be modified if it hadn't been modified before.
It might could only be modified if it's not a certain type of item, right? Like there could
be tons of business rules, but that's what I want to say is this is a complex problem. Where does
that live? Does it live in your database? Does it live in your application? So as soon as you started
bringing in other business rules that were like, okay, if it hasn't already been edited, if it
hasn't, it can only be changed once, things like that.
It, it kind of felt like now your business rules were getting into the application tier.
Right. Like I was on the fence when it was just like a permission thing.
And I was like, oh, it's a, this is a great trick question that he does. He got me. He, he,
dang, that was great. How he did that. I didn't even see it coming but but then yeah it kind of felt like it was leaning more towards the application tier so here is my biggest problem
with this is if you had asked me five years ago maybe i would have said database why because
anybody that needs to bulk update things,
they need all this stuff to be able to happen in the database.
My biggest problem with that now, it's actually twofold,
is one, databases typically don't scale very well, right?
That's one big one.
And we know that when I write applications,
I want them to be used by 10 billion concurrent users at a time.
That's a given.
That's in every one of your specifications.
That's where we first learned about the specification pattern was number of
concurrent users. Yes. All of them.
Yes. All the world. Thank you.
But then the other thing too is outside of scalability,
performance and sometimes context doesn't exist in the database, right?
The user of your application has a particular context. It's somebody that's logged in. It's
whatever. It's in the application. Are you going to funnel all that stuff into your database to
where now it can somewhat be cheated, right? Because you could call a stored proc and pass
it whatever the heck you want. And if somebody could figure that out, then they can sort of cheat it. And
it's no longer a black box. It is just something that you can plug whatever you want into it.
Another thing that I don't like is most of the time, and I know there's ways around this,
but a lot of the time your business logic is wide out in the open may not be a great thing.
But then the other thing too is, and one of our friends that we work with said this,
and I completely agree with it.
You cannot think of databases like you do with,
with object oriented programming.
Typically,
if you try and make something reusable,
you come at a major performance cost in your database.
You can't,
if you apply some sort of scalar function to an entire query,
it has to run that function for every single, you got 10 million records, guess what? It's running
it 10 million times. And it's not efficient at that. It is a set-based system. And so like when
I started thinking about this stuff, I'm like, man, it really makes more sense in the application.
Why? Because you can scale it. If you need to reuse it,
it's easier to reuse, right? You can just plug it in. Now, some people argue, well, if it's in
the database, you can just call it. You got 20 parameters past this proc. How do you fill that
thing in, right? It sounds like one of the things that you're saying then is that one of the
decision criteria is if state is involved in the decision making then it's in the application tier i think that's don't try to
transfer your state into your database this the database should be stateless everything that
happens there should you know just run on sets stateless and be done yeah Yeah. I think that's a pretty good rule of thumb for me.
I think, I guess I've just gotten more and more as time's gone on.
I've really seen more value in having that stuff live in an application that's somewhat easier to reason about. And also, like I said, it's easier to scale. If you want to, if you want to spend
that thing up on 10 other servers, you can, right?
And if you have a thousand different things that you need to process all at the same time,
you could potentially spend up a thousand different servers if you wanted to each do
their own thing.
You can't do that with a database.
And oftentimes, it is way uglier to look at your dynamically created stuff in a database
to figure out how all these
pieces fit together. You know what I'm saying? So I thought it was an interesting thing because
this whole specification thing is literally doing your validation, even though it says not validation
checks, but it's doing your, your requirement checking in the application. So you've now taken
that away from your, your database. So if you wanted to
process that same type of information in a batch, you wouldn't be able to necessarily just do it in
a SQL statement, right? You'd have to leverage the code that you've written that have all these
specification tests. And that's why I brought this up is because it, this kind of does say,
no, you're choosing a side
and you're choosing the application tier.
Yeah, I'm trying to think of a good example, though,
where you need to operate on large sets
in order to make some determination
or to set something.
Oh, I give you a perfect example. You wouldn't want to do that in code, right?
And so kind of the one example that was kind of coming to mind here
is that like if you were going to do score percentiles on all of the tests,
all of the scores of students in the United States, right,
that's a lot of data and you don't want to like loop through that.
And in order to do this, the percentile scoring,
you want to do it on the set,
the data set across the entire population of scores that you have.
So that kind of, you know,
business logic would be in the database.
Could be, but so check this out. There was, there was a,
a thing that happened, you know,
in the past where customers needed to get refunds of certain amount for it,
like coupons that were applied wrong. And so you have,
let's say 5,000 orders that needed to have certain refunds run.
Well, you could do it in the database, but then you're missing out on all the logic that was in
your application that would do your audit trails, your logging. And it might've known about things
that the people in the database thought that they knew about, but they didn't, you know what I'm
saying? And so by, by writing a SQL script to do that kind of stuff, you're missing out on all those
pieces that add up that, that your application gave you for not for free, but, but it's already
baked in there, right? That's where it already was. You try and port that stuff over to the
database. You lose your logging. Let's say that you had things that were logging out to files on a disc for your audit trails. You're not going to get that out of your
SQL box or, or you're already BMS. Like there's a lot of things that don't happen. Like you were
talking about aspects, right? Like this try three times thing, like you need to call your credit
card processor and issue the refunds, you know, that becomes way more difficult, right? So then let's restate it this way then.
So we said that anything that involves state
goes into the application tier.
And let's say that anything that might be simple CRUD,
you keep in the data tier, like, you know,
simple SPROCs for like getting and retrieving and updating data.
But anything that is set-based that needs to operate on large sets
for particular operations should stay in the database.
Unless there's a lot of business logic.
Well, I mean, that percentile scoring is something that...
I can't see how you'd want to do that.
If you had... Right, I'm with you. I don can't see how you'd want to do that. If you had,
right. Like I'm with, I don't even know how many students there are in the United States.
Right. Uh, there's like what, I don't remember. 300 million people here. Who knows how many kids
are, how many students? Yeah. So, I mean, like if, if, uh, if a third of the United States are
students, that's a hundred million students. And if you were to rank all of those students' test scores so that you could say, like, oh, my student is in the 98th percentile, right?
That's a large data set.
You don't want 100 million records in memory that you're then going to try to do some scoring on.
And why would you?
Like you already have this capability inside of databases, right?
Yeah.
There are some things that they're made to do better, right?
Just straight up.
So large scale set operations leave to the database.
Yeah.
So it's just something interesting to think about, right?
Like don't take that hard line stance of everything has to be in the database or everything has to be in the application. Like there are definitely
awesome. My original answer was right. I mean, I think so. Um, but I do lean towards putting a lot
of things in the application layers nowadays. Just it gives you more flexibility overall.
So with that, that wraps up the specification section and our random thoughts
on, you know, where to put things. So with that, I do want to say first, thank you for everybody
that has left us a review and written all the incredibly nice things to us. So thank you. And
if you haven't, and you've been on the fence and you just haven't done it yet,
because you forget about it when you get to work or you get home, please do take the time to go up
there and, you know, write a few nice words to us on, you know, why you like the show or how it's
helping you or anything. It really does make our day. We appreciate it. And we do this because we
really want to help other folks out. So if you would like to do that,
go to www.cuttingblocks.net slash review. And there are links there to either take you to iTunes or
Stitcher and you can, you know, put all your, your happy words in there and we will gladly read them.
So it's now time for my favorite portion of the show survey says
all right so i was i gotta say i gotta admit like to listen to you guys since i
i wasn't available for the uh last recording i was a little saddened that i missed the, you know, being here for the yep, nope survey before for the invariant.
That one, I was like, oh man, I forgot I'm missing that.
Yeah, I really believe everybody lied about that one.
They had to.
Yeah, I was still a little shocked by that.
I was like, oh man, really? So yeah, so in the last episode, you guys asked
at what speed do you listen to podcasts and your choices were half speed, normal speed or two times normal speed. So Alan, you're going to, you're going
to play prizes, right? Rules by yourself. Yes, I can win. Yeah. Well, maybe there's
still an opportunity to lose. Let's not, let's not take that away yet. Yeah. I got to pick
the right one. Uh, yeah. Oh, so, I think we might have omitted some things here because James,
he said that he listens at SOMIT four times playback.
What player is he using?
Dude, I don't know because most of them get really choppy at two.
So I don't know.
We're going to have to ask him because that that's insanity. Uh, I mean,
obviously you can't listen to us at four speed because we speak real fast. Do we? Not really.
I don't think so. Um, so, uh, by price is right rules. I'm going to kind of split the difference here and i'm going to say the 1.5 okay is what most people chose
and let's go with 25 okay so you remember when i said that you could still lose
i lost man that's ridiculous this is an example of that
normal speed then everybody does normal normal. Oh my God.
I couldn't believe that that was the popular vote.
Yep.
Yeah.
Yep.
Normal speed.
Over 50% of the audience listens at normal speed.
That was shocking to me.
You know what though?
I've heard a lot of people say that they listen while they're doing things.
And the only way that they'll retain anything, and Carl's one of these
guys that will listen to podcasts while he's coding and he'll retain it, but only at normal
speed. So I think that's the reason. I think if it's something where people are listening
on the go, like just driving, I bet they do. No, I bet they go faster.
I mean, I can understand that because if you're okay. So preference is two times i like to listen to things two times
but it does require active listening in order to follow along with what's being said because you
can get lost in the conversation quick uh and then you know occasionally you know it'll happen
where like i'll be driving and all of a sudden you know i'm in an intersection and whatever and
yeah i'll be like oh, what did they say again?
Let me rewind it or I'll slow the conversation down just to pick back up
and then I go back to double speed.
But, yeah, if I can, double speed is my choice every time.
But I get it.
You're right.
That's fast, man.
Like I'm a one and a half speed guy.
Like that's to where it still sounds like a normal person just speaking faster
to is almost like chipmunk speak,
right?
Like,
like you said,
it's active listening.
It really depends on the player though.
I mean,
I think that the,
I think modern players,
I don't think they sound like chipmunk speak.
I mean,
maybe like if,
if you had tried to play something at double speed 20 years ago
then yes definitely but i don't feel like it's that bad now it's just not as smooth i like it to
i like it to sound you know double is not natural and actually some some are just too fast like some
of them are just you know the people speak fast enough to where two is, is just too fast.
Maybe that's what James meant by four times because he's listening to like
somebody from New York who already talks really fast.
And then he's listening to them at double speed,
which makes it sound like somebody from the South talking at four times speed.
So yeah, I get it now.
Wait, wait, do we talk slower down here?
Yeah. I really felt like yours should be like half speed.
Because you got that slow southern drawl about it, you know?
That buttery smooth.
No, not really.
All right.
All right, so let's get into today's survey.
And this one is brought to us again, Joe Recursion Joe,
bringing us another survey idea.
So I guess that makes him our absentee Joe. So, so since we're, since many monitors do you use?
Just one.
Or two is the minimum.
Or three, like a boss.
Or more than three, because if it's worth doing, it's worth overdoing.
What about you? Not a guess. What's your take? it's worth overdoing.
What about you?
Not a guess.
What's your take?
What's my answer?
I mean, yeah, it's varied.
I've gone from two screens to three screens before. I guess more recently it was from three to two,
but the two that I'm using now are like ultra-wides.
They're gigantic.
So, I mean, I haven't upgraded yet to that 49-inch Samsung Beast yet,
but I keep saying yet.
Yeah, so I think it kind of depends.
But there's times where it's like even with the with those
screens where i'm like i almost wonder if it's kind of like a handicap at some point you know
like if i have to work off of just my laptop monitor nowadays it drives me insane to have only that single 15 inch display you know what i will say this and this is one
thing that i love about the max and even windows the like the the latest windows 10 stuff as long
as the gestures on the trackpad on on the laptop are good enough to where you can do like your four finger swipes
to move screens, like virtual desktops. I can live with it because it's, it's like super fast
to get from one program to another. So like if I have my programming window up and then I have my
email up, then I can just swipe over and get to my email or swipe back and get to my program. I will say I do prefer big monitors,
but I can do it just because trackpads have gotten so good
on allowing you to navigate better.
I honestly think that that 34-inch widescreen ultra-wide has ruined me.
Yeah, me too.
I mean, we've talked about this monitor before.
I don't remember which, some LG monitor.
Yeah, LG 34UM95.
Yeah.
Sorry.
That sounds right.
That thing, I've gotten to the point where, like,
the thing I like about it is that in whatever editor I'm
working in I can tear off files into multiple tabs and I can have I can see them all concurrently
and so I really use the center third of the monitor the most like that's where I do like
my primary work but then on the like virtual wings, right. Of, of the, you know, the other two thirds
of this thing I'm using as like references. So I'll have like, you know, Oh, here's this other
file. Uh, like if I'm working in a MVVM pattern, right. I'll have like, you know, maybe the view
on the left and the model on the right. And in the middle is the controller. And then, you know,
I can reference things like, Oh yeah, that's what I have in the model. Oh yeah. That's right and in the middle is the controller. And then, you know, I can reference
things like, oh yeah, that's what I have in the model. Oh yeah, that's what's in the view. But
then in the controller I can do, you know, whatever the meat and potatoes is. So yeah,
I've totally gotten ruined on that one monitor. So if I were to answer one, it would have to be
like, yeah, one monitor that's just really, really big. Right. It's not quite fair. I think two would be for me, and I think most people are
going to say two, and I'm going to love all those that go three and above. Yeah, right. I think we
should put some specifications on it though, because if you're going to say an ultra wide
monitor like that LG that we're talking about then I think that needs to count as two I mean
that's yeah that puts us in three ballpark there then you know that right in terms of real estate
yeah yeah yeah I I get it yeah I need like two more of those 34s though oh man I want them wrapping
around me you better get some dual gX 1080s out there.
1080Ti's.
Yeah, man.
Awesome.
This episode is sponsored by Linode.
Linode has 10 data centers around the world with plans starting at just $5 per month
for 1 gig of RAM and 20 gigs of SSD storage
and can go all the way up to 200 gigs of RAM
and 16 cores for your heavy computing
needs. And all of this can be done in under a minute. Linode uses hourly billing with a monthly
cap on plans and add-on services, ensuring you'll never get in over your head. You have full control
of your VMs, so go ahead and add Docker, encrypted disks, VPNs, and more.
To get a promotional credit of $20 towards your Linode hosting fees, go to www.codingblocks.net
slash Linode, that's L-I-N-O-D-E, and enter CodingBlocks17 to get started today. It's like
you're getting your first four months on us.
All right, so back into it.
The next one that we have up is intention-revealing interfaces.
So you want to kick us off on this one?
I would, but I've lost my place in the notes here.
Uh, well, then you can't.
Oh.
Okay.
Now I got it.
That was weird.
Google Spreadsheets was getting all funky on me.
Yeah, okay.
So this is kind of like, I mean, we already honestly hit on this before already.
We did.
I forget what that section was.
It was, oh, the explicit constraints, right? Is that, you know, if the developer must consider the implementation of the component in order to use it, then the
value of the encapsulation is lost, right? If you can't read the name, that was a quote from the
book, by the way, but if you can't read the name alone to know what this thing is doing, then, you know, you've already messed up,
right? Like if you shouldn't have to go in and read the code of that method or that class to
understand what its purpose is. Yep. And again, straight out of clean code, right? I mean,
yeah, again, yeah. The parallels between the two. But I think this dives into more about what you like and that's the whole testing part
of this section, right?
Well, yeah, we'll get to that.
There was one part though, one quote that was related to the naming that I thought like,
oh, that's a great, that's a quote, was that the names of classes and methods
are great opportunities for improving communication
between developers.
And while that's a quote from this book,
I kind of, I felt like we said something very similar
during the Clean Code series.
But yeah, there was this other statement in the book
that he says that, you says that you write a test
for a behavior before creating it, and that forces your thinking into client developer mode.
And I loved that idea. I'd never before considered that the impact that TDD has on your brain by forcing you to think of your code as if you were someone else.
Yep.
And TDD, for those listening that haven't been along with us for the entire ride, is test-driven development.
So you start with your test first.
Yeah, go ahead.
Go ahead.
No, you're good no i i was just going to you know go on with that
that comment that that you know normally when we've talked about tdd or behavioral driven
development in the past thing you know anything where you're like uh let's focus more on the tdd
but like you know anything where you're writing the test first, you know, we,
when we've talked about that,
it's been more around just like making sure something works, you know,
and not this whole idea of like kind of tying in clean code with a DDD by
like saying, okay, let's,
let's write something that's expressive and let's write something, you know,
and then
if we are going to be the user of this thing for the first time, how might we want it to look,
right? So there was this other section in this chapter where he's talking about like, hey,
when you're writing your test, you know, write the test the way you would like this class to
function, you know, to be used. And then, you know, write these tests as a way to
explore the interface design of this class that you're trying to test, right? And then worry about
making it compile, right? It's like a mind hack, right? Yeah, exactly. Which is why I love this concept. I,
you know, I, I guess, yeah, TDD probably makes you think in that way, you know, as a user of
your code, but this kind of made it a little bit more clear and I think takes it to the next step
or, you know, uh, the next logical step, which is to, to definitely think about your code in this way, right?
Yep.
So I thought maybe not the exact reason for being for this particular chapter,
but it was definitely like one takeaway that I got from it that I just absolutely loved.
Yeah, I thought that was excellent.
I like the whole idea of test-driven development anyways.
Just I think it forces you to be better about your code from the get-go.
And I mean, we've talked about it before.
And one of the biggest problems is getting upper management buy-in, right?
Like if you don't already have an environment where people have bought into the idea trying to sell the idea is difficult as heck i mean it really
is right so um yeah and then uh you know there was this section where you're talking about like
you know in your public within the public interfaces of your domain, right? Again, keeping this concept of the
intention-revealing part in play here is that your public interfaces should state the relationship
and the rules, but not how they are enforced, right? It should describe the events and the actions, but not
how they're carried out. It should formulate the equation, but not the numerical method to solve it.
And it should pose the question, but don't present the means by which the answer shall be found.
And I found that section. I was like, oh, this is a great – I really liked the way he kind of put it here, right?
Yeah.
It goes back to just naming your things well.
Which is the hardest thing we do.
It really is.
I mean, how many times –
The struggle is real.
It really is.
How many times you sat there and said, man, should I name this?
And 10 minutes later, you've renamed it 10 times,
and you're still not happy with it.
Then you ask a friend, and then you phone a friend,
and then you say, can I eliminate 50-50?
Is that your final answer?
No.
You know, I'm going to go out on a limb and say that I'm not the only person
that has come up with what I felt was an awful name for something,
but I was at a loss for ideas for like,
what would be a better name for this thing?
And then I'm like,
okay,
let me see if someone else agrees that this is a decent enough name.
And so you call somebody or talk to somebody like this is a good,
this is okay.
Right?
Like this isn't,
you're not like,
if you saw this in a pull request,
you're not going to be like,
you know,
deny.
Right.
Like you're going to let it pass. You're going to
be like, yeah, whatever. That's good enough.
Right?
I can't be the only one.
I've totally had group conversations
where we're like, yeah, I don't know, man.
I just, I don't know.
I definitely named some stuff badly.
But I,
while I have named them badly, I did try to make their, their intent clear.
Which is all you can do.
So that brings us into the last section that we're going to cover tonight.
And this one's fairly straightforward.
It's side effect free functions. And there's really just two types when you think about it, and it's queries and commands.
And one is get, and the other is do type operations, right?
Gets should never modify the state.
Commands can.
You expect them to modify or,
or mutate the state of your objects?
And this is,
this one is so much easier to talk about than it is to do in real practice for
me sometimes.
Like,
and the thing that I like about it is typically when you follow this pattern,
this,
there's actually an entire pattern
called CQRS, which is command query. Doggone it. I'll have to look up the other two.
But the whole thing is you'll be able to look at it and you'll know, am I supposed to get something
back out of this? Is this a query? So you might call it get something, right?
Or if it's a command, it will be something that is an action that we'll take.
And so you just know by looking at them.
And if you follow that pattern in your entire project, it's real easy for developers to know what's supposed to happen, right?
Yeah. Yeah, I mean Reading this section of it though
Just made me think that
Like, well, I was like
Okay, is he really just going after functional programming?
Is that what we're trying to talk about here?
Like functional programming
And in a way, kinda
You know?
I mean, he gets into
Okay, well, if we're talking about the computer science
Definition of what a side effect is, then it's a change to, you know, it means that if there's any effect to the state of the system, then that counts as a side effect.
And that if you, you know, a function is an operation that can produce a result without any side effects, right?
Kind of sounds like functional programming when we talk any side effects, right? Kind of sounds like functional programming
when we talk about using functions, right?
And he later talks about like,
it's easier to use value objects, which are immutable,
and functions, they're easier and safer to use.
And maybe more importantly, they're easier to test.
And we've talked about that,
and it makes sense why that would be, right?
If you have a function that makes zero state change and just takes in two integers and returns back a result of adding those two together, that's an easy thing to test for, right?
But when you have to deal with state, that's where things get complicated.
Really fast. Yeah.
And so, you know, he talks
in this chapter about, like, you should try,
you should make every effort that you
can to put as much of your logic
into functions.
Right? Yep.
It's testable.
And easier to understand.
Right.
So, yeah. Fun functions, all the things.
So here's the thing that bugs me, though.
And this is why I say it's easier for me to talk about than it is to do in practice.
So I just recently had a problem to where I needed to get a draft item out of a system.
If you hadn't created a draft item already,
then we create it for you.
Right.
And this is where it really like internally,
I struggled with this.
I think I even got cold sweats,
like the whole nine.
Cause I made this,
this call to the server to say, hey, give me back the draft.
Right?
Get draft.
And basically pass it in like an empty GUID.
Right?
If you don't have one, we need to create one for you and give you back the real ID for that thing.
So you're hung up on the concept that you're making a query that should only obtain information and not affect state,
but yet if the thing didn't exist,
then you want to affect the state by creating it.
Yes.
But you could have, I mean, correct me if I'm wrong,
but you could have like created the,
or you could have returned back an object that's not yet persisted.
Like that persistence doesn't have to be part of the get.
Well, I think the correct way to do it in the command query type thing is
you would first query.
Actually, it sucks.
Like basically, you'd have to check to see if it exists.
If it doesn't exist, so literally you'd have to check to see if it exists, if it doesn't exist. So literally
you'd have to have a whole string of other command or other, um, processes to run through first.
First, does it exist? No. Okay. Now create it. All right, now go get it. Like literally you'd
have to have a three-step process instead of my simple, um, you know, thing that, that mutated
the state when it shouldn't have. So, I mean, things like that frustrate me because I want to follow good principles,
but then I also have this internal struggle with access operations.
They drive me crazy.
Yeah, the CQRS, by the way, just to of like back up for a second that's uh command query
responsibility segregation and that is a pattern also that you can look up we should probably have
a link in the show notes for this yeah uh i put one in there and this i guess maybe i don't like
it was definitely the art the first article that came up was uh martin fowler fowler and i don't like it was definitely the art the first article that came up was uh Martin Fowler Fowler
and I don't know if he was the oh he wasn't uh Bertrand Meyer mayor I'm not sure how his name
would be pronounced but he was the guy that pioneered it but it seems like Fowler has an
article on every single topic like he's basically his site is kind of like the Wikipedia of anything related to software.
It makes you wonder if he's actually the owner of Google.
Or at least the computer programming portion of Wikipedia.
Right.
But yeah, CQRS is a really cool topic.
Maybe that's something we'll drop into at some point as well.
There are some good Pluralsight courses on that as well.
So anyways, back to the topic at hand here.
But yeah, the whole idea is your query should not mutate the state
unlike what I just told you I did.
And the commands can, and typically those just return out void. Like in the pure sense of it, if you mutate something, then you might call the get afterwards, just like I was talking about to get that information back out.
So in the purest form, that's typically how it works. But at least as it relates to what the author was saying here,
is that when you're using commands, you should try to keep,
like I said earlier, try to use functions as often as possible
so you're not affecting state.
But when you do have to use commands, keep them segregated away,
keep them simple,
and they shouldn't return domain information.
Yep.
Yeah, I think that's pretty much everything.
Oh, this is, so the reason why they talk about the value objects as well,
there was a statement in there saying that maintaining invariance and
entities,
and this goes back to state completely,
but when you're talking about entities and aggregate roots and domain
driven design,
they're responsible for maintaining the invariance,
the state and the consistency within everything in its domain there.
That's way more difficult than just throwing away a value object and
replacing it with a new value object. So that's why that's like the preferred way of going about
things. So that brings us into the resources we like this go around. Domain driven design,
I actually moved it up to the top this go around
because we pretty much dug straight into the book for this one. We've got a link to the book there.
We highly recommend it. If this is a topic you are interested in, like I said, it's a little
bit wordy, but it gets really good when you start getting to the meat and potatoes. Also, there's a
site that I keep coming across that I really like. It's Los Techies. And they have all kinds of
topics. They have multiple different authors that write different, you know, anything about design
patterns or just different practices or whatever. They've got a lot of good information up there.
Their search is abysmal. I could not use the search on their site and get anything to come back.
So if you want to search a site for something like DDD, you need to do it from Google and just, you know, tell it that you want to go there.
And their slogan is, say, habla code, which is we speak code.
Yeah, I mean, you know, you say Los Techies, but depending on how you read that URL, it could just be Lost Eckies. It's funny because I actually
had the same thought when I first got there. I was like, Lost Eckies?
Oh, the Techies. So, yeah,
that one, we've also got the Pluralsight course that we've gone through and looked at, and
then another Pluralsight one that
is by Dino Esposito, which is excellent.
And then, again, dddcommunity.org and domainlanguage.com.
All super good references.
You can go piece together all your questions that you have, or you can ask us on these episodes.
So, now, it is my favorite part of the show.
It's the tip of the week.
That's right.
All right.
So I'm kind of cheating today.
Oh,
cheating.
I'm cheating.
Yeah,
man.
Ryan Williams actually sent this one in and shared it with us today.
So Nick Craver from stack overflow had sent out a reminder on C sharp for
color info attributes. And this is really cool.
So, um, if you are doing something and you're dealing with stack traces, that's awesome,
right? Because you can see exactly where things were calling. You can see the trace all the way
up, but a lot of times people will want to put like, uh, they'll want to put information in logs
and maybe you don't want the entire stack trace in there.
You can do what are these caller info attributes and you get the path, you can get the line of
code and you can get the method from which a particular method was called. And you can use
that as variables in your own code. And so this is a really nice way to be able to log where things
are coming from, or even be able to trace them back later if you need to.
Or maybe even put in debug points and be able to see it without digging through your stack.
So we'll have a link in the show notes here, but I thought that was really awesome.
It was a really cool approach to be able to find out where things were happening from inside your code in C Sharp.
And this is a cool part is I believe this is compile time stuff.
So there's no reflection hit or anything like that.
Yeah.
That's what I was about to say as a,
as a big bonus to this way of doing it is instead of using like the stack
trace object,
this there's a,
in the remarks section here,
the documentation, it says, call our info values
are emitted as literals into the intermediate language or the IL at compile time. So that's
super cool. I didn't know about this thing. Yeah, really fast. Yeah. So it's neat stuff. I'd never
heard of it. And I think that's awesome. So, uh, thank you to Ryan for sharing that, and you're welcome to everybody who's going to get to use it now.
That's awesome.
So, you know, as we do, we often find ourselves having to debug our web API calls and, like, why isn't that getting called?
Or why am I not getting the parameters I think I'm supposed to be getting and things like that. And sometimes like in, in.net web API can just be the most frustrating experience.
Maybe I'm alone in that thought,
but I'm pretty sure I'm not.
So I ran into this scenario where I had,
um,
my method was getting called, but the parameters that I thought were getting passed in
weren't making their way into the actual method. So I could look at the call from like, say,
Chrome DevTools. I could look at what Chrome was passing in to the request, right? And everything looked good there.
But by the time it was making its way into my web API call,
the method was getting called,
but the parameters weren't there.
And what do you do?
So I found this really great Stack Overflow answer
where they describe a way where you use object
instead, just plain old object. And then that way you can just do a two string and see what
actually was being, what the raw, uh, what the raw request contained. So you just use object as part of your method.
So let's say you had some web API post method
and you take in whatever your data type is,
but instead you could just say object
and whatever variable name you want to give it.
So in the example they give here in the Stack Overflow example,
it was model. And then you could just say model.toString and you could actually see
what what it was and it was so much easier to debug that way to see like oh I see why my object
isn't getting or I see that a it is getting everything that I think it's supposed to be
getting and now I can see why it's not making its way into the object like I thought it should be.
So would you recommend just leaving it this way or just use it as a debug tool
so that you can find out what the problem is and then put it back to your DTO or your object or whatever?
I would definitely put it back to the DTO because then it's more expressive.
Okay.
One thing that I like to do, and I don't know if you like to do this with your web API calls,
I've gotten, I don't know if this is a good habit i haven't decided if this is a good habit or a bad habit yet but i'll i've gotten into this pattern where i like to create a request object that my
my calls on the javascript side will will pass in an object that,
a JSON object that matches that C sharp request object.
And then in the C sharp side, I'll also have a response object.
So from that same, so let's say like if we had some customer,
you know, get customer request or something like that, you know, some kind of method like that,
I might have like a get customer request and a get customer response. I might have those some kind of method like that, I might have like a get customer request
and a get customer response.
I might have those two kind of objects, right?
I know we've talked about having like
too many DTOs floating around too.
So that's where I'm like kind of on the fence.
Like, is this an awful idea?
Or is this like an ingenious idea
that Martin Fowler is going to write a topic about
if he hasn't already?
Honestly, he probably already has.
Let's be honest.
That's a pattern I've actually seen a lot in Java.
I mean, in the Spring apps that I've done in the past, that is the pattern, right?
There's a request and a response object for basically everything.
But not a generic, not like just a generic HTTP request and an HTTP response.
No, I'm talking about per method.
Very specific to that method, yeah.
Yeah, I'm not, I don't love that.
I typically, I mean, I'm not.
So don't send you any of my pull requests is basically what I'm hearing from this.
So here's my thing, and this is probably my issue with a lot of programming in general,
is I'm not diametrically opposed to much of anything.
How can you be a developer?
We're supposed to be opinionated.
I mean, that's the thing, right?
I'm very opinionated, but I am not opinionated to the point where I'm going to dictate how a lot of other people write their code.
That's me, because I feel like, to me, coding is partly art, right?
And I truly do feel that way.
And I feel like if, and if you take that away from somebody, you take away some of the enjoyment
or a lot of the enjoyment of being able to do things.
But I guess the way that I typically do it is if there is a DTO, so like you said, you know, get customer, right?
I'd have a customer object and it would be both the same DTO that would be used to transfer that customer information would be the same thing I'd use for both the request and the response. Well, you know, that's actually probably like a horrible example now that I think about it because like that makes it sound like,
I should really say where like the method name is some kind of an action, right?
Because then it makes more sense.
Like if you had an update, going back to our canonical e-commerce reference,
if you had an update order request or, you know, method,
then maybe I would have like an update order request and an update order
response. I don't know. Maybe that's a bad example too, but yeah, I don't,
I don't know.
Yeah. That one's always tough for me too, because you know,
at least in C sharp for years,
like typically when you see an action on something, it's got a void type.
Right. And that's always kind of bugged me because I'm like, man, over years, like typically when you see an action on something, it's got a void type, right? And
that's always kind of bugged me because I'm like, man, what if, you know, if I send in something and
it gets mutated because I did an action on it, it'd be kind of nice to just have it back in that
same request, right? Like, I mean, we've probably all seen the trick where if you call it a SQL
server proc and you insert a new item, you might do select scope identity at the end of that to return back the key
for that newly created item.
And that way you can give it back to the calling application or whatever.
And I kind of like that pattern, but it seems to be anti the.NET way.
You know, going back to like, you remember, man,
I think it was episode one where Joe was talking about like this whole what if there was the comic books, the what if series, like, you know, what if Iron Man was evil and things like that.
Right.
And we were talking about like, you know, how interfaces could work like a what if kind of pattern.
But, you know, we've talked about how we hate like just sprinkling too many
dto's around right and going back to this like you know me being on the fence about like oh is this
request response pattern good bad right the one side about that that i actually kind of hate is
that i hate creating that response object because nine times out of ten all i want to i just really
want to be able to return back
an anonymous object because I don't care. It's throwaway. I'm just returning back a response.
And what I really wish that you could do, because in C Sharp, you can use anonymous types,
but you can't pass them around from one method to another and return them from a method.
But it would be so awesome if you could.
Can you not do it with a dynamic keyword?
I don't think you can do public.
I don't think in your method signature.
Let's say if you had a method signature that returned back an int.
You would say public int get order number.
I don't think you could do public dynamic get order number.
I mean, I'm wrong.
Oh, no, but you can do public object.
You can do object.
Yeah, but now you're boxing.
You are boxing, yeah.
Yeah, so that's lame.
That's lame.
No, what I'm saying is, so in that scenario, yeah, you're right.
You're right in that example.
Maybe you could.
And maybe that's the way I should do it, by the maybe that's the answer to my my response request uh scenario but it'd be nice if you could
just have something like you didn't care about and just you know i don't know what that syntax
might look like maybe it'd be like uh instead of public int get order number like public new
get order number or you know whatever i don. I don't know. Public curly brace, close curly brace, get order number. I don't know.
Just a one thing.
One thing that I have done in situations like what you're talking about though
is I'll literally,
and basically because I know it is sort of throwaway,
I'll put that same class in with the web API class, you know?
So if it's a DTO that is never ever going to be touched outside
of that particular area, then I'll just put a public class, you know, request DTO response DTO
at the top of that file, because I don't necessarily want it used anywhere else. You know what I'm
saying? So yeah, well, in that case, if you didn't want to use anywhere else then it'd probably better to make
that a private class yeah but you can't do privates on dto's for web api right if you're
going to marshal them yeah yeah it's web api is aggravating yes it is it can really lose hours
of your life so to answer to go back to answer your question as it relates to this Stack Overflow answer,
I would not leave the object,
I would not leave the type as object long-term.
I would only use it for debugging purposes.
Good on you. I would go back to my badly used request object type
and then have my pull request slapped by Alan.
Alan just, I would restate.
And his indifference.
Boop.
We have a bit of a joke, right, between us?
I'm the laid back whatever guy.
That's how I am about most everything.
And maybe that's good, maybe it's bad, who knows?
You don't have a care in the world.
I'm pretty close.
So that's it.
In summary,
we've gone over some nitty gritty stuff in DDD that would cover.
Let's see.
Let's let me scroll back through cause we didn't type it in here.
Explicit constraints, processes, domain objects.
We had the specification pattern, which I thoroughly confused Outlaw on.
Intention revealing interfaces, side effect free functions.
So basically fun stuff.
Yeah, man.
And honestly, go check out the specification pattern.
You will thank us later.
I promise you.
Yeah, that's part of my homework assignment.
So be sure to subscribe to us on iTunes, Stitcher, and more using your favorite podcast app.
And be sure to give us a review by visiting www.codingblocks.net
slash review, where you can find links
to your favorite podcast aggregators.
Yep.
And send your feedback,
question and rants
to our Slack channel
instead of our email.
You can go there
by codingblocks.slack.com
and be sure to follow us
on Twitter at CodingBlocks
or head over to codingblocks.net
and find all our social links
there at the top of the page.
We are growing our YouTube thing.
So, you know, definitely go up there and check out the videos.
Like I said, I do want to do something on specification pattern up there as well.
And, you know, we want to keep bringing you more great stuff.
So thanks, everybody.
You're listening to Coding Blorbs, episode 63.
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 our show notes, examples, discussion, and more.
Send your feedback, questions, and rants to comments at codingblocks.net.
Follow us on Twitter at codingblocks or head to www.codingblocks.net and find all our social links there at the top of the page.
Wait a minute.
Did I say Blorbs?
You did.
It should be Borbs.
Dang.
You're listening to Coding Blorb.
I said it again.
Blorbs.
Borbs.
Borbs.
B-O-R-B.
Yes. Beep
Alright