eShopOnWeb Architecture (3/16) – uses custom exceptions to more explicitly express what has gone wrong

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…

BUT… Microsofts Best Practices for exceptions page recommends we only introduce new exceptions classes when predefined ones don’t apply

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.

eShopOnWeb Architecture (2/16) – uses Value Objects to model immutable domain concepts

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.

Using Records for Value Objects in C#?

Records were introduced in C#9 and give us built in immutability and comparison checks. Can we use them to model Value Objects? In many cases yes, but beware there are some limitations when using records over classes to model Value Objects as discussed by Vladimir Khorikov.

What does your typical Value Object implementation look like? Do you mostly use Records or Classes?

Using Guard Clauses to reduce nesting levels in our code

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.

The example above (it’s JavaScript but its the same kind of idea for all languages) is from Álvaro Trigos Twitter. Note the example is actually missing the throw keyword so code should be throw new Error(… etc. but hopefully you still get the idea.

What do you think? IMHO the code on the right is a lot easier to read.