Introduction

While Baklava is delicious for everybody, its technical pendant nBaclava might be delicious for you as a developer. nBaclava stands for "BAse CLAsses for VAlue objects" and gives you - well - base classes for value objects. If you are not familiar with value objects I recommend to read this article from Richard A. Dalton here on CodePrpject but I will give you a short introduction as well.

Within the domain driven design (DDD) a value object is describes as "an object that describes some characteristic or attribute but carries no concept of identity". For example the Point structure of the .net framework is a value object. It is defined by its x- and y-coordinate.

It might be obvious to you to define a point as its own type because the x- and y-coordinate seem very inseparable. So it is very common to combine them in a class or struct - that is what object oriented programming is for . But what about primitive values? Ever thought about defining a class for a string or an decimal? For example an email address is usually defined by a string and an amount is defined by a decimal. This seems to be good enough and a class which looks as followed seems to be oversized without adding something special to it:

Advantages of value objects

By definition, value objects should be immutable. This means that their values cannot be changed if set. This is a very important fact in functional programming as described by Marc Clifton here but the advantages for functional programming are more or less transferable to OOP.

Defining your own class - even for primitive values like string as shown above - gives you the potential to validate the used values. For example, you can throw an exception if your string does not represent a valid email address:

In combination with the concept of immutability you can now be sure to always have a valid email address. And it is a perfect central place for validation logic code which would otherwise be scattered in some utility classes.

Having your own type you are much more open to new functionality. Imagine that you will have to grab the top level domain of an email address within your program. Having email address just hanging around as a string you hopefully will not copy and paste the needed string operations every time you need them. Obviously you would end with a utility class again. But check out the possibility of a value object:

You can define plausible null values. For example String.Empty so that you do not have to check against null within your entire application.

And for free, you will get a much more structured, readable and expressive design of your software.

I hope you can see that there is much more potential within your usage of primitive values if you look twice and switch to value objects. Define "amount" instead using decimal directly and you automatically can round any value to a precision of two decimal places. Define "age" instead using an int and offer a calculated "YearOfBirth" property if required...

Disadvantages of value objects

Beside the fact that you will have to do some work in order to define your own types - even more if it is just for a primitive value - you might find it cumbersome to wrap values into classes and back again in order to use them in third party APIs (including the .net framework) because these APIs do not know your types and just offer the primitive values as method arguments or properties.

nBaclava

That is what nBaclava is for. It offers you base classes for value objects in general (as Point mentioned above) and for primitive values (as string and decimal) in particular. Furthermore there are some Visual Studio class templates to make its usage even simpler. Read on to learn about how nBaclava will support you on each concept of value objects.

ValueObject vs. PrimitiveValueObject

nBaclava offers two main types: ValueObject and PrimitiveValueObject. ValueObject is the base class for your complex types with more than one attributes (e.g. Point) whereas PrimitiveValueObjects encapsulate a single simple type (as string, decimal, etc.). For the last one nBaclava offers dedicated subclasses like StringValueObject or DecimalValueObject. PrimitiveValueObjects have a property named Value which holds the actual value (e.g. string). That is the same as on nullable types types like int? or DateTime?. So a simple starting point for your email address class would look like this:

So there is no need for using the inner value for this kind of operations. And the using of value objects is readable in a more natural manner.

Immutability

As said above value types should be immutable. This is mostly done by taking over the values within the constructor and just defining get on properties without their set pendants. But there are scenarios where this is not suitable. For example there are OR-Mappers which rely on parameterless default constructors. And for more complex objects it might be a good thing to set each property within a special building process instead of using a constructor with a lot of parameters.

So I decided to implement the freeze pattern. This means that an instance is mutable as long as the Freeze() method is called. So you can decide when it is time to freeze your objects.

Because PrimitiveValueObject has just one value you can shorten the freezing process by calling the base constructor with the concrete value and FreezingBehaviour.FreezeOnAssignment (have a look at the code snippets above).

This way the instance will automatically freeze on its first value assignment.

You will see that PrimitiveValueObject does not offer a setter for its Value property by default. Immutability was preferred by design. If you need a Value setter for your own types you will have to overwrite the property as follows:

CanFreeze (could be overwritten by you for your own types), IsFrozen and IsMutable.

Along with two event methods:

OnFreeze() and OnFrozen() which could be handled by you if you have to.

Once an object is frozen there is no way back!

Validity

Value objects should be valid by default or at least they should give you the possibility to check their validity. So you can check its IsValid property. Or you can call the Validate() method which throws an exception if the accordingly instance is in an invalid state. In order to just get the exception you can call TryValidate().

You will have to overwrite TryValidate() in order to define your own validation logic. By default all value objects are valid at all times.

To enforce validity you will have to call the base constructor with ValidityBehaviour.EnforceValidity (as shown above). This way Validate() is automatically called when a property changes its value.

For PrimitiveValueObjects you can overwrite OnValueChanging() in order to adapt a value before it is set (e.g. returning String.Empyt if null). So you can avoid an invalid state if suitable.

For ValueObject you should implement your properties as mentioned under Immutability.

Equality

