<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta name="description" content="My little place where I write about things that interest me." />



  <title>Taking advantage of the type system (in C++) </title>



  <meta property="og:site_name" content="Krzysztof Hrynczenko&#x27;s Dev Diary">
  <meta property="og:title" content="Krzysztof Hrynczenko&#x27;s Dev Diary">
  <meta property="og:description" content="My little place where I write about things that interest me.">
  <meta property="og:url" content="https://www.blog.khrynczenko.com">
  <meta property="og:image" content="">
 <meta property="og:type" content="article" />
  <meta property="article:published_time" content="2021-02-16T00:00:00+00:00" />

 <link rel="prev" href="https://www.blog.khrynczenko.com/posts/post-2021-01-13-dependency-inversion-principle/" />
 <link rel="next" href="https://www.blog.khrynczenko.com/posts/post-2021-03-30-arm-assembly-1/" />
  <style>
html,body{background:rgba(245,242,240,0.168627);color:#000;font-family:Helvetica, Roboto, Arial, sans-serif;font-size:18px;line-height:1.6em;margin:auto;max-width:50rem}blockquote{font-style:italic}.post-list{list-style-type:none;margin:0;padding:0}nav{word-spacing:200%}h1,h2,h3,h4,h5,h6{color:#cb4b16}a,a:visited{color:#d13812;text-decoration:none}a:hover{text-decoration:underline}pre{overflow:scroll;padding:1rem}img{height:auto;max-width:100%}

  </style>

</head>

<body>
<vid>

<header>
    <h1><a href="https://www.blog.khrynczenko.com">Krzysztof Hrynczenko&#x27;s Dev Diary</a></h1>
    <h2>My little place where I write about things that interest me.<h2>
</header>

<hr />
<main>
  
<article>
<h1 class="title">
  Taking advantage of the type system (in C++)
</h1>
<p class="subtitle"><strong>Posted on February 16, 2021</strong></p>
<p><blockquote>
<p>This article was originally written as a blog post for the
<a href="https://bulldogjob.pl"><strong>Bulldogjob</strong></a>
blog. I am thankful to both <strong>Bulldogjob</strong> and my company <strong>Rockwell
Automation</strong> for the opportunity to work on it and publishing it.
You can find the original version
<a href="https://bulldogjob.pl/articles/1265-taking-advantage-of-the-type-system-in-c">here</a>.</p>
</blockquote>
<h2 id="introduction">Introduction</h2>
<p>After working on several projects now I believe that people do not use
facilities that come with using compiled programming languages that have
capable type systems such as C++, C, Java etc. I found that programmers often
too much rely on the primitive types and run-time checking which often leads to
bugs that are often hard to detect. In this article I would like to present
simple techniques to make your code less error-prone, more readable, and
maintainable, simply by using types.</p>
<h2 id="example">Example</h2>
<p>Let us start with an example of a code that we will improve step by step
throughout the article. Assume that we are working on a shipping/ordering
software for a coal selling company. Inside there is a system that is
responsible for initiating a shipping process with a given amount of coal
to a customer.</p>
<pre style="background-color:#282a36;">
<code class="language-C++" data-lang="C++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Address </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">Address</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#50fa7b;">Address</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">street</span><span style="color:#f8f8f2;">,
        std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">city</span><span style="color:#f8f8f2;">,
        std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">zip_code</span><span style="color:#f8f8f2;">,
        std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">country</span><span style="color:#f8f8f2;">);

    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string street;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string city;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string zip_code;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string country;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Customer </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">first_name</span><span style="color:#f8f8f2;">, std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">last_name</span><span style="color:#f8f8f2;">, Address </span><span style="font-style:italic;color:#ffb86c;">address</span><span style="color:#f8f8f2;">);
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string first_name;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string last_name;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Address address;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">; 
 
</span><span style="font-style:italic;color:#8be9fd;">void </span><span style="color:#50fa7b;">ship_order</span><span style="color:#f8f8f2;">(Customer </span><span style="font-style:italic;color:#ffb86c;">customer</span><span style="color:#f8f8f2;">, std</span><span style="color:#ff79c6;">::</span><span style="font-style:italic;color:#66d9ef;">uint16_t </span><span style="font-style:italic;color:#ffb86c;">amount</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
    </span><span style="color:#6272a4;">// initiate shipping
</span><span style="color:#ffffff;">}

</span></code></pre>
<p>We can see that we have a <code>ship_order</code> function that is responsible for the
shipping. It takes two parameters, one of which is a <code>Customer</code> structure
with all the required details related to the customer. The second parameter is
related to the amount of coal that should be delivered.</p>
<h2 id="simple-types">Simple types</h2>
<p>Let us focus on the first function parameter – the <code>customer</code> parameter. If we
look at the structure definition a couple of things should raise your
awareness.  The first and the last name of the customer are defined as strings.
But is it correct? The type tells us that for example the name of the user can
be “Android-321#@!”. This is a valid string, unfortunately this is not a valid
name. This is an example of a simple type, a type which is represented by a
primitive type, but it is not exactly the same. One could argue that these
values for the first name and the last name could be checked inside the
constructor like below.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string first_name, std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string last_name, Address address)
    </span><span style="color:#ff79c6;">: </span><span style="color:#50fa7b;">first_name</span><span style="color:#f8f8f2;">(first_name)
    , </span><span style="color:#50fa7b;">last_name</span><span style="color:#f8f8f2;">(last_name)
    , </span><span style="color:#50fa7b;">address</span><span style="color:#f8f8f2;">(address) </span><span style="color:#ffffff;">{
    </span><span style="color:#ff79c6;">if </span><span style="color:#f8f8f2;">(</span><span style="color:#ff79c6;">!</span><span style="color:#50fa7b;">is_name_valid</span><span style="color:#f8f8f2;">(first_name) </span><span style="color:#ff79c6;">|| !</span><span style="color:#50fa7b;">is_name_valid</span><span style="color:#f8f8f2;">(last_name)) </span><span style="color:#ffffff;">{
        </span><span style="color:#ff79c6;">throw </span><span style="color:#f8f8f2;">std</span><span style="color:#ff79c6;">::</span><span style="color:#50fa7b;">invalid_argument</span><span style="color:#f8f8f2;">(</span><span style="color:#f1fa8c;">&quot;Invalid name&quot;</span><span style="color:#f8f8f2;">);
    </span><span style="color:#ffffff;">}
}
</span></code></pre>
<p>While this might look good at first glance, this approach is severely lacking.
Firstly, this requires us to vide into implementation of the <code>Customer</code>
structure to be sure that the names are validated. Secondly this approach does
not scale well. If there are other places where we would like to represent
names without the <code>Customer</code> structure we will need to again make sure that
those are valid. This puts a lot of responsibility to keep the integrity of the
system on our shoulders. We start to rely on the fact that nobody has made a
mistake, and all the logic that touches such variables will always be correct.
In a small codebase this all might seem to be okay and trackable, but I hope
you can imagine that when the code grows this might get problematic
(from my experience it always does). I hope you see now that we can do better.</p>
<h2 id="maintaining-integrity-with-simple-types">Maintaining integrity with simple types</h2>
<p>We are now going to tackle the problem of keeping the integrity within our
system throughout its lifetime. We start from introducing a new type which
will take role of representing names.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Name </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">Name</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#ff79c6;">explicit </span><span style="color:#50fa7b;">Name</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">name</span><span style="color:#f8f8f2;">);
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string value;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
</span></code></pre>
<p>Now we replace the old string types from the <code>Customer</code> type with the <code>Name</code>
type.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Customer </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">(Name </span><span style="font-style:italic;color:#ffb86c;">first_name</span><span style="color:#f8f8f2;">, Name </span><span style="font-style:italic;color:#ffb86c;">last_name</span><span style="color:#f8f8f2;">, Address </span><span style="font-style:italic;color:#ffb86c;">address</span><span style="color:#f8f8f2;">)
        : </span><span style="color:#ffffff;">first_name</span><span style="color:#f8f8f2;">(first_name)
        , </span><span style="color:#ffffff;">last_name</span><span style="color:#f8f8f2;">(last_name)
        , </span><span style="color:#ffffff;">address</span><span style="color:#f8f8f2;">(address) </span><span style="color:#ffffff;">{
    }
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Name first_name;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Name last_name;
   </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Address address;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
