February 22, 2018

RedStar.Amounts to Avoid Primitive Obsession

I’ve been programming for more than 10 years now, and only recently heard about Primitive Obsession. I’ve been guilty of this now and then. But I’ve also written/extended a library that tackles exactly that.

Primitive Obsession is the use of primitive data types (i.e. strings, integers, doubles, etc.) for simple tasks, instead of using small objects. Examples are currency, phone numbers, postal codes, etc.

Why would you not use primitive types for this? Surely a simple concept like a postal code or phone number doesn’t warrant the effort to write a class? But what starts with being just a property on another class, ends up with logic scattered all over the place (like validation or calculation logic).

Another example is amounts, units and measurements. Typically, you would see classes like this:

But if we have a Square with a SideLength of 20, what does that mean? 20 centimeters? 20 inches? 20 kilometers?

RedStar.Amounts can avoid this, precisely because it avoids the primitive obsession for this scenario. In the above example, we would change the class to this:

Now you can construct a Square like this:

Now you know what the dimensions of the square are, and when you call the GetSurface function, you will get another Amount as a result. That result will have 400m² as value.

Encapsulating simple concepts like that, instead of using primitives, has several advantages:

  • validation and/or calculation logic is centralized and can be tested
  • code becomes more readable
  • hard to find bugs are less likely to occur

I’ve used this library in similar forms before I took the original code (by Rudi Breedenraedt) and formalized it into RedStar.Amounts. The code is running in multiple industrial projects without any issues. I’ve also ported it to .NET Standard 2.0.

This library isn’t the only solution too avoid primitive obsession. For example, just doing a bit of searching learnt me there are solutions for money (NodaMoney, TeixeiraSoftware.Finance.Currency), and phonenumbers (PhoneNumbersCore).

Whatever your simple concept, it might be worth checking if there isn’t already a solution for it. If not, consider writing your own little class and expanding from there.

Leave a Reply

Your email address will not be published. Required fields are marked *