As mentioned at the beginning, value objects are just described by their attributes. This leads to equality if all attributes of two value objects are equal. Compared to default classes which are only equal if their references point to the same memory location! Picking up Point again as an example you will agree that all points having x = 8 and y = 5 are the same point - regardless of their memory pointers. The base classes of nBaclava overwrite Equals() in order to fulfill this strategy. So you do not have to do anything special here – it’s all done! This was easy for PrimitiveValueObject because it just has one value to compare. For ValueObject all fields of your classes are collected per reflection and then their values are checked against each other. It is nearly the same as it is done by the .net framework within the ValueType class.

Null

Value objects give you the chance to define a suitable replacement for null by changing the given value before it is set (for example use OnValueChanging() for PrimitiveValueObjects). So there is no need for checking against null within the rest of your application.

If you need to store null as a valid value you will be glad to read that PrimitiveValueObjects which encapsulate a struct (e.g. decimal, int, DateTime, etc.) follow the nullable pattern so that you can use decimal? or int?, too.

Implicit conversion

PrimitiveValueObject provides implicit conversion to its encapsulated type. This way you can use your value object in any scenario where the base type is requested - e.g. as a method parameter or for variable assignments:

More conversions

Operators

There are some other operators defined for PrimitiveValueObject – not just the implicit conversion! So you can use the arithmetic operators like +, -, *, /, <, <=, >, >=, !=, == on numeric value types like DecimalObjectValue or IntValueObject.

In order to get this to work you will have to provide a constructor with one parameter – the value (as shown in the code above). And that is why your class needs itself as a generic parameter. This way nBaclava can construct your types on demand.

Visual Studio class templates

You can download a template package for nBaclava. It contains class templates for the PrimitiveValueObject definitions like DateTimeValueObject or StringValueObject and for the general ValueObject. So you are really fast in setting up your own value objects. In order to use the templates you will have to extract the package into your template folder. Look here if you do not know where to find or how to define it. After having these templates installed you will have a new category nBaclava when you call "Add – Class" within your project.

NuGet

nBaclava is also available as a NuGet package. Just search after nBaclava within the NuGet Package Manager.

Conclusion

If you can see the advantages of value objects but you are more or less too lazy to define them consistently within your applications then I hope that you will be much more consequent when you get help using nBaclava. If you are not of the lazy type I hope you will find it useful all the same

I would like to hear what you think about it? If you find it useful I will add support for the missing types like Int16, Int64, bool, etc. as well!

Comments and Discussions

I'm working up a proof-of-concept to use nBaclava in our application. I've built a series of tests to verify our requirements for such an implementation, and am having trouble implicitly converting an Int32ValueObject-based type to a nullable integer. Running the code below results in:

And you are right - for now, this is not supported. But that is more because I did not need it.
If you are interested in it, let me know - I will come back to you after my holidays.
I also would like to know if nBaclava was usefull for your application if you are going to use it.

I use value objects frequently. I consider they are much better than using attributes to define validations or what kind of information a field/property really holds.
As I use my own ORMs, I made them prepared to "user types", so they don't become a problem.
But my vote is 4, instead of 5, because I consider creating a base type for such value objects a performance killer. ValueObjects should be structs to have a good performance and also to avoid double null situations (the ValueObject can be null or its content can be null).
Also, even if the automatic equality is great, using reflection to get the values to them do the comparison is another performance killer.

I think that I don't tell you something new if I mention that the .net framework uses reflection a lot on its own. In particular if you have a look into the Equals method of the ValueType (run a decompiler) you will see that it just performs like my code (to be honest, my code performs like the .net code ). I agree with you on high performance critical requirements. But I think that reflection as a performance killer in general is rated too pessimistic. If you are in such a performance critical situation then you should stay away from ORMs, etc. either. But you won't ignore ORMs in general. I prefer to have a lot of utilities in my toolbox from which I can choose the right one in the right situation. But it's always good to point disadvantes out!

However, the null problem is a good point! I was aware of that but by using a factory/repository (looking from the Domain Driven Design) it was not a problem to me. There are by far too much discussions about when to use a struct and when a class...

Please, don't get me wrong - I appreciate your comments. But it's always hard to get a 100% solution

That's why I always reimplement the Equals and also use the generic IEquatable interface. I will really love to be able to create "base structs" (like abstract structs) that implement a common functionality and then "inherit" from them.

And for ORMs, I always use my own ORMs that perform a lot better than using DataTables. In fact, they use the ExecuteReader and avoid boxing... but I use a lot of Reflection.Emit to give the best possible performance.

This is a natural addition to your previous articles. It still looks like work in progress, but interesting concept nevertheless.

I don't think this is "over designing"... After all an email, for instance, is more than a string and should be treated differently; specially so if we have to validate it, convert it to and from other formats...

Hi,
thank your for taking time to read my article. I know it looks overdesigned (or oversized as I called it above) at first. But if you look at it with a "Domain Driven Design" or "Functional" background in mind (also mentioned above) you won't come over value objects - then it is by design!

I like the fact that my code expresses my domain. So if you write an email client it's worth to have an email type instead of just using a string. And if you want (or have!) to use value objects I think it's naturally to reduce effort - that's what this library is for.