</span></code></pre>
<p>Just by doing that we now do not mislead people into believing that the name
variables can hold anything that string can (not entirely, but more on that
later). Moreover, as long as the value of the type <code>Name</code> can only be built
with valid string we now can be sure that where a value of the type <code>Name</code> is
present, there is no need to check whether it is valid.</p>
<p>The validation could look similarly to what we had present in the <code>Customer</code>
structure before.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Name </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">Name</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#ff79c6;">explicit </span><span style="color:#50fa7b;">Name</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">name</span><span style="color:#f8f8f2;">) : </span><span style="color:#ffffff;">value</span><span style="color:#f8f8f2;">(name) </span><span style="color:#ffffff;">{
        </span><span style="color:#ff79c6;">if </span><span style="color:#f8f8f2;">(</span><span style="color:#ff79c6;">!</span><span style="color:#50fa7b;">is_name_valid</span><span style="color:#f8f8f2;">(name)) </span><span style="color:#ffffff;">{
            </span><span style="color:#ff79c6;">throw </span><span style="color:#f8f8f2;">std</span><span style="color:#ff79c6;">::</span><span style="color:#50fa7b;">invalid_argument</span><span style="color:#f8f8f2;">(</span><span style="color:#f1fa8c;">&quot;Invalid name.&quot;</span><span style="color:#f8f8f2;">);
        </span><span style="color:#ffffff;">}
    }
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string value;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
</span></code></pre>
<p>What if the requirements for a valid name differ between the first name and the
last name? For example a first name cannot contain the hyphen (-) sign but a
last name can (two part last names are completely valid and not that uncommon).
We can just create two independent types that apply their own business rules.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">FirstName </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#ff79c6;">explicit </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">name</span><span style="color:#f8f8f2;">);
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string value;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">LastName </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">LastName</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#ff79c6;">explicit </span><span style="color:#50fa7b;">LastName</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">name</span><span style="color:#f8f8f2;">);
  </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string value;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Customer </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">(FirstName </span><span style="font-style:italic;color:#ffb86c;">first_name</span><span style="color:#f8f8f2;">, LastName </span><span style="font-style:italic;color:#ffb86c;">last_name</span><span style="color:#f8f8f2;">, Address </span><span style="font-style:italic;color:#ffb86c;">address</span><span style="color:#f8f8f2;">)
        : </span><span style="color:#ffffff;">first_name</span><span style="color:#f8f8f2;">(first_name)
        , </span><span style="color:#ffffff;">last_name</span><span style="color:#f8f8f2;">(last_name)
        , </span><span style="color:#ffffff;">address</span><span style="color:#f8f8f2;">(address) </span><span style="color:#ffffff;">{
    }
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> FirstName first_name;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> LastName last_name;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Address address;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
</span></code></pre>
<p>Personally, even if the rules were the same, I would still make two separate
types for them to keep them distinct. This would enforce the compiler to issue
an error if someone tried passing a first name argument to the function that
wanted last name. Some people might find it a little of an overkill, I do not.
I believe in taking advantage and removing possibility for error where
possible, but of course all use cases vary, and you should use your own
judgment.</p>
<p>We should not forget about our <code>Address</code> structure. Obviously addresses, zip
codes, and countries cannot hold just any string. I believe that you can figure
it out yourself now how we apply the same technique there. Now our <code>Customer</code>
and <code>Address</code> structure should look something like below.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Address </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">Address</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#50fa7b;">Address</span><span style="color:#f8f8f2;">(Street </span><span style="font-style:italic;color:#ffb86c;">street</span><span style="color:#f8f8f2;">, City </span><span style="font-style:italic;color:#ffb86c;">city</span><span style="color:#f8f8f2;">, ZipCode </span><span style="font-style:italic;color:#ffb86c;">zip_code</span><span style="color:#f8f8f2;">, Country </span><span style="font-style:italic;color:#ffb86c;">country</span><span style="color:#f8f8f2;">);
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Street street;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> City city;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> ZipCode zip_code;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Country country;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Customer </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#50fa7b;">Customer</span><span style="color:#f8f8f2;">(FirstName </span><span style="font-style:italic;color:#ffb86c;">first_name</span><span style="color:#f8f8f2;">, LastName </span><span style="font-style:italic;color:#ffb86c;">last_name</span><span style="color:#f8f8f2;">, Address </span><span style="font-style:italic;color:#ffb86c;">address</span><span style="color:#f8f8f2;">);
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> FirstName first_name;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> LastName last_name;
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Address address;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="font-style:italic;color:#8be9fd;">void </span><span style="color:#50fa7b;">ship_order</span><span style="color:#f8f8f2;">(Customer </span><span style="font-style:italic;color:#ffb86c;">customer</span><span style="color:#f8f8f2;">, std</span><span style="color:#ff79c6;">::</span><span style="font-style:italic;color:#66d9ef;">uint16_t </span><span style="font-style:italic;color:#ffb86c;">amount</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
    </span><span style="color:#6272a4;">// initiate shipping
</span><span style="color:#ffffff;">}
</span></code></pre>
<p>This code looks much less worrisome now. Additionally, we restricted validation
code only to the constructors for the simple types. No more relying on yourself
and other programmers to keep all the values proper and validating them all
over the place. Yet there is still some room for improvement.</p>
<h2 id="representing-units-of-measure">Representing units of measure</h2>
<p>Now let us take care of the second parameter of the <code>ship_order</code> function. This
parameter corresponds to the amount of coal to be shipped to a customer.
Its type is a 16-bit unsigned integer. Looking at the interface of a function
we cannot really know what units of weight it uses and if there are any
restrictions on a shipped amount. From the requirements we obtained from the
client we gathered that we cannot ship more than 10000 kg of coal. That is
probably why 16-bit unsigned integer was used, since it is the smallest integer
type that can hold value of 10000. If we were a little bit luckier someone
would add the name of the unit to the parameter name like so.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">void </span><span style="color:#50fa7b;">ship_order</span><span style="color:#f8f8f2;">(Customer </span><span style="font-style:italic;color:#ffb86c;">customer</span><span style="color:#f8f8f2;">, std</span><span style="color:#ff79c6;">::</span><span style="font-style:italic;color:#66d9ef;">uint16_t </span><span style="font-style:italic;color:#ffb86c;">amount_kg</span><span style="color:#f8f8f2;">);
</span></code></pre>
<p>While this somewhat improves things and makes it more obvious someone can still
make a simple mistake and pass a value that does not correspond to kilograms.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">void </span><span style="color:#50fa7b;">resolve_order</span><span style="color:#f8f8f2;">(</span><span style="color:#6272a4;">/* ... */</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
    </span><span style="color:#6272a4;">// ..
