{
    "componentChunkName": "component---src-templates-post-page-js",
    "path": "/2019/error-handling-techniques",
    "result": {"data":{"site":{"siteMetadata":{"title":"Solid Abstractions","siteUrl":"https://solidabstractions.com","twitterId":291334023,"author":{"fullName":"Julien Hartmann","profileHtml":"I am an open-source de­vel­op­er, for­mer IT con­sul­tant with a pas­sion for new tech­nol­o­gies. I be­lieve the role of an en­gi­neer is to em­pow­er peo­ple, by as­sem­bling sim­ple, re­fined de­signs.\n","links":[{"url":"https://github.com/spectras/","name":"github","title":"GitHub"},{"url":"https://stackoverflow.com/users/3212865/spectras","name":"stackoverflow","title":"StackOverflow"},{"url":"https://www.linkedin.com/in/julienhartmann/","name":"linkedin","title":"LinkedIn"}],"profilePicNode":{"original":{"src":"/static/profile-pic-301a9cbe7b572c3e7910c9717d2b3bcd.jpg"}},"url":"https://etherdream.org/about"}}},"markdownRemark":{"id":"41254eec-1b82-5d4a-b718-bd7791481c7e","excerpt":"After the theory, a quick review of common runtime error handling techniques.\nMost ecosystems focus on one, but knowing the others might come in handy in some situations.","html":"<p>After the theory, a quick review of common runtime error handling techniques.\nMost ecosystems focus on one, but knowing the others might come in handy in some situations.</p>\n<p>--- excerpt ---</p>\n<p>In <a href=\"error-handling-levels\" class=\"internal\">previous post</a>, we explored levels of abstractions and the flow\nof errors through interfaces. We did not, however, examine the actual tools used to implement\nthem.</p>\n<p>In this post, we will review the main error handling paradigms.</p>\n<h2 id=\"error-handling-techniques\">Error handling techniques</h2>\n<h3 id=\"error-codes\">Error codes</h3>\n<p>The oldest way to report errors: return a value that tells whether an error occured.</p>\n<div class=\"side-by-side abstract\">\n<div class=\"side\">\n<div class=\"figure-wrapper\"><figure id=\"fig-1\"><div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">void</span> <span class=\"token function\">consumer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">provider</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> Code<span class=\"token double-colon punctuation\">::</span>Ok<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token comment\">// handle error</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token comment\">// continue</span>\n<span class=\"token punctuation\">}</span></code></pre></div><figcaption><div class=\"figcaption-wrapper\">Checking for error with a code.</div></figcaption></figure></div>\n</div><div class=\"side\">\n<div class=\"figure-wrapper\"><figure id=\"fig-2\"><div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span>nodiscard<span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> Code <span class=\"token function\">provider</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>failure<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">return</span> Code<span class=\"token double-colon punctuation\">::</span>Failure<span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token keyword\">return</span> Code<span class=\"token double-colon punctuation\">::</span>Ok<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div><figcaption><div class=\"figcaption-wrapper\">Signalling an error with a code.</div></figcaption></figure></div>\n</div></div>\n<p>Easy to implement, easy to understand, and very portable. This is common in C-style and\ncross-language APIs.</p>\n<p>It is fully manual though, which implies significant drawbacks:</p>\n<ul>\n<li>\n<p>In most languages, it is <strong>buggy by default</strong>: the <code class=\"language-text\">consumer()</code> is expected to check for error\ncodes, but if it forgets to do it, the error is <em>silently discarded</em>.</p>\n<p>This specific example code uses a C++17 feature, the\n<a href=\"https://en.cppreference.com/w/cpp/language/attributes/nodiscard\" class=\"external\" rel=\"external noopener noreferrer\"><code class=\"language-text\">[[nodiscard]]</code></a>\nattribute, to ask the compiler to verify that the consumer uses the error code,\nalleviating that risk. This feature does not exist in most languages, though.</p>\n</li>\n<li>\n<p>Error forwarding adds a lot of <strong>boilerplate</strong>, as every single function along the call stack\nmust implement it manually.</p>\n<p>And again, if a single function misses it, it is silently discarded.</p>\n</li>\n</ul>\n<h3 id=\"sentinel-values\">Sentinel values</h3>\n<p>Somewhat similar to error codes. The idea is to package in one type both information about\nsuccess or failure and the actual result.</p>\n<div class=\"side-by-side abstract\">\n<div class=\"side\">\n<div class=\"figure-wrapper\"><figure id=\"fig-3\"><div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">void</span> <span class=\"token function\">consumer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">auto</span> handle <span class=\"token operator\">=</span> <span class=\"token function\">provider</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>handle <span class=\"token operator\">==</span> InvalidHandle<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token comment\">// handle error</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token comment\">// use handle</span>\n<span class=\"token punctuation\">}</span></code></pre></div><figcaption><div class=\"figcaption-wrapper\">Checking for error with a sentinel.</div></figcaption></figure></div>\n</div><div class=\"side\">\n<div class=\"figure-wrapper\"><figure id=\"fig-4\"><div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\">Handle <span class=\"token function\">provider</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>failure<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">return</span> InvalidHandle<span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token comment\">// continue</span>\n   <span class=\"token keyword\">return</span> actualHandle<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div><figcaption><div class=\"figcaption-wrapper\">Signalling an error with a sentienl.</div></figcaption></figure></div>\n</div></div>\n<p>Many variants exist, such as:</p>\n<ul>\n<li><code class=\"language-text\">NULL</code> pointers in C.</li>\n<li>returning a negative value in many POSIX apis, such as\n<a href=\"https://man7.org/linux/man-pages/man2/open.2.html\" class=\"external\" rel=\"external noopener noreferrer\"><code class=\"language-text\">open()</code></a>.</li>\n<li>similarly, <code class=\"language-text\">INVALID_HANDLE_VALUE</code> in Win32 APIs.</li>\n</ul>\n<p>The main point is to allow using the same approach as error codes, without having to\nuse a separate parameter.\nIt only works if the type inherently has some unused values that can be used to signify the\nlack of a useful value. That special value is called a <strong>sentinel</strong>.</p>\n<p>The method has the same pros and cons as error codes.</p>\n<h3 id=\"exceptions\">Exceptions</h3>\n<p>Error handling as part of language control flow.</p>\n<div class=\"side-by-side abstract\">\n<div class=\"side\">\n<div class=\"figure-wrapper\"><figure id=\"fig-5\"><div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">void</span> <span class=\"token function\">consumer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token function\">provider</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> Error <span class=\"token operator\">&amp;</span> err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token comment\">// handle error</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token comment\">// continue</span>\n<span class=\"token punctuation\">}</span></code></pre></div><figcaption><div class=\"figcaption-wrapper\">Checking for error with exceptions.</div></figcaption></figure></div>\n</div><div class=\"side\">\n<div class=\"figure-wrapper\"><figure id=\"fig-6\"><div class=\"gatsby-highlight\" data-language=\"cpp\"><pre class=\"language-cpp\"><code class=\"language-cpp\"><span class=\"token keyword\">void</span> <span class=\"token function\">provider</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>failure<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">throw</span> <span class=\"token function\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"blah\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   <span class=\"token punctuation\">}</span>\n   <span class=\"token comment\">// continue</span>\n<span class=\"token punctuation\">}</span></code></pre></div><figcaption><div class=\"figcaption-wrapper\">Signalling an error with exceptions.</div></figcaption></figure></div>\n</div></div>\n<p>The main advantages of exceptions are that:</p>\n<ul>\n<li>They make it easy to have structured error handling, typically by using some kind of\nexception class hierarchies.</li>\n<li>They skip forwarding boilerplate entirely, as exceptions automatically raise up to the\npoint catching them.</li>\n<li>This makes them safe by default: errors will not be discarded.</li>\n</ul>\n<p>This typically comes at the price of much more complexity:</p>\n<ul>\n<li>Reasoning about code paths becomes hard: what can throw? At which point? What are the\nexact guarantees if a statement throws half-way through?</li>\n<li>Exceptional codepaths tend to be slower on performance-oriented languages. Though irrelevant\nfor most code as few programs really care for a few nanoseconds on an error path, it\ndisqualifies them for time-critical applications.</li>\n</ul>\n<h3 id=\"callbacks\">Callbacks</h3>\n<p>An error handling method is defined upfront, and error conditions cause it to be called.\nThis is used either:</p>\n<ul>\n<li>for asynchronous error handling, where the function call that triggered the failing\noperation has already returned by the time the error is detected.</li>\n<li>to provide additional context before returning an error code.</li>\n</ul>\n<p>As it is somewhat unusual, we will not cover it.</p>\n<h2 id=\"some-design-considerations\">Some design considerations</h2>\n<h3 id=\"ecosystem-practices\">Ecosystem practices</h3>\n<p>Some languages and platforms favor one mechanism over others. For instance:</p>\n<ul>\n<li>C does not have support for exceptions.</li>\n<li>Python language and community favor exceptions.</li>\n<li>Some microcontrollers make exception support unpractical.</li>\n<li>Some framework you use might already have a strong opinion you want to be consisent with.</li>\n</ul>\n<h3 id=\"error-context\">Error context</h3>\n<p>Giving context with an error tends to be difficult with error codes and sentinel values.\nIn the worst case, only one sentinel value exists (eg a <code class=\"language-text\">NULL</code> pointer in C) so the only\nuseful information we can send is <em>“this failed”</em>.</p>\n<p>Though there are techniques to provide more information, it is usually impractical,\ninvolving saving the error context in some global state area, possibly with thread-safety\nimplications.</p>\n<h3 id=\"a-word-on-monadic-types\">A word on monadic types</h3>\n<p>One way to overcome the limitations of error codes comes from functional programming.</p>\n<p>The core idea is to create a type that is the sum of possible outputs and error conditions.\nThat is, after constructing such a type, a variable of that type might take either of any\npossible output value or any possible error condition.</p>\n<div class=\"figure-wrapper\"><figure id=\"fig-7\"><div class=\"gatsby-highlight\" data-language=\"haskell\"><pre class=\"language-haskell\"><code class=\"language-haskell\"><span class=\"token keyword\">type</span> <span class=\"token constant\">Error</span> <span class=\"token operator\">=</span> <span class=\"token constant\">Int</span>\n<span class=\"token keyword\">type</span> <span class=\"token constant\">Value</span> <span class=\"token operator\">=</span> <span class=\"token constant\">String</span>\n<span class=\"token keyword\">type</span> <span class=\"token constant\">Result</span> <span class=\"token operator\">=</span> <span class=\"token constant\">Either</span> <span class=\"token constant\">Error</span> <span class=\"token constant\">Value</span>\n\n<span class=\"token comment\">-- A function that returns a value</span>\n<span class=\"token hvariable\">okFunc</span> <span class=\"token operator\">::</span> <span class=\"token constant\">Result</span>\n<span class=\"token hvariable\">okFunc</span> <span class=\"token operator\">=</span> <span class=\"token constant\">Right</span> <span class=\"token string\">\"Hello\"</span>\n\n<span class=\"token comment\">-- A function that fails</span>\n<span class=\"token hvariable\">failFunc</span> <span class=\"token operator\">::</span> <span class=\"token constant\">Result</span>\n<span class=\"token hvariable\">failFunc</span> <span class=\"token operator\">=</span> <span class=\"token constant\">Left</span> <span class=\"token number\">42</span>\n\n<span class=\"token comment\">-- Consumer that uses the result</span>\n<span class=\"token hvariable\">format</span> <span class=\"token operator\">::</span> <span class=\"token constant\">Result</span> <span class=\"token operator\">-></span> <span class=\"token constant\">String</span>\n<span class=\"token hvariable\">format</span> <span class=\"token punctuation\">(</span><span class=\"token constant\">Left</span> <span class=\"token builtin\">error</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"Error \"</span> <span class=\"token operator\">++</span> <span class=\"token builtin\">show</span> <span class=\"token builtin\">error</span>\n<span class=\"token hvariable\">format</span> <span class=\"token punctuation\">(</span><span class=\"token constant\">Right</span> <span class=\"token hvariable\">value</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token hvariable\">value</span>\n\n<span class=\"token comment\">-- Demo</span>\n<span class=\"token hvariable\">main</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">do</span>\n    <span class=\"token builtin\">putStrLn</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">format</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">okFunc</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token builtin\">putStrLn</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">format</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">failFunc</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div><figcaption><div class=\"figcaption-wrapper\">Monadic return type for error handling.</div></figcaption></figure></div>\n<p>Here the <code class=\"language-text\">Result</code> type is always either an error code or a string value.</p>\n<p>This approach has many advantages:</p>\n<ul>\n<li>It solves the forwarding boilerplate problem, because simply forwarding the\n<code class=\"language-text\">Result</code> carries error information with it.</li>\n<li>Attempting to access the value if <code class=\"language-text\">Result</code> holds an error will be detected.</li>\n<li>It does not incur the complexities that come with exceptions.</li>\n</ul>\n<p>Monadic types deserve a full article some day. They are not reserved to Haskell. For\ninstance, C++17 <a href=\"https://en.cppreference.com/w/cpp/utility/variant\" class=\"external\" rel=\"external noopener noreferrer\"><code class=\"language-text\">std::variant</code></a>\nis similar to Haskell's <code class=\"language-text\">Either</code> that we used in the example above.</p>\n<h2 id=\"conclusion\">Conclusion</h2>\n<p>Writing this I realised that the topic is much deeper than one blog article can cover.\nEach paragraph would deserve its own post. But it was important to bring closure to\nthat short series, and maybe we will explore those in more depth later.</p>","fields":{"isPage":false,"slug":"/2019/error-handling-techniques"},"frontmatter":{"title":"Error Handling part 3: Techniques","classname":null,"date":"2021-04-03T00:00:00.000Z","formattedDate":"April 03, 2021","isoDate":"2021-04-03T00:00:00+00:00"},"headings":[{"value":"Error handling techniques","depth":1},{"value":"Error codes","depth":2},{"value":"Sentinel values","depth":2},{"value":"Exceptions","depth":2},{"value":"Callbacks","depth":2},{"value":"Some design considerations","depth":1},{"value":"Ecosystem practices","depth":2},{"value":"Error context","depth":2},{"value":"A word on monadic types","depth":2},{"value":"Conclusion","depth":1}],"image":null,"series":{"name":"software","fullName":"software engineering","fields":{"slug":"/software"}},"tags":[{"name":"code","slug":"/tag/code"}]}},"pageContext":{"series":"software","slug":"/2019/error-handling-techniques","previous":{"fields":{"slug":"/2019/zero-cost-unique_ptr"},"frontmatter":{"title":"Zero-cost unique_ptr deleters","series":"software"},"tags":[{"name":"code","slug":"/tag/code"},{"name":"c++","slug":"/tag/c"}]},"next":null,"seriesPrevious":{"fields":{"slug":"/2019/zero-cost-unique_ptr"},"frontmatter":{"title":"Zero-cost unique_ptr deleters","series":"software"},"tags":[{"name":"code","slug":"/tag/code"},{"name":"c++","slug":"/tag/c"}]},"seriesNext":null}},
    "staticQueryHashes": ["1733002695","4006707078"]}