In the ApplicationCore project eShopOnWeb defines some custom exceptions…
This approach means we can raise strongly typed exceptions rather than throwing an InvalidOperationException (for example) with its string message property set. This in itself however isn’t a huge reason to use custom exceptions but…
… if we need to do something when we have an empty basket during checkout (for example) we can catch EmptyBasketOnCheckoutException rather than catching InvalidOperationException and string matching on its message property…
I guess what ‘doesn’t apply’ means is open to interpretation. For example can we consider trying to create an order for empty basket an invalid operation.. almost certainly yes.
What do you think? Do you regularly define custom exceptions or use built in ones where possible? IMHO throwing pre-defined exceptions is fine until we need to explicitly handle certain error scenarios differently than others. In this case I’d favour custom exceptions to avoid messy string matching in catch blocks.
Value Objects (VO) are a core part of DDD. A Value Object is an immutable type that is distinguishable only by the state of its properties, it doesn’t have the concept of identity.
Value Objects can better represent some domain concepts compared to entities
IMHO the main advantage of using Value Objects is that they can better represent and model certain real world concepts compared to regular entities with identities.
For example if we are dealing with money our domain might not care about the fact two $5 notes are different, for our business $5 is $5. If on the other hand we are some central bank or the US Fed and want to track the flow of currency in an economy then $5 with the serial number ABC is considered different than the $5 with the serial number XYZ.
Both domains above deal with money but how its handled and compared in each one is different. Value Objects give us the extra level of granularity needed to more correctly model this difference.
Always valid after creation
Another big benefit from using Value Objects comes from the fact they are immutable, this means once we validate them on creation we never have to worry about validation again. This can simplify our code base significantly.
We can see in eShopOnWeb that Address is a value object, after creation it is not possible to change its properties…
To keep things simple in this case we don’t have a full Value Object implementation as we don’t have logic for comparing two Value Objects together. This can be done a number of ways but a typical implementation is to use an abstract base class along with an overridden method in our derived Value Type which will return the list of properties we need to include when comparing two Value Objects.
File-level namespaces in C# 10 will help us remove a level of nesting in our code. This is helpful but.. actually the real problem with nesting doesn’t come from a language constraint but rather often comes from our coding style….
.. I’m referring to having multiple levels of nested if conditionals in a method. This is perfectly valid code but IMHO it can be hard to understand. A pseudo code example is below. This kind of code is often referred to as arrow anti pattern code as we can see that the indentation forms an arrow.
An alternative to nested ifs is to use guard clauses. This is where we test our conditionals early and exit the method immediately if anything is in a bad state. As we’ve tested our conditionals early our ‘Happy Path’ code (eg. the main thing the method does) is not buried in lots of if and else blocks.
What do you think? IMHO the code on the right is a lot easier to read.