</span><span style="color:#f8f8f2;">    std</span><span style="color:#ff79c6;">::</span><span style="font-style:italic;color:#66d9ef;">uint16_t</span><span style="color:#f8f8f2;"> tons_to_send </span><span style="color:#ff79c6;">= </span><span style="color:#50fa7b;">parse_amount</span><span style="color:#f8f8f2;">(form);
    </span><span style="color:#50fa7b;">ship_order</span><span style="color:#f8f8f2;">(customer, tons_to_send);
</span><span style="color:#ffffff;">}
</span></code></pre>
<p>This code would compile without emitting any error, not even a warning. This is
a type of a problem that is hard to detect before it shows in the production,
and even then, finding it is a tedious process. Any compiler will help us with
such problems if we just give him a little more concrete information.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">enum class </span><span style="color:#f8f8f2;">WeightUnit </span><span style="color:#ffffff;">{
</span><span style="color:#f8f8f2;">    MG,
    G,
    KG,
    T,
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="font-style:italic;color:#8be9fd;">template</span><span style="color:#f8f8f2;">&lt;WeightUnit&gt;
</span><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">Weight </span><span style="color:#ffffff;">{
</span><span style="color:#ff79c6;">public</span><span style="color:#f8f8f2;">:
    </span><span style="color:#ff79c6;">explicit </span><span style="color:#50fa7b;">Weight</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="font-style:italic;color:#66d9ef;">size_t </span><span style="font-style:italic;color:#ffb86c;">amount</span><span style="color:#f8f8f2;">) : </span><span style="color:#ffffff;">amount</span><span style="color:#f8f8f2;">(amount) </span><span style="color:#ffffff;">{
    }
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="font-style:italic;color:#66d9ef;">size_t</span><span style="color:#f8f8f2;"> amount;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="font-style:italic;color:#8be9fd;">void </span><span style="color:#50fa7b;">ship_order</span><span style="color:#f8f8f2;">(Customer </span><span style="font-style:italic;color:#ffb86c;">customer</span><span style="color:#f8f8f2;">, Weight&lt;WeightUnit</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">KG&gt; </span><span style="font-style:italic;color:#ffb86c;">amount</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
    </span><span style="color:#6272a4;">// initiate shipping
</span><span style="color:#ffffff;">}
</span></code></pre>
<p>We introduced a new enumerator that describes what unit of weight we are using.
Moreover, we introduced a new weight type that stores the amount under a given
unit. It has a template parameter that corresponds to the weight unit and that
must be provided at compile time. Now if we would try to do the same as in the
example before the compiler would gracefully emit an error and save us from
a lot of trouble.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">void </span><span style="color:#50fa7b;">resolve_order</span><span style="color:#f8f8f2;">(</span><span style="color:#6272a4;">/* ... */</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
    </span><span style="color:#6272a4;">// ..
