I really like this style of baking the constraints into a type. Makes it a lot easier to communicate to newer developers on your team which constraints need to be where without sprinkling ifs all over the place and eventually missing something.
I find the distinction to be blurry at best. In my experience, it is more helpful to distinguish the kind of validation you are doing: syntactic or semantic. Let's for example take an E-Mail Address: a) Syntactic Validation: is the format of the address valid; using a Domain Primitive, as you showed with the Quantity, is a good way of capturing this kind of validation. b) Semantic Validation, i.e. imposing business rules, like: 1. The E-Mail Address my not be already in-use, e.g. for creating a user account 2. The E-Mail Address must exist for resetting a password. Or put another way: Syntactic validations can stand on their own and only consider a single value, e.g. an E-Mail Address (correct format), an Order Quantity (0 > and < 100), etc. Semantic Validations are more involved. They look at relations between elements, which might involve current system state.
I differ logic by two types - 1. Technical Logic - Boilerplate, setup, API calls setup, data transformation, parsing data etc... 2. Business Logic - Client requirements, business flow, client domain-specific logic and so on.
Nice video as always. I would argue though that Exceptions should not be used for handling Business Rules that you know about when writing the code (e.g. don't ship an item if you don't have any in stock) . Exceptions are for situations that should never happen, like shipping a negative quantity. Too many developers rely on Exceptions for business logic that should be dealt with more gracefully.
I still disagree with you this might be true in event-driven systems but on api based application you need to do this because if you don’t and you only checking for positive shipping then request will have to travel through entire flows while at the end of the day will fail. This makes your application slow. It is always good to always use fail fast approach to handle errors.
@@gafarolanipekun1202 if the check fails on the "inner layers" of the software it can be handled by exceptions. "Outside" you can just do simple validations and return 4XX. I don't think it's a problem to validate things twice.
Honestly i think this depends on language and current design patterns in the system you are working in. In Java, common practice is to throw an exception. Especially if you want to trigger some transaction to rollback, or if you want to respond with that error to the user. If you are writing Go, you probably wouldn't throw an exception and instead return an error. In JavaScript you probably do a mix of both, etc.
Another way I've heard it described is that business rules are "designed by the business to bring value to the business". In other words, if the business didn't develop the idea, then it's probably not a business rule. Everything else is a technical concern like validation. Definitely much different than answers I get when I'm doing code reviews with Indian contractors and I ask them if they know what a business rule is (we model them in a different layer) and they basically say " told me to do this and he works for the business, so therefore it's a business rule" or some variation of this. /tableflip
Not really, stories usually have validation and business logic intermingled. Perhaps you need to write/convey better stories/information (with/without a business analyst)? So, its definitely difficult for developers but the distinction this video makes a lot more sense. Atleast contractors you are working with cross checked with their team lead.
@@iorch82 I don't know what procedence is but no, I don't feel it was unnecessary. It's a perfect example of why it is so important to know the difference between business rules, validation, or even generic requirements for that matter, let alone NFRs. It's also a callout that it tends to be contractors who never take the time to learn any of this stuff because they don't care; they have no stake in the systems they vomit all over because they just move onto other jobs. Most contractors I've worked with (hundreds if not thousands at this stage) are basically bots. To them, if it is any form of requirement, then it is a "business rule". When interviewing, it's actually one of the first questions I ask - explain the difference between those things. Most people get it completely messed up, so I'll offer a better definition and ask the question again, see how they answer and then ask them to assign these "labels" to a few different examples. Probably 1 in 5 get anywhere close and we'll usually hire them them anyway and then 4 out of 5 of those tend to be a net negative impact on the project they're assigned to. Been tracking this for a long time because, big secret, I dislike most contractors. @wennwenn1422 no I think you misunderstand. I didn't say the contractors cross referenced anything, I didn't even say they asked any questions. I said the lead told them to do something so they think that something is a business rule because someone from the business told them to do it. And to that point, it doesn't matter what is in the user story because they will call everything in that user story a business rule. It's problematic to me because 1. It's usually an indicator that this developer will also have absolutely no idea how to break down a problem and 2. We keep our business rules in the domain layer separate of the application layer but since they don't know the difference and don't really care to learn, those business rules end up scattered everywhere and it causes more work to get them sorted back out.
Guys, semantic validation or syntaxique validation are business. Is the client business who's saying the quantity should be greater than 0. Some time the client business would even say, quantity can be negative or positive bu note null. Like in stock adjustment situation.
I agree with the trivial validation thingy. A valid postal code is not a BR, just generic domain constraints. I have seen countless times the "yeah I have to validate an email so lets do DDD"
An interesting extension to this conversation would be taking a look at the database elements in terms of business rules and trivial validation. Databases encapsulate well these differences. Even though we tend to speak of databases as the biggest expression of a system's business rules, these days they are mostly about built-in data trivial validation. For instance, our datatype choices for fields, nullability options, identity, many (but maybe not all) unique constraints, CHECK constraints like limiting the range of an RGB colour column, and I would strongly argue for referential integrity to be included in trivial validation too. What's left for business rules in modern databases? Well, we would prefer nothing at all. So assuming we aren't creating any stored procedures, one can argue some business rules still remain in databases, like table organization (which tables you have on your schema and the logical relationship between them). And you can bet that all those cases where we are breaking normal forms are ... by design business rules too ;)
Thanks a lot Derek, great video! I wonder if you have some sort of list of books about architecture & design that you think is useful for software developer?
A few users asked about FluentValidation. That's something I'm curious about as well. In a Web API, I'm going to have a DTO coming in. I could very easily apply validation rules against that using FluentValdation, *before* I construct domain models and initialize them with data from that DTO. Is that a valid approach? In those cases, you might still have models for concepts like Quantity but they wouldn't be concerned with input validation. Really would love to see your thoughts on this.
Not sure that is a business rule so much as a Policy, business rules will use policies to trigger actions. So to make you example a business rule, you'd have a something like a minimum quantity ( the policy) before triggering restocking ( an action)
If the cart requires 1 product to be able to check it out, is this "simple validation" or a business rule? For me its a mandatory business rule, you can't checkout a cart without items. Assuming you have a cart aggregate with a checkout method, you need to ensure you can't checkout without any item present in the cart. Lets assume further I make an API call, then my "simple" validator would validate the API request, return an error if the cart item count is not greater than zero and not even hit the domain layer. The rule in the domain layer will just ensure (and probably throw an exception instead of a nice message) the consistence of the state and cart logic. I don't differentiate by triviality but if something is a direct business rule that is expressed and defined as such and therefore part of the domain model. Complexity of a rule is not an argument for me here. But I differentiate between input validation, e.g. validating a HTTP Request, CLI command args or a message from some bus. Each of them will have to be validated and after that turned into a command or query object. All of this happens before it even touches the domain model. But the domain model must ensure its in a correct state and therefore duplicate the logic sometimes with the input validation. However, the input channels and their format and structure can be very different. Therefore the separation between input (or simple) validation vs business rules. And by the way, a nice pattern for business logic is the en.wikipedia.org/wiki/Specification_pattern.
It's a business rule for sure. An empty shopping cart could still go through the checkout process. The fact that you can't do it was a specific data flow decision that didn't necessarily have to be made or that can be changed in the future. It's not a trivial validation in the sense that it's trying to be more than a simple (trivial) axiomatic rule.
In general, I call this "Basic" validation. But part of me feels like business rules could also fall under basic validation. My rule of thumb is: if different businesses might want to do something different, it's a business rule. No business will want to let you order a 0 quantity because that makes no sense. For your email example, I've had different clients that wanted to be more or less stringent on what they allowed for: the regex for validating email is famously complicated, and it will allow through certain things some people won't want to let through. It can be pretty basic in code, but if you've got a codebase you're going to deploy for multiple clients, then a hard coded solution doesn't necessarily work here. Another example I've ran across is a sanity "maximum value" for every order. Some clients want it, some don't.
The problem with this term is that is meaningless and people are still trying to extract the "Business model" from their codebases. Forget about that and your life will be easier. If you have good unit tests all of this BS doesn't matter.
Validation: An employee must have a first name and a last name. Such as Cosmo Kramer. Business rule: An employee can't be fired unless they were employed by the company in the first place. Such as Cosmo Kramer.
Perhaps a good way to think of it is that validation guards against doing logically impossible things, preventing pure nonsense. You couldn't ship someone negative 5 widgets if you wanted to. One does not *decide* that "in this business, we're not going to ship negative numbers of widgets". That has been decided for you by, um, the universe. Business rules, on the other hand, reflect voluntary decisions that are subject to change.
ive encountered this before, but not thought about it in the way you described. i wonder if you apply a strategy pattern and strategy locator pattern using fluent validation would prove more useful or just be another leaky abstraction, be important to document it and name the stuff correctly. i also often find myself trying to write classes that take options whenever they are related to a customer's specific requirements but we have foreknowledge that there is a margin of variability within specific "rules", that way when the next customer inevitablely wants it different we can adjust the customer's configuration in a database and then the code doesnt need to be change, but sadly it usually involves writing a new strategy entirely. hard to predict...
Would it be appropriate to use this same distinction to help understand when to put constraints into your Database schema, versus when to do validation in application?
So it is this ok that validations rules to stay in an outer layer(not domain layer),may be the application layer which is the domain layer client?Thnk you?
Derek, how you'd handle business rules that are tightly coupled to the user interface? I'm afraid I'm putting too much work in my frontend, dealing with business rules in the frontend which is a bad sign.
So as i understood trivial validation should be stored in the application service layer, not in the aggregate as invariants ,is this correct ?Thank you!
Would someone in the business talk about an email address being valid apart of some business workflow or process? If not, it's probably not domain logic.
While I agree there's a distinction, I don't agree with your example. For me business logic is where knowledge of the domain is vital, everything else is validation. You can sense check this by removing all the domain ubiquitous language, transpose into another domain and if it still makes sense then it's probably not domain logic. Taking quantity
Thanks for the comment. I can see your argument. "you can't ship 0 products" isn't a domain rule the same as you're birthday can't be 3000-02-01. It's not logically valid. As for being deterministic, why do people mock so much (not that I agree with it)? It's because they want the dependencies in their tests to be deterministic. The state isn't deterministic depending on how you're getting it. In my example it was because the state was event sourced. I do appreciate the comment, honestly.
@RobLang "For me business logic is where knowledge of the domain is vital, everything else is validation"... And don't you need domain knowledge to perform validations? "You can do this by removing all the domain ubiquitous language, transpose into another domain and if it still makes sense then it's probably not domain logic." Ever heard of shared kernels? There can be concepts that are used by many domains, you cannot guarantee they are exactly the same though, different domains => different perspectives. But there still can be some shared knowledge. Interesting note about the quantity. You made me realize it's kinda misleading, but not for the reason you provided. You say quantity isn't a domain term, but how isn't it? Isn't it literally the name of the argument my domain service asks to be provided? The reason it's wrong is that 0 is a quantity. I can say I have 0 apples. And it's hard to give a domain name to implement this type of requirement. Maybe SomeQuantity? lol better than repeating the same validation check everywhere, even if trivial. I don't get why when the logic is not from >your< business domain, u guys say it's not domain/business logic. It's just that it's logic from another domain, not that it's not domain logic...
@@CodeOpinion as soon as you use domain language to describe a problem, it's domain logic. You can't get round that. You can't ship 0 products. "Ship" is domain language because what it means to ship something differs between domain. I guarantee systems have work-around where a customer is charged but nothing is shipped. Birth date is different because everyone on the planet has one, it's not unique to a given domain. It's globally ubiquitous. My definition of deterministic is mathematical/scientific. Everything is repeatable unless you're using System.Random without setting the seed. You can absolutely reproduce event stream state in unit tests; I've done it (and we were using Event Store back then). Really love the video though, feels like I'm splitting hairs with this!
@@henriquesouza5109 most validation is performed by the type system "ABC" is not an integer. I don't need domain knowledge to know that ABC is not an integer. You can't be born in the future. That's not unique to any domain, that's globally understood. Quantity is a domain term, I think you misread my comment. Different domains have their own domain logic. They own it themselves. Even in the same industry.
"Simple" validations are as much a business rule as any other invariant, the fact it went from 'not null' to 'check w/15 other services to derive the validity' makes no difference.
In the example here, the use of an int for the representation of a physical quantity is where the problem lies. No matter the business, negative physical quantities don't exist. The fact that a business does not accept the registration of a shipment unless the quantity is below the physical stock is a business rule. A different business may allow such a registration, as long as some other criterion is met. Shipping negative quantities of goods is impossible for any business, so there is a distinction between the two cases.
I agree that everything is a business rule. I would argue that using the quantity class is enforcing that business rule. However, I think it is still valid to remove the primitive int from the method declaration. Especially since the logic was occurring across multiple methods.
@@CodeOpinionAlways valid entities is a concept every domain/business should hold. Now for the validation check, it's of the email business responsibility to check if the email is valid, and of the phone number business responsibility to check if it is valid. Of course its very likely that it isn't responsibility of the business you work on, if it ships products or w/e, your business should assume valid email or phone numbers, but that doesn't mean they don't belong to any business. Sorry for so many edits, my english is bad :P
@CodeOpinion if a valid email is a concept that my business uses than its part of my business rules. I would handle it in the same way as the Quantity object, with an Email object.
Derek, what is your opinion about the externalization of business logic with BPMN-based business rule tasks and DMN-based decision models? Speaking of process and rules engines like Camunda.
Great video! Thanks a lot! May I nitpick regarding your terminology? When you say ”deterministic”, I think you mean “functional” (as in functional programming). I doubt that much business logic is based on randomness. Sorry for complaining on such a detail in such an amazing video!
@@CodeOpinion Sorry and thanks :) It seems to mean something very similar, and I would still call a program filled with global variables ”deterministic” although it can be hard to follow.
Hey Derek, First of all a great video as always. I have a couple of thoughts on this topic - I think in your explanation you've mixed up a couple of different and distinctive approaches to layering/segregation and I would like to hear your thoughts on this opinion. The following is my IMHO and not critique or challenge ;) The refactoring you did was completely logical, but not based on the separation of validation rules and business rules, but rather segregation of rules to their domains (you mentioned this later in the video). The positive quantity validation is a "rule of a product quantity", independently of where it is used (in this context), while quantity being more or equals to the available amount is a "warehouse order rule". So this resolves more around segregation of concerns and not application layers. What you mention as validation logic being set in stone is because the scope of "product quantity" is and has always been more standardized, I mean, we have thousands of ecommerce engines and this is a standard rule for all of them and we think it's set in stone, while, let's say for an example, business wants to sell some product only in batches of 3 and 5, so you would validate quantity for qty > 0 AND (qty%3 OR qty%5), and what's worse it should happen much earlier than order placing - somewhere while forming the order, at this moment the "rule of product quantity" becomes a business logic and not validation. Or vice versa, you no longer need the "warehouse order rule" of limiting the order amount (for example, if you're not only a warehouse, but a production company) and only limit to a sane amount defined by one of the production line managers. I hope I was elaborate enough and did explain clearly. From my experience, I really don't like the definition of "business rules", everything that is not a technical limitation would or can be called a business rule at some point if your business is creative enough :) What are your thoughts?
Thanks for the comment. Yes, I see your argument and in the product quantity example you gave, I'd relate that to more domain specific. A few other comments have made a similar argument that "Quantity" is a domain concept. I'd argue it's not by itself, unless you have some non-conformity like you just described. As a similar example to that, an Email address associated to a customer isn't a domain concept. It's universally understood. If however you only accepted email addresses with a ".ca" (I'm Canadian eh!), then that to me differentiates it. Credit Cards, Phone Numbers, Time zones (IANA), the list goes on for me. At the end of the day, I want to separate complex logic that's specific to MY business. Appreciate the comment. We might be splitting hairs.
@@CodeOpinion Thank you for the reply! I love refactoring topics and moving things around, always interesting to hear the thought process of other people.
It' a bit strange for me that WarehouseProduct has method ShipProduct and apply. Is it normal approach in DDD that business objects are self awareness and work as use cases? I'm beginner in this topic of DDD, but it indicates that WarehouseProduct can consume any other business objects as dependencies?
Just out of curiosity: Sometimes you need to determine if a button which executes an action is shown based on the rules you showed. How can this be achieved?
Hypermedia. Passing down the actions that are possible/not to the client so they know what they can or cannot do. ruclips.net/video/OcWa0WJBF2U/видео.html
@@Alex-lu4po It's a UI-only concern. Business rules come in layers. Your UI has its own set of business rules, distinct of your data process business rules. So if you have a UI that needs to make a decision, that decision will be evaluated and be made on the UI. Once the button is clicked, some other layer of your project will process the data according to its own business rules.
@@Alex-lu4po Don't see how. You'd need to be more specific. (And btw... just a side-note here: duplicate code is not so bad as people point out. Embrace duplicate code when you need it. Don't always try to get away from doing it.)
Hah! I've been calling it "trivial validation" for a little while now. I'm just going to assume this is a term you've used previously in a video or blog and I just picked it up. =)
I can't agree with deeming this logic as trivial and therefore not business rules - bit of a judgment call in my opinion but in the end it doesn't affect things much. Regardless that logic should definitely be kept out of the UI. Also considering that the logic for the trivial validations is deterministic and static, wouldn't it be better to convert that logic into static functions instead of a record? That's literally the definition of a pure function.
I like the change of moving this to a non-primitive. (And great video and channel by the way, I really like it) But, I do wonder... Why is it not business logic to error when quantity is less than or equal to zero? If I were running a pizza shop and someone said they'd like to order -100 pizzas, I would think that it reasonable that I ask whoever is answering phones to mention back to the caller that we can only fulfill pizza orders of at least 1 pizza. I would ask for them to do this for all orders Why is that not a business rule? And once again, thanks for all the great videos. (I try to avoid mentioning a software system because the fact that it is software seems not to matter when sussing out business rules)
Exceptions are just kinda easy to manage a categorize and handled differently based on that, i think that's why they are the best choice. So like what i like to do is i have two kind of exception, one is a 'buisness rule' kind, when i throw that, it just written out in a messagebox, and the other is the 'normal' exception, when that throw its logged and also provides a stacktrace in the messagebox for easy troubleshoot. This way, all the 'communicatiom with the user' can be kept in one place, in the central exception handler, no need to have any specific thing. But also this needs to have the exception handling to be centralized to work well.
A good start! Generally speaking, if you code an "if" in your code, you are doing it wrong. Polymorphism and and OO patterns should alleviate that need. But, this is just junior level thinking. In an enterprise setting, you should delegate validations of simple syntactic nature to OpenAPI3.0 definitions. More complicated true business logic should be delegated to an evaluation engine like RedHat Kogito. Again more jummy lose coupling and delegating things that change to definition files that can be changed in runtime.
There are business rules, they are simply rules of a specific business (or domain), you just have to specify which business you're talking about before asserting stuff.
@@leonardomangano6861 Every rule is some business' rule, for instance, if your business problem is dividing numbers for example, warning your customer and also checking divisions by zero is your business responsibility. And in this case "you can't divide by zero" is a business logic (your business logic).
@@leonardomangano6861 Why you asking this? lol a DB schema is not any logic, it's rather a structure that contains tables, constraints, indexes, etc. You can for sure define some simple business checks in it but it cant go much further than that. The structure you define for sure has relation with your business requirements, entities, relations and etc, but it's just how your domain projects into it, it's your entities projected into a table for example. It's just that DBs aren't expressive enough nor easily queryable for its definitions.
Isn't that a little bit too simple. By this example everything that is invariant is a validation, and everything that has parameters it has to adhere to is a business rule. I can't put my finger on what is astray, but this explanation seems too simplistic and one-dimensional. Are there really no invariant business rules? 🤔
This is the opinion of a man who has never shipped a stable production application in his life. You can safely ignore whatever Mr. IJobNativeParallelMultiHashMapMergedSharedKeyIndices has to say
I really like this style of baking the constraints into a type. Makes it a lot easier to communicate to newer developers on your team which constraints need to be where without sprinkling ifs all over the place and eventually missing something.
Scala is big on that concept
I find the distinction to be blurry at best.
In my experience, it is more helpful to distinguish the kind of validation you are doing: syntactic or semantic.
Let's for example take an E-Mail Address:
a) Syntactic Validation: is the format of the address valid; using a Domain Primitive, as you showed with the Quantity, is a good way of capturing this kind of validation.
b) Semantic Validation, i.e. imposing business rules, like:
1. The E-Mail Address my not be already in-use, e.g. for creating a user account
2. The E-Mail Address must exist for resetting a password.
Or put another way: Syntactic validations can stand on their own and only consider a single value, e.g. an E-Mail Address (correct format), an Order Quantity (0 > and < 100), etc.
Semantic Validations are more involved. They look at relations between elements, which might involve current system state.
I differ logic by two types -
1. Technical Logic - Boilerplate, setup, API calls setup, data transformation, parsing data etc...
2. Business Logic - Client requirements, business flow, client domain-specific logic and so on.
Splitting those only cause harm to your solution and also is very hard to draw the line
Nice video as always. I would argue though that Exceptions should not be used for handling Business Rules that you know about when writing the code (e.g. don't ship an item if you don't have any in stock) . Exceptions are for situations that should never happen, like shipping a negative quantity. Too many developers rely on Exceptions for business logic that should be dealt with more gracefully.
Agreed. I'll be creating another video to illustrate this with a Either type (best we can do in c# right now for discriminated unions)
I still disagree with you this might be true in event-driven systems but on api based application you need to do this because if you don’t and you only checking for positive shipping then request will have to travel through entire flows while at the end of the day will fail. This makes your application slow. It is always good to always use fail fast approach to handle errors.
@@gafarolanipekun1202 if the check fails on the "inner layers" of the software it can be handled by exceptions. "Outside" you can just do simple validations and return 4XX. I don't think it's a problem to validate things twice.
Hard disagree. It's the easiest way to signal your system has entered an invalid state.
Honestly i think this depends on language and current design patterns in the system you are working in. In Java, common practice is to throw an exception. Especially if you want to trigger some transaction to rollback, or if you want to respond with that error to the user. If you are writing Go, you probably wouldn't throw an exception and instead return an error. In JavaScript you probably do a mix of both, etc.
Another way I've heard it described is that business rules are "designed by the business to bring value to the business". In other words, if the business didn't develop the idea, then it's probably not a business rule. Everything else is a technical concern like validation. Definitely much different than answers I get when I'm doing code reviews with Indian contractors and I ask them if they know what a business rule is (we model them in a different layer) and they basically say " told me to do this and he works for the business, so therefore it's a business rule" or some variation of this. /tableflip
Not really, stories usually have validation and business logic intermingled.
Perhaps you need to write/convey better stories/information (with/without a business analyst)?
So, its definitely difficult for developers but the distinction this video makes a lot more sense.
Atleast contractors you are working with cross checked with their team lead.
Honestly noting the procedence of the contractors was a bit unnecesary, don't you think?
@@iorch82 I don't know what procedence is but no, I don't feel it was unnecessary. It's a perfect example of why it is so important to know the difference between business rules, validation, or even generic requirements for that matter, let alone NFRs. It's also a callout that it tends to be contractors who never take the time to learn any of this stuff because they don't care; they have no stake in the systems they vomit all over because they just move onto other jobs. Most contractors I've worked with (hundreds if not thousands at this stage) are basically bots. To them, if it is any form of requirement, then it is a "business rule". When interviewing, it's actually one of the first questions I ask - explain the difference between those things. Most people get it completely messed up, so I'll offer a better definition and ask the question again, see how they answer and then ask them to assign these "labels" to a few different examples. Probably 1 in 5 get anywhere close and we'll usually hire them them anyway and then 4 out of 5 of those tend to be a net negative impact on the project they're assigned to. Been tracking this for a long time because, big secret, I dislike most contractors.
@wennwenn1422 no I think you misunderstand. I didn't say the contractors cross referenced anything, I didn't even say they asked any questions. I said the lead told them to do something so they think that something is a business rule because someone from the business told them to do it. And to that point, it doesn't matter what is in the user story because they will call everything in that user story a business rule. It's problematic to me because 1. It's usually an indicator that this developer will also have absolutely no idea how to break down a problem and 2. We keep our business rules in the domain layer separate of the application layer but since they don't know the difference and don't really care to learn, those business rules end up scattered everywhere and it causes more work to get them sorted back out.
Guys, semantic validation or syntaxique validation are business. Is the client business who's saying the quantity should be greater than 0.
Some time the client business would even say, quantity can be negative or positive bu note null. Like in stock adjustment situation.
I agree with the trivial validation thingy. A valid postal code is not a BR, just generic domain constraints.
I have seen countless times the "yeah I have to validate an email so lets do DDD"
I watched it again today and enjoyed it again. Good principles bears repeating.
Thanks for the double watch!
An interesting extension to this conversation would be taking a look at the database elements in terms of business rules and trivial validation. Databases encapsulate well these differences. Even though we tend to speak of databases as the biggest expression of a system's business rules, these days they are mostly about built-in data trivial validation. For instance, our datatype choices for fields, nullability options, identity, many (but maybe not all) unique constraints, CHECK constraints like limiting the range of an RGB colour column, and I would strongly argue for referential integrity to be included in trivial validation too. What's left for business rules in modern databases? Well, we would prefer nothing at all. So assuming we aren't creating any stored procedures, one can argue some business rules still remain in databases, like table organization (which tables you have on your schema and the logical relationship between them). And you can bet that all those cases where we are breaking normal forms are ... by design business rules too ;)
There is not such thing as a "Business Rule", is just a term without a real meaning.
Thanks a lot Derek, great video! I wonder if you have some sort of list of books about architecture & design that you think is useful for software developer?
A few users asked about FluentValidation. That's something I'm curious about as well. In a Web API, I'm going to have a DTO coming in. I could very easily apply validation rules against that using FluentValdation, *before* I construct domain models and initialize them with data from that DTO. Is that a valid approach? In those cases, you might still have models for concepts like Quantity but they wouldn't be concerned with input validation. Really would love to see your thoughts on this.
I agree with you but I'd like to know where should you put the validation logic?
Thanks for making this video. I'm starting to come around on the idea of encapsulating input values in validated objects.
One more amazing video. Thanks for your work!
I think it was uncle bob that said you should get rid of all value types and almost everything should be a reference type like you did with quantity
Unless you care about speed and memory consumption enough to use `record struct`
Not sure that is a business rule so much as a Policy, business rules will use policies to trigger actions. So to make you example a business rule, you'd have a something like a minimum quantity ( the policy) before triggering restocking ( an action)
If the cart requires 1 product to be able to check it out, is this "simple validation" or a business rule? For me its a mandatory business rule, you can't checkout a cart without items. Assuming you have a cart aggregate with a checkout method, you need to ensure you can't checkout without any item present in the cart. Lets assume further I make an API call, then my "simple" validator would validate the API request, return an error if the cart item count is not greater than zero and not even hit the domain layer. The rule in the domain layer will just ensure (and probably throw an exception instead of a nice message) the consistence of the state and cart logic.
I don't differentiate by triviality but if something is a direct business rule that is expressed and defined as such and therefore part of the domain model. Complexity of a rule is not an argument for me here. But I differentiate between input validation, e.g. validating a HTTP Request, CLI command args or a message from some bus. Each of them will have to be validated and after that turned into a command or query object. All of this happens before it even touches the domain model. But the domain model must ensure its in a correct state and therefore duplicate the logic sometimes with the input validation. However, the input channels and their format and structure can be very different. Therefore the separation between input (or simple) validation vs business rules.
And by the way, a nice pattern for business logic is the en.wikipedia.org/wiki/Specification_pattern.
It's a business rule for sure. An empty shopping cart could still go through the checkout process. The fact that you can't do it was a specific data flow decision that didn't necessarily have to be made or that can be changed in the future. It's not a trivial validation in the sense that it's trying to be more than a simple (trivial) axiomatic rule.
The Quantity class is a value object. You get rid of "primitive obsession" by using value objects. Regular DDD.
In general, I call this "Basic" validation. But part of me feels like business rules could also fall under basic validation. My rule of thumb is: if different businesses might want to do something different, it's a business rule. No business will want to let you order a 0 quantity because that makes no sense.
For your email example, I've had different clients that wanted to be more or less stringent on what they allowed for: the regex for validating email is famously complicated, and it will allow through certain things some people won't want to let through. It can be pretty basic in code, but if you've got a codebase you're going to deploy for multiple clients, then a hard coded solution doesn't necessarily work here.
Another example I've ran across is a sanity "maximum value" for every order. Some clients want it, some don't.
The problem with this term is that is meaningless and people are still trying to extract the "Business model" from their codebases. Forget about that and your life will be easier. If you have good unit tests all of this BS doesn't matter.
Validation: An employee must have a first name and a last name. Such as Cosmo Kramer.
Business rule: An employee can't be fired unless they were employed by the company in the first place. Such as Cosmo Kramer.
Havent found the answer to this question anywhere, and Ive read so many software books! Thank you so so soooo much!
Perhaps a good way to think of it is that validation guards against doing logically impossible things, preventing pure nonsense. You couldn't ship someone negative 5 widgets if you wanted to. One does not *decide* that "in this business, we're not going to ship negative numbers of widgets". That has been decided for you by, um, the universe. Business rules, on the other hand, reflect voluntary decisions that are subject to change.
ive encountered this before, but not thought about it in the way you described. i wonder if you apply a strategy pattern and strategy locator pattern using fluent validation would prove more useful or just be another leaky abstraction, be important to document it and name the stuff correctly.
i also often find myself trying to write classes that take options whenever they are related to a customer's specific requirements but we have foreknowledge that there is a margin of variability within specific "rules", that way when the next customer inevitablely wants it different we can adjust the customer's configuration in a database and then the code doesnt need to be change, but sadly it usually involves writing a new strategy entirely. hard to predict...
Would it be appropriate to use this same distinction to help understand when to put constraints into your Database schema, versus when to do validation in application?
Suggestion to create Quantity value type earned my like and sub.
Thank you. Very interesting and useful knowledge!
So it is this ok that validations rules to stay in an outer layer(not domain layer),may be the application layer which is the domain layer client?Thnk you?
Derek, how you'd handle business rules that are tightly coupled to the user interface? I'm afraid I'm putting too much work in my frontend, dealing with business rules in the frontend which is a bad sign.
Task based UI's guiding the client, often with Hypermedia to drive the UI. ruclips.net/video/OcWa0WJBF2U/видео.html
So as i understood trivial validation should be stored in the application service layer, not in the aggregate as invariants ,is this correct ?Thank you!
Would someone in the business talk about an email address being valid apart of some business workflow or process? If not, it's probably not domain logic.
super explanation
I wonder hearing your ideas about using fluent validation, validating rules there, making db calls to know if command's parameters are valid
very helpful, thank you Derek.
Glad it was helpful!
While I agree there's a distinction, I don't agree with your example. For me business logic is where knowledge of the domain is vital, everything else is validation. You can sense check this by removing all the domain ubiquitous language, transpose into another domain and if it still makes sense then it's probably not domain logic.
Taking quantity
See it absolutely the same way. Very good comment!
Thanks for the comment. I can see your argument. "you can't ship 0 products" isn't a domain rule the same as you're birthday can't be 3000-02-01. It's not logically valid. As for being deterministic, why do people mock so much (not that I agree with it)? It's because they want the dependencies in their tests to be deterministic. The state isn't deterministic depending on how you're getting it. In my example it was because the state was event sourced. I do appreciate the comment, honestly.
@RobLang "For me business logic is where knowledge of the domain is vital, everything else is validation"... And don't you need domain knowledge to perform validations?
"You can do this by removing all the domain ubiquitous language, transpose into another domain and if it still makes sense then it's probably not domain logic." Ever heard of shared kernels? There can be concepts that are used by many domains, you cannot guarantee they are exactly the same though, different domains => different perspectives. But there still can be some shared knowledge.
Interesting note about the quantity. You made me realize it's kinda misleading, but not for the reason you provided. You say quantity isn't a domain term, but how isn't it? Isn't it literally the name of the argument my domain service asks to be provided? The reason it's wrong is that 0 is a quantity. I can say I have 0 apples. And it's hard to give a domain name to implement this type of requirement. Maybe SomeQuantity? lol better than repeating the same validation check everywhere, even if trivial.
I don't get why when the logic is not from >your< business domain, u guys say it's not domain/business logic. It's just that it's logic from another domain, not that it's not domain logic...
@@CodeOpinion as soon as you use domain language to describe a problem, it's domain logic. You can't get round that. You can't ship 0 products. "Ship" is domain language because what it means to ship something differs between domain. I guarantee systems have work-around where a customer is charged but nothing is shipped. Birth date is different because everyone on the planet has one, it's not unique to a given domain. It's globally ubiquitous.
My definition of deterministic is mathematical/scientific. Everything is repeatable unless you're using System.Random without setting the seed. You can absolutely reproduce event stream state in unit tests; I've done it (and we were using Event Store back then).
Really love the video though, feels like I'm splitting hairs with this!
@@henriquesouza5109 most validation is performed by the type system "ABC" is not an integer. I don't need domain knowledge to know that ABC is not an integer. You can't be born in the future. That's not unique to any domain, that's globally understood.
Quantity is a domain term, I think you misread my comment.
Different domains have their own domain logic. They own it themselves. Even in the same industry.
"Simple" validations are as much a business rule as any other invariant, the fact it went from 'not null' to 'check w/15 other services to derive the validity' makes no difference.
In the example here, the use of an int for the representation of a physical quantity is where the problem lies. No matter the business, negative physical quantities don't exist. The fact that a business does not accept the registration of a shipment unless the quantity is below the physical stock is a business rule. A different business may allow such a registration, as long as some other criterion is met. Shipping negative quantities of goods is impossible for any business, so there is a distinction between the two cases.
I agree that everything is a business rule. I would argue that using the quantity class is enforcing that business rule. However, I think it is still valid to remove the primitive int from the method declaration. Especially since the logic was occurring across multiple methods.
So you would say that a valid email address is a business rule? or a phone number is a business rule?
@@CodeOpinionAlways valid entities is a concept every domain/business should hold. Now for the validation check, it's of the email business responsibility to check if the email is valid, and of the phone number business responsibility to check if it is valid. Of course its very likely that it isn't responsibility of the business you work on, if it ships products or w/e, your business should assume valid email or phone numbers, but that doesn't mean they don't belong to any business.
Sorry for so many edits, my english is bad :P
@CodeOpinion if a valid email is a concept that my business uses than its part of my business rules. I would handle it in the same way as the Quantity object, with an Email object.
This is gold.
Derek, what is your opinion about the externalization of business logic with BPMN-based business rule tasks and DMN-based decision models? Speaking of process and rules engines like Camunda.
Very useful, thanks ❤
If you can explain a line of code with an existing product backlog item then it's most likely a business rule
Great video! Thanks a lot!
May I nitpick regarding your terminology? When you say ”deterministic”, I think you mean “functional” (as in functional programming).
I doubt that much business logic is based on randomness.
Sorry for complaining on such a detail in such an amazing video!
No, I mean deterministic. Same input will always produce the same output.
en.wikipedia.org/wiki/Deterministic_algorithm
@@CodeOpinion Sorry and thanks :) It seems to mean something very similar, and I would still call a program filled with global variables ”deterministic” although it can be hard to follow.
Hey Derek,
First of all a great video as always. I have a couple of thoughts on this topic - I think in your explanation you've mixed up a couple of different and distinctive approaches to layering/segregation and I would like to hear your thoughts on this opinion. The following is my IMHO and not critique or challenge ;)
The refactoring you did was completely logical, but not based on the separation of validation rules and business rules, but rather segregation of rules to their domains (you mentioned this later in the video). The positive quantity validation is a "rule of a product quantity", independently of where it is used (in this context), while quantity being more or equals to the available amount is a "warehouse order rule". So this resolves more around segregation of concerns and not application layers. What you mention as validation logic being set in stone is because the scope of "product quantity" is and has always been more standardized, I mean, we have thousands of ecommerce engines and this is a standard rule for all of them and we think it's set in stone, while, let's say for an example, business wants to sell some product only in batches of 3 and 5, so you would validate quantity for qty > 0 AND (qty%3 OR qty%5), and what's worse it should happen much earlier than order placing - somewhere while forming the order, at this moment the "rule of product quantity" becomes a business logic and not validation. Or vice versa, you no longer need the "warehouse order rule" of limiting the order amount (for example, if you're not only a warehouse, but a production company) and only limit to a sane amount defined by one of the production line managers.
I hope I was elaborate enough and did explain clearly. From my experience, I really don't like the definition of "business rules", everything that is not a technical limitation would or can be called a business rule at some point if your business is creative enough :) What are your thoughts?
Thanks for the comment. Yes, I see your argument and in the product quantity example you gave, I'd relate that to more domain specific. A few other comments have made a similar argument that "Quantity" is a domain concept. I'd argue it's not by itself, unless you have some non-conformity like you just described. As a similar example to that, an Email address associated to a customer isn't a domain concept. It's universally understood. If however you only accepted email addresses with a ".ca" (I'm Canadian eh!), then that to me differentiates it. Credit Cards, Phone Numbers, Time zones (IANA), the list goes on for me. At the end of the day, I want to separate complex logic that's specific to MY business. Appreciate the comment. We might be splitting hairs.
@@CodeOpinion Thank you for the reply! I love refactoring topics and moving things around, always interesting to hear the thought process of other people.
It' a bit strange for me that WarehouseProduct has method ShipProduct and apply. Is it normal approach in DDD that business objects are self awareness and work as use cases? I'm beginner in this topic of DDD, but it indicates that WarehouseProduct can consume any other business objects as dependencies?
Just out of curiosity: Sometimes you need to determine if a button which executes an action is shown based on the rules you showed. How can this be achieved?
Hypermedia. Passing down the actions that are possible/not to the client so they know what they can or cannot do. ruclips.net/video/OcWa0WJBF2U/видео.html
@CodeOpinion thanks. But it was more related to: Where do I put these rules in the code? I don’t want to repeat myself.
@@Alex-lu4po It's a UI-only concern. Business rules come in layers. Your UI has its own set of business rules, distinct of your data process business rules. So if you have a UI that needs to make a decision, that decision will be evaluated and be made on the UI. Once the button is clicked, some other layer of your project will process the data according to its own business rules.
@@Marfig but then I have to duplicate logic…
@@Alex-lu4po Don't see how. You'd need to be more specific. (And btw... just a side-note here: duplicate code is not so bad as people point out. Embrace duplicate code when you need it. Don't always try to get away from doing it.)
Hah! I've been calling it "trivial validation" for a little while now. I'm just going to assume this is a term you've used previously in a video or blog and I just picked it up. =)
Ya, I often call it that or superficial
I can't agree with deeming this logic as trivial and therefore not business rules - bit of a judgment call in my opinion but in the end it doesn't affect things much. Regardless that logic should definitely be kept out of the UI. Also considering that the logic for the trivial validations is deterministic and static, wouldn't it be better to convert that logic into static functions instead of a record? That's literally the definition of a pure function.
I like the change of moving this to a non-primitive. (And great video and channel by the way, I really like it)
But, I do wonder...
Why is it not business logic to error when quantity is less than or equal to zero?
If I were running a pizza shop and someone said they'd like to order -100 pizzas, I would think that it reasonable that I ask whoever is answering phones to mention back to the caller that we can only fulfill pizza orders of at least 1 pizza. I would ask for them to do this for all orders
Why is that not a business rule?
And once again, thanks for all the great videos.
(I try to avoid mentioning a software system because the fact that it is software seems not to matter when sussing out business rules)
To the point ❤
Why do we see so many exceptions being thrown when business rules are not met? Is this really an exception or just a possible result of an operation?
Exceptions are just kinda easy to manage a categorize and handled differently based on that, i think that's why they are the best choice. So like what i like to do is i have two kind of exception, one is a 'buisness rule' kind, when i throw that, it just written out in a messagebox, and the other is the 'normal' exception, when that throw its logged and also provides a stacktrace in the messagebox for easy troubleshoot.
This way, all the 'communicatiom with the user' can be kept in one place, in the central exception handler, no need to have any specific thing. But also this needs to have the exception handling to be centralized to work well.
Result types (Either) are helpful when you expect a result and not an exception.
Great thank you!
New business rule: we don't send quantity less then 5
A good start! Generally speaking, if you code an "if" in your code, you are doing it wrong. Polymorphism and and OO patterns should alleviate that need.
But, this is just junior level thinking. In an enterprise setting, you should delegate validations of simple syntactic nature to OpenAPI3.0 definitions. More complicated true business logic should be delegated to an evaluation engine like RedHat Kogito. Again more jummy lose coupling and delegating things that change to definition files that can be changed in runtime.
There is no such thing as a "Business Rule" because there is no way to truly define what is a BR and what is not.
There are business rules, they are simply rules of a specific business (or domain), you just have to specify which business you're talking about before asserting stuff.
@@henriquesouza5109 I don't understand your statement
@@leonardomangano6861 Every rule is some business' rule, for instance, if your business problem is dividing numbers for example, warning your customer and also checking divisions by zero is your business responsibility. And in this case "you can't divide by zero" is a business logic (your business logic).
@@henriquesouza5109 is your db schema business logic?
@@leonardomangano6861 Why you asking this? lol a DB schema is not any logic, it's rather a structure that contains tables, constraints, indexes, etc. You can for sure define some simple business checks in it but it cant go much further than that. The structure you define for sure has relation with your business requirements, entities, relations and etc, but it's just how your domain projects into it, it's your entities projected into a table for example. It's just that DBs aren't expressive enough nor easily queryable for its definitions.
Isn't that a little bit too simple. By this example everything that is invariant is a validation, and everything that has parameters it has to adhere to is a business rule. I can't put my finger on what is astray, but this explanation seems too simplistic and one-dimensional. Are there really no invariant business rules? 🤔
Simply put, it's about primitive obsession :-)
This is the opinion of a man who has never shipped a stable production application in his life. You can safely ignore whatever Mr. IJobNativeParallelMultiHashMapMergedSharedKeyIndices has to say
Second
Im the first