</span><span style="color:#f8f8f2;">    Weight&lt;WeightUnit</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">T&gt; tons_to_send </span><span style="color:#ff79c6;">= </span><span style="color:#50fa7b;">parse_amount</span><span style="color:#f8f8f2;">(form);
    </span><span style="color:#50fa7b;">ship_order</span><span style="color:#f8f8f2;">(customer, tons_to_send); </span><span style="color:#6272a4;">// This no longer compiles!
</span><span style="color:#ffffff;">}
</span></code></pre>
<p>This will no longer compile thus providing the type-safety we want (the kg unit
is expected). This is a rather bare-bones approach to this problem, but it
shows once again that we can use type-system to our advantage. I specifically
omitted any details regarding conversion between different weight units to not
cloud the general idea and keep the article concise. There are many ways to
tackle this problem and there are some battle tested libraries that do that,
you don’t have to solve it yourself (though it is not that hard). There is a
<em>Boost Units</em> library or the work in progress <em>units</em> library that can help you
with the problem of working with units.</p>
<p>As for the second requirement that the shipped amount should not exceed 10000
kg I think we already know how to approach it now. We introduce a new simple
type of course.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">ShippedAmount </span><span style="color:#ffffff;">{
    </span><span style="color:#ff79c6;">explicit </span><span style="color:#50fa7b;">ShippedAmount</span><span style="color:#f8f8f2;">(Weight&lt;WeightUnit</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">KG&gt; </span><span style="font-style:italic;color:#ffb86c;">amount</span><span style="color:#f8f8f2;">) : </span><span style="color:#ffffff;">amount</span><span style="color:#f8f8f2;">(amount) </span><span style="color:#ffffff;">{
        </span><span style="color:#ff79c6;">if</span><span style="color:#f8f8f2;">(amount </span><span style="color:#ff79c6;">&gt; </span><span style="color:#50fa7b;">Weight</span><span style="color:#f8f8f2;">&lt;WeightUnit</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">KG&gt;(</span><span style="color:#bd93f9;">10000</span><span style="color:#f8f8f2;">)) </span><span style="color:#ffffff;">{
            </span><span style="color:#ff79c6;">throw </span><span style="color:#f8f8f2;">std</span><span style="color:#ff79c6;">::</span><span style="color:#50fa7b;">invalid_argument</span><span style="color:#f8f8f2;">(</span><span style="color:#f1fa8c;">&quot;Shipping amount cannot exceed 10&#39;000 kilograms.&quot;</span><span style="color:#f8f8f2;">);
        </span><span style="color:#ffffff;">}
    }
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> Weight&lt;WeightUnit</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">KG&gt; amount;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="font-style:italic;color:#8be9fd;">void </span><span style="color:#50fa7b;">ship_order</span><span style="color:#f8f8f2;">(Customer </span><span style="font-style:italic;color:#ffb86c;">customer</span><span style="color:#f8f8f2;">, ShippedAmount </span><span style="font-style:italic;color:#ffb86c;">amount</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
    </span><span style="color:#6272a4;">// initiate shipping
</span><span style="color:#ffffff;">}
</span></code></pre>
<p>Now, if we need to use values that are shipping amounts in other places in the
code, the validation stays in one place only and we can be sure that everything
stays correct.</p>
<h2 id="documenting-effects-and-working-with-errors">Documenting effects and working with errors</h2>
<p>To that point I omitted one problem that kept one showing in several places.
That is the problem of validation in constructors that is not in any way
showcased by the interface of those constructors. Below is the <code>FirstName</code>
class that was shown earlier.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">FirstName </span><span style="color:#ffffff;">{
    </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#ff79c6;">explicit </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">name</span><span style="color:#f8f8f2;">);
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string value;
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
</span></code></pre>
<p>One small problem is that we use an exception for something that really is not
an exception, and we force on the user of the class to perform exception
handling which has its own issues. More importantly the signature of the
constructor does not say much about that it performs any kind of validation.
How is a user supposed to know that he has to handle possible exceptions?
One way of approaching that would be to introduce exception list like below.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="color:#ff79c6;">explicit </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string name) </span><span style="color:#ff79c6;">throw</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">invalid_argument);
</span></code></pre>
<p>This at least somehow tells the reader that this function might throw,
which would indicate some kind of validation, especially if we would create
our own exception type with a better name. Unfortunately, we still use
exceptions, so it solved only part of the problem. Moreover, exceptions
specifications have been deprecated since C++11 and removed in C++17. There
must be another way.</p>
<p>Of course, once again we can use types. For errors specifically C++ introduces
new std::optional type (since C++17). This type is a representation for a value
that might be present or might be missing (due to something that happened).
Let us try to use it. We will need to slightly refactor our class.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">struct </span><span style="color:#f8f8f2;">FirstName </span><span style="color:#ffffff;">{
    </span><span style="color:#ff79c6;">static</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">optional&lt;FirstName&gt; </span><span style="color:#50fa7b;">Create</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">name</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
        </span><span style="color:#ff79c6;">if </span><span style="color:#f8f8f2;">(</span><span style="color:#ff79c6;">!</span><span style="color:#50fa7b;">is_name_valid</span><span style="color:#f8f8f2;">(name)) </span><span style="color:#ffffff;">{
            </span><span style="color:#ff79c6;">return</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">nullopt;
        </span><span style="color:#ffffff;">}
        </span><span style="color:#ff79c6;">return </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">(name);
    </span><span style="color:#ffffff;">}
    </span><span style="color:#ff79c6;">const</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string value;
</span><span style="color:#ff79c6;">private</span><span style="color:#f8f8f2;">:
    </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">() </span><span style="color:#ff79c6;">= delete</span><span style="color:#f8f8f2;">;
    </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">name</span><span style="color:#f8f8f2;">) : </span><span style="color:#ffffff;">value</span><span style="color:#f8f8f2;">(name) </span><span style="color:#ffffff;">{}
}</span><span style="color:#f8f8f2;">;
</span></code></pre>
<p>Since now we want to showcase that the creation of the <code>FirstName</code> class can
fail we need to use separate static function instead of constructor.
Constructor cannot return different type that the class it belongs to. And we
want to return <code>std::optional&lt;FirstName&gt;</code> to indicate that possible failure.
To do that we make our constructor private and call it from the new static
public function that performs the validation. If the validation succeeds we
return the valid <code>FirstName</code>, else we return <code>std::nullopt</code> which represents
missing value. Let us take a look on how using this class might look now. First
we replace the call to the constructor, with the call to the <code>Create</code> function.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="color:#f8f8f2;">Customer </span><span style="color:#50fa7b;">parse_customer</span><span style="color:#f8f8f2;">(</span><span style="color:#6272a4;">/* ... */</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
    </span><span style="color:#6272a4;">// …
    </span><span style="font-style:italic;color:#8be9fd;">auto</span><span style="color:#f8f8f2;"> first_name </span><span style="color:#ff79c6;">= </span><span style="color:#f8f8f2;">FirstName</span><span style="color:#ff79c6;">::</span><span style="color:#50fa7b;">Create</span><span style="color:#f8f8f2;">(some_value);
    </span><span style="color:#50fa7b;">use_first_name</span><span style="color:#f8f8f2;">(first_name); </span><span style="color:#6272a4;">// Wrong type!
</span><span style="color:#ffffff;">}
</span></code></pre>
<p>This code will not compile yet. Now whenever someone wants to create value of
type <code>FirstName</code> they must check whether the creation succeeds. There will be
no unhandled exceptions anymore. The proper way to do this will look as
follows.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="color:#f8f8f2;">Customer </span><span style="color:#50fa7b;">parse_customer</span><span style="color:#f8f8f2;">(</span><span style="color:#6272a4;">/* ... */</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
    </span><span style="color:#6272a4;">// ...
    </span><span style="font-style:italic;color:#8be9fd;">auto</span><span style="color:#f8f8f2;"> first_name </span><span style="color:#ff79c6;">= </span><span style="color:#f8f8f2;">FirstName</span><span style="color:#ff79c6;">::</span><span style="color:#50fa7b;">Create</span><span style="color:#f8f8f2;">(some_value);
    </span><span style="color:#ff79c6;">if </span><span style="color:#f8f8f2;">(first_name</span><span style="color:#ff79c6;">.</span><span style="color:#50fa7b;">has_value</span><span style="color:#f8f8f2;">()) </span><span style="color:#ffffff;">{
        </span><span style="color:#50fa7b;">use_first_name</span><span style="color:#f8f8f2;">(first_name);
    </span><span style="color:#ffffff;">} </span><span style="color:#ff79c6;">else </span><span style="color:#ffffff;">{
        </span><span style="color:#6272a4;">// handling code
    </span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
    </span><span style="color:#6272a4;">// ...
</span><span style="color:#ffffff;">}
</span></code></pre>
<p>To summarize, we addressed the issue that users were not aware of the
possibility of failure without looking into implementation. We also moved the
possibility of error from a run-time to compile-time. In other words, we made
our code less error-prone and achieved better documentation with code itself.</p>
<p>A question might arise, what if our validation would involve different checks
and we would like to inform the user what exactly went wrong instead of just
returning a missing value. We could simply use a variant that will store one of
two types, one will represent a possible error, and the second one will
represent a desired value.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="font-style:italic;color:#8be9fd;">enum class </span><span style="color:#f8f8f2;">ValidationError </span><span style="color:#ffffff;">{
</span><span style="color:#f8f8f2;">    NameContainsInvalidCharacters,
    NameTooLong,
</span><span style="color:#ffffff;">}</span><span style="color:#f8f8f2;">;
 
</span><span style="color:#ff79c6;">using </span><span style="color:#f8f8f2;">ValidationResult </span><span style="color:#ff79c6;">=</span><span style="color:#f8f8f2;"> std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">variant&lt;ValidationError, FirstName&gt;;
</span></code></pre>
<p>Now we just need to reflect this in our <code>Create</code> method.</p>
<pre style="background-color:#282a36;">
<code class="language-c++" data-lang="c++"><span style="color:#f8f8f2;">ValidationResult FirstName</span><span style="color:#ff79c6;">::</span><span style="color:#50fa7b;">Create</span><span style="color:#f8f8f2;">(std</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">string </span><span style="font-style:italic;color:#ffb86c;">name</span><span style="color:#f8f8f2;">) </span><span style="color:#ffffff;">{
   </span><span style="color:#ff79c6;">if </span><span style="color:#f8f8f2;">(</span><span style="color:#ff79c6;">!</span><span style="color:#50fa7b;">is_valid_name</span><span style="color:#f8f8f2;">(name)) </span><span style="color:#ffffff;">{
       </span><span style="color:#ff79c6;">return</span><span style="color:#f8f8f2;"> ValidationError</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">NameContainsInvalidCharacters;
   </span><span style="color:#ffffff;">}
   </span><span style="color:#ff79c6;">if </span><span style="color:#f8f8f2;">(</span><span style="color:#50fa7b;">is_too_long</span><span style="color:#f8f8f2;">(name)) </span><span style="color:#ffffff;">{
       </span><span style="color:#ff79c6;">return</span><span style="color:#f8f8f2;"> ValidationError</span><span style="color:#ff79c6;">::</span><span style="color:#f8f8f2;">NameTooLong;
   </span><span style="color:#ffffff;">}
 
   </span><span style="color:#ff79c6;">return </span><span style="color:#50fa7b;">FirstName</span><span style="color:#f8f8f2;">(name);
</span><span style="color:#ffffff;">}
</span></code></pre>
<p>Many other languages like Rust and Haskell have had such types for a long time
already, with much better language support for them. There is ongoing work to
add a type that will do what we need to the C++ standard library with all
auxiliary functionality attached, unfortunately there is no expected time of
arrival yet. Nonetheless like I presented already, we can build our own type
like that with <code>std::variant</code>.</p>
<h2 id="summary">Summary</h2>
<p>I hope that after reading this article you can see the benefits of properly
utilizing a type system. We refactored our initial code in a way that moves
possible errors from run-time to compile-time. We made it more obvious of what
values are expected inside our system and improved its integrity and
maintainability. At last, we now have explicit documentation for our functions,
not only about what values they take but also about the effects they carry. The
techniques I presented are only the basic ones when it comes to improving your
codebase with types. Depending on the language you use, some things might be
easier to do, some might not. If you are interested in more ways of bending the
compiler to your will, I encourage you to read some books on type-driven
development and domain driven design. There are many books that vide much
deeper into this topic and will show you some more sophisticated methods.</p>
</p>
</article>

</main>
<hr />

<nav>
  
  <a href="https:&#x2F;&#x2F;www.blog.khrynczenko.com&#x2F;about&#x2F;">About</a>
  <a href="https:&#x2F;&#x2F;www.blog.khrynczenko.com/atom.xml">Atom/RSS</a>
</nav>

<footer>
</footer>

</vid>
</body> 

</html>

