<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jonas Gauffin</title>
    <description>The latest articles on DEV Community by Jonas Gauffin (@jgauffin).</description>
    <link>https://dev.to/jgauffin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1108%2F7d88381e-7a75-4f83-8211-9c3e73455a4f.png</url>
      <title>DEV Community: Jonas Gauffin</title>
      <link>https://dev.to/jgauffin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jgauffin"/>
    <language>en</language>
    <item>
      <title>Giving AI agents knowledge they were never trained on</title>
      <dc:creator>Jonas Gauffin</dc:creator>
      <pubDate>Thu, 14 May 2026 22:02:53 +0000</pubDate>
      <link>https://dev.to/jgauffin/giving-ai-agents-knowledge-they-were-never-trained-on-5fd7</link>
      <guid>https://dev.to/jgauffin/giving-ai-agents-knowledge-they-were-never-trained-on-5fd7</guid>
      <description>&lt;p&gt;I love coding my own stuff, and my clients typically have lots of internal specifications and libraries to use.&lt;/p&gt;

&lt;p&gt;But since LLMs haven't been trained on that, it's hard to get them to code accurately using those specs, libraries, or frameworks.&lt;/p&gt;

&lt;p&gt;You can, of course, let the agents parse everything, but that wastes tokens and your patience :)&lt;/p&gt;

&lt;p&gt;The same goes for well-known libraries, but you are stuck on a specific version that you must follow. You don't want it to guess the API.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docs-mcpserver&lt;/code&gt; exists to deal with both.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;It is an MCP server that provides an agent with accurate knowledge of a framework or specification using documentation as the medium. It reads three kinds of docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Markdown docs&lt;/strong&gt; — your &lt;code&gt;*.md&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API reference&lt;/strong&gt; — C# XML documentation, or TypeDoc JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema&lt;/strong&gt; — JSON Schema, OpenAPI 3.x, Swagger 2.0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What the agent gets out of it is the same in every case: the real names, the real&lt;br&gt;
signatures, the real shapes. Sources can come from a&lt;br&gt;
local folder or straight from a GitHub URL. A single&lt;br&gt;
server instance can host several libraries side by side. For instance, your in-house framework, a client's framework, and a specific version of some public library. &lt;/p&gt;

&lt;p&gt;The agent picks which one to query.&lt;/p&gt;

&lt;p&gt;I personally have used it to code against a specification called DATEX (traffic information for roads), which is HUGE, my own &lt;a href="https://github.com/relax-js/core" rel="noopener noreferrer"&gt;SPA library&lt;/a&gt;, and against sound format specifications for a sound app I'm building.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why not just give the agent the files
&lt;/h2&gt;

&lt;p&gt;You could point the agent to the folders and let it read them. The MCP server does a few things that raw file access does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It is sandboxed.&lt;/strong&gt; Each source is scoped, with path-traversal protection. The
agent reads what you exposed, nothing else on the disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It reads in pieces.&lt;/strong&gt; Instead of loading a 4000-line reference file, the agent
asks for the table of contents, then pulls the one chapter it needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It searches properly.&lt;/strong&gt; Dedicated search tools with regex and glob support,
instead of the agent improvising its own grep.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is self-describing.&lt;/strong&gt; With several libraries configured, the agent calls
one tool to discover what is available. You do not have to spell out every path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub works without cloning.&lt;/strong&gt; Give it a repo URL and it handles the rest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The multi-library part is the point. Instead of running several MCP servers for&lt;br&gt;
documentation, you get one with a small toolset. No token waste.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting it up
&lt;/h2&gt;

&lt;p&gt;Install and build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The quick way, a single folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docs-mcpserver ./docs &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"My Docs"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the real use case — several libraries — use a config file. Here is an&lt;br&gt;
in-house framework served from disk, next to a pinned version of a public&lt;br&gt;
library pulled from GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dev-docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Frameworks the model has not been trained on"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cacheDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./cache"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"libraries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme-core"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Our internal application framework"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"origin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./frameworks/acme-core/docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docs"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"origin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./frameworks/acme-core/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"somelib-3.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SomeLib, pinned to v3.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"origin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/someorg/somelib/tree/v3.2.0/docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docs"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start it with the config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docs-mcpserver &lt;span class="nt"&gt;--config&lt;/span&gt; dev-docs.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And register it with Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add mydocs &lt;span class="nt"&gt;--&lt;/span&gt; node /path/to/markdown-docs-mcp/dist/index.js &lt;span class="nt"&gt;--config&lt;/span&gt; /path/to/dev-docs.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For private GitHub repos, set &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; in the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the agent actually sees
&lt;/h2&gt;

&lt;p&gt;Each library exposes tools based on the &lt;code&gt;kind&lt;/code&gt; of its sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;docs&lt;/strong&gt; — &lt;code&gt;get_doc_index&lt;/code&gt;, &lt;code&gt;get_sub_index&lt;/code&gt;, &lt;code&gt;read_doc_file&lt;/code&gt;, &lt;code&gt;get_file_toc&lt;/code&gt;,
&lt;code&gt;get_chapters&lt;/code&gt;, &lt;code&gt;search_docs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;api&lt;/strong&gt; — &lt;code&gt;get_api_index&lt;/code&gt;, &lt;code&gt;get_api_type&lt;/code&gt;, &lt;code&gt;get_api_member&lt;/code&gt;, &lt;code&gt;search_api&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;schema&lt;/strong&gt; — &lt;code&gt;list_schemas&lt;/code&gt;, &lt;code&gt;list_definitions&lt;/code&gt;, &lt;code&gt;get_definition&lt;/code&gt;,
&lt;code&gt;search_definitions&lt;/code&gt;, &lt;code&gt;search_all_schemas&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A typical run looks like this. The agent calls &lt;code&gt;list_libraries&lt;/code&gt; and sees&lt;br&gt;
&lt;code&gt;acme-core&lt;/code&gt; and &lt;code&gt;somelib-3.2&lt;/code&gt;. It needs to know how &lt;code&gt;acme-core&lt;/code&gt; handles&lt;br&gt;
configuration, so it calls &lt;code&gt;search_docs&lt;/code&gt; with &lt;code&gt;library: "acme-core"&lt;/code&gt;, finds the&lt;br&gt;
right file, asks for its table of contents with &lt;code&gt;get_file_toc&lt;/code&gt;, then pulls the&lt;br&gt;
one relevant section with &lt;code&gt;get_chapters&lt;/code&gt;. It answers the question without ever&lt;br&gt;
loading the whole file.&lt;/p&gt;

&lt;p&gt;When multiple libraries are configured, every tool takes a &lt;code&gt;library&lt;/code&gt; parameter.&lt;br&gt;
When there is only one, the parameter disappears, and the tools behave like a&lt;br&gt;
plain single-library server.&lt;/p&gt;

&lt;p&gt;The same applies to schema sources. For an OpenAPI spec, path operations show up&lt;br&gt;
as definitions named like &lt;code&gt;GET /pets&lt;/code&gt;, so the agent can ask for one endpoint&lt;br&gt;
without reading the whole document. Useful when you want the agent to call your&lt;br&gt;
API correctly rather than guess at the shape of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating the API input
&lt;/h2&gt;

&lt;p&gt;One thing worth knowing up front: the &lt;code&gt;api&lt;/code&gt; pipeline does not read source code.&lt;br&gt;
It consumes a generated documentation file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript / JavaScript&lt;/strong&gt; — use TypeDoc's JSON serializer:
&lt;code&gt;typedoc --json api.json src/index.ts&lt;/code&gt;. Point the source at that &lt;code&gt;.json&lt;/code&gt; file.
The markdown output from &lt;code&gt;typedoc-plugin-markdown&lt;/code&gt; is not supported — it has to
be the JSON serializer output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C#&lt;/strong&gt; — enable &lt;code&gt;&amp;lt;GenerateDocumentationFile&amp;gt;true&amp;lt;/GenerateDocumentationFile&amp;gt;&lt;/code&gt;
and point the source at the generated &lt;code&gt;*.xml&lt;/code&gt; file, or the build output folder
that contains it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it does not do
&lt;/h2&gt;

&lt;p&gt;It does not read source code. If you want API reference, you generate the doc&lt;br&gt;
file first, as above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The code is on &lt;a href="https://github.com/jgauffin/dev-docs-mcp" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, or on npm as &lt;code&gt;docs-mcpserver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to leave feedback, or check my other MCP servers on &lt;a href="https://github.com/jgauffin" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>typescript</category>
      <category>llm</category>
    </item>
    <item>
      <title>Exception handling explained</title>
      <dc:creator>Jonas Gauffin</dc:creator>
      <pubDate>Thu, 10 May 2018 11:33:24 +0000</pubDate>
      <link>https://dev.to/jgauffin/exception-handling-explained-ima</link>
      <guid>https://dev.to/jgauffin/exception-handling-explained-ima</guid>
      <description>&lt;p&gt;This article explains what exception handling is and how it differs from&lt;br&gt;
traditional error handling with error codes. The article does not get&lt;br&gt;
into usage or exception classes, but only to explain their purpose.&lt;/p&gt;

&lt;p&gt;Let's start with errors.&lt;/p&gt;
&lt;h1&gt;
  
  
  A brief introduction to error
&lt;/h1&gt;

&lt;p&gt;From the dawn of programming, error codes have been used to deal with errors in applications. An error code is used to indicate if the&lt;br&gt;
executed function was successful or not.&lt;/p&gt;

&lt;p&gt;Here is a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;SaveDefaultAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;accountName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetUserIdFromName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetAccountFromName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;StoreDefaultAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example illustrates that when you use error codes, it is the API&lt;br&gt;
consumer that must abort if something fails. You might, but how about&lt;br&gt;
the rest of the team, or those who maintained the application before&lt;br&gt;
you? It is like you would retire the entire police force and expect&lt;br&gt;
&lt;strong&gt;&lt;em&gt;all&lt;/em&gt;&lt;/strong&gt; citizens to behave and be good law abiding citizens.&lt;/p&gt;

&lt;p&gt;One developer could have been lazy and just written (or refactored) the&lt;br&gt;
code as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;SaveDefaultAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;accountName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetUserIdFromName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Arne"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetAccountFromName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Savings account"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;StoreDefaultAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that the code looks perfectly legal, but silently ignores&lt;br&gt;
errors. If you for instance mistakenly add a white space after all&lt;br&gt;
account names on the account selection page, the code above starts to&lt;br&gt;
fail silently. What's worse is that you will not know about it until&lt;br&gt;
code dependent upon the default account starts to fail, and that can be&lt;br&gt;
after a while. Tracking down that subsequent error can be challenging,&lt;br&gt;
primarily if the default account is set in different ways.&lt;/p&gt;

&lt;p&gt;Error codes are easy to get started with and can be quite powerful. Even&lt;br&gt;
modern languages like Go-lang uses errors instead of exceptions. Here is&lt;br&gt;
a go snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"filename.ext"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While errors are easy to understand and use, they have three&lt;br&gt;
significant drawbacks:&lt;/p&gt;
&lt;h2&gt;
  
  
  They do not convey context
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This section is for languages that only uses error codes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For instance, error code 2 means "File Not Found" in Windows. There is&lt;br&gt;
no way to state which file nor other information that might help you to&lt;br&gt;
understand why the file was missing. Error codes are just that. Codes&lt;br&gt;
that indicate a specific error, without context or clues.&lt;/p&gt;

&lt;p&gt;The problem with that is that it is hard to understand why or under what&lt;br&gt;
circumstances that the error occurred. The Windows API solves this by&lt;br&gt;
introducing a method called &lt;code&gt;GetLastError()&lt;/code&gt; which is used to get more&lt;br&gt;
information about the error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;OFSTRUCT&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;HFILE&lt;/span&gt; &lt;span class="n"&gt;hFile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;OpenFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"d:\\sample.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OF_READ&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hFile&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;HFILE_ERROR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// all this is required to get the error message.&lt;/span&gt;
    &lt;span class="c1"&gt;// you typically add it to a separate function&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the error code, as hFile only indicates an error&lt;/span&gt;
    &lt;span class="c1"&gt;// but not which one.&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;errorCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetLastError&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the generic error message which&lt;/span&gt;
    &lt;span class="c1"&gt;// represents the above error code.&lt;/span&gt;
    &lt;span class="n"&gt;LPVOID&lt;/span&gt; &lt;span class="n"&gt;lpMsgBuf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;LPVOID&lt;/span&gt; &lt;span class="n"&gt;lpDisplayBuf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;FormatMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;FORMAT_MESSAGE_ALLOCATE_BUFFER&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; 
        &lt;span class="n"&gt;FORMAT_MESSAGE_FROM_SYSTEM&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;FORMAT_MESSAGE_IGNORE_INSERTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;errorCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nf"&gt;MAKELANGID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LANG_NEUTRAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SUBLANG_DEFAULT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LPTSTR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lpMsgBuf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NULL&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My point is that an error code is not enough when you want to&lt;br&gt;
&lt;em&gt;solve&lt;/em&gt; the error.&lt;/p&gt;
&lt;h2&gt;
  
  
  The burden is on the function caller
&lt;/h2&gt;

&lt;p&gt;It is safe to say that all applications have errors, it is exceptionally&lt;br&gt;
rare (pun intended) that errors can be ignored. Ignoring errors might&lt;br&gt;
seem to work, but sooner or later consequential problems will surface.&lt;br&gt;
It will be much harder to find the root cause since the found error is&lt;br&gt;
just a consequence of the first one. Any kind of "fix" is just a&lt;br&gt;
workaround which clutters the code base but does not prevent the root&lt;br&gt;
cause from happening again.&lt;/p&gt;

&lt;p&gt;It is crucial that all errors are handled in your code. When you use&lt;br&gt;
error codes, it is so easy to ignore or forget errors. Had a tight&lt;br&gt;
deadline? Wrestled with an obscure bug or incomprehensible requirements?&lt;br&gt;
Those situations make it so easy to take a shortcut. If not all&lt;br&gt;
developers on your team have the same discipline, errors will get&lt;br&gt;
ignored.&lt;/p&gt;
&lt;h1&gt;
  
  
  Enter exceptions
&lt;/h1&gt;

&lt;p&gt;Exceptions are for exceptional situations. If something didn't go as&lt;br&gt;
expected, you got an exceptional situation.&lt;/p&gt;

&lt;p&gt;Sounds easy, huh?&lt;/p&gt;

&lt;p&gt;But what does that mean?&lt;/p&gt;
&lt;h2&gt;
  
  
  An exceptional example
&lt;/h2&gt;

&lt;p&gt;If you expect that something can fail, you should guard against that&lt;br&gt;
situation.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;p&gt;Let's say that you love shopping the newest and hottest technical&lt;br&gt;
gadgets. When the new gadget is released, you want to be first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo83dfiz9eacxmggbl7pf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo83dfiz9eacxmggbl7pf.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Scenario 1
&lt;/h3&gt;

&lt;p&gt;If you are like most of us, you can probably not just go on a shopping&lt;br&gt;
spree. You need to make sure that you have enough money.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Check your bank account.&lt;/li&gt;
&lt;li&gt; Go shopping.&lt;/li&gt;
&lt;li&gt; Pay&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Scenario 2
&lt;/h3&gt;

&lt;p&gt;However, if you are fortunate enough to have plenty of money, you can&lt;br&gt;
go shopping directly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Go shopping.&lt;/li&gt;
&lt;li&gt; Pay&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  The difference
&lt;/h3&gt;

&lt;p&gt;In the first scenario, we have a known issue that we need to deal with:&lt;br&gt;
A money limit. Therefore, we always need to check that we have enough&lt;br&gt;
money. In the second scenario, we should have enough money.&lt;/p&gt;

&lt;p&gt;What happens if someone has hacked us in scenario 2:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Someone hacked us&lt;/li&gt;
&lt;li&gt; Go shopping&lt;/li&gt;
&lt;li&gt; Pay &amp;lt;-- Failed, no money&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In that case, we got an exception, since it is a case that shouldn't&lt;br&gt;
happen since we &lt;strong&gt;&lt;em&gt;expect&lt;/em&gt;&lt;/strong&gt; to have enough money.&lt;/p&gt;

&lt;p&gt;That is an exceptional situation.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;Why can't we always write the code like in scenario 1?&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;First, it's about communicating intent. We mostly get a set of business&lt;br&gt;
requirements that we should fulfill. They tell us what to expect when&lt;br&gt;
implementing different use cases. If we go and add many checks for&lt;br&gt;
things that might, but should not, happen we lose the connection between&lt;br&gt;
our use cases and the code. It will be hard to tell the intent of the&lt;br&gt;
code, which in turn lead to assumptions and in the end decreased code&lt;br&gt;
quality.&lt;/p&gt;

&lt;p&gt;Second, if we add many checks we are coding workarounds as the real&lt;br&gt;
problem is that our account was hacked, not that we could not pay. By&lt;br&gt;
adding checks and abort instead of paying we are hiding that fact.&lt;/p&gt;
&lt;h2&gt;
  
  
  What exceptions are
&lt;/h2&gt;

&lt;p&gt;Exceptions are for situations that wasn't considered when defining what&lt;br&gt;
the application should do. When writing a messaging library for message&lt;br&gt;
queues you expect to receive complete messages, but when you write one&lt;br&gt;
for TCP you expect to receive partial messages. What's exceptional in&lt;br&gt;
one case doesn't necessarily have to be exceptional in another.&lt;/p&gt;

&lt;p&gt;If you would open a file there are several errors that can happen.&lt;br&gt;
Non-existent directory, file is missing, access denied, partial file,&lt;br&gt;
etc. All those errors are known to most programmers, so they are not&lt;br&gt;
exceptions, right?&lt;/p&gt;

&lt;p&gt;Wrong. In most cases, they are exceptions. Because you typically do&lt;br&gt;
expect that a file exists and that it's complete and readable. Well, if&lt;br&gt;
you are writing a data forensics application, most of those errors are&lt;br&gt;
expected and should be dealt with (and therefore not exceptional cases).&lt;/p&gt;
&lt;h3&gt;
  
  
  Exceptions exist to prevent your application from doing something stupid.
&lt;/h3&gt;

&lt;p&gt;It's crucial for you to understand that. Don't think of exceptions as&lt;br&gt;
something you can use to control your application when coding. Think of&lt;br&gt;
exceptions as a mechanism to guard against your application doing&lt;br&gt;
something wrong/unexpected.&lt;/p&gt;
&lt;h3&gt;
  
  
  Exceptions exist to help you fix problems in the future
&lt;/h3&gt;

&lt;p&gt;Since exceptions are not a flow control mechanism, they do add little&lt;br&gt;
value when executing your code (previously described point excluded).&lt;/p&gt;

&lt;p&gt;However, writing informative exception messages makes it much easier to&lt;br&gt;
correct future bugs, since they add context to the error. Always try to&lt;br&gt;
do so, your future self will thank you for it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code example
&lt;/h2&gt;

&lt;p&gt;Let's take the same code as was found in the beginning of this article,&lt;br&gt;
but changed to use exception handling instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SaveDefaultAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;accountName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetUserIdFromName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Arne"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetAccountFromName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Savings account"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;StoreDefaultAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the method now returns void as it does not need to&lt;br&gt;
indicate that everything went successfully. Nor does it need to validate&lt;br&gt;
error codes from the called methods. One can safely assume that an&lt;br&gt;
exception abort the processing if the expected result cannot be&lt;br&gt;
guaranteed.&lt;/p&gt;

&lt;p&gt;In fact, in most cases, we do not have to care if exceptions are thrown&lt;br&gt;
at all. Remember, exceptions are used to communicate that something&lt;br&gt;
unexpected happened. If we cannot predict it, how on earth could we be&lt;br&gt;
able to handle the exception?&lt;/p&gt;

&lt;p&gt;Let's look at the &lt;code&gt;StoreDefaultAccount&lt;/code&gt; method. The most important thing&lt;br&gt;
to understand is that the method says that a default account should be&lt;br&gt;
stored successfully. Since that is the method promise, we must throw an&lt;br&gt;
exception every time we find something that would prevent the default&lt;br&gt;
account from being stored.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;StoreDefaultAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"A valid user id must be specified."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"A valid account id must be specified."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_accountRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OwnerId&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidOperationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"User &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; do not own account &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultAccount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;_userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two exceptions are used to mitigate errors like parse errors&lt;br&gt;
or invalid data.&lt;/p&gt;

&lt;p&gt;The third exception is for a business rule. We may only use the user's&lt;br&gt;
own accounts as default accounts.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_accountRepository.GetById(accountId);&lt;/code&gt; will in turn throw an&lt;br&gt;
exception if the given accountId do not exist in the database since the&lt;br&gt;
method name states that an account should be fetched.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;The purpose of exceptions is not to allow you to take different actions&lt;br&gt;
depending on if something failed or not. i.e. they are not a flow&lt;br&gt;
control mechanism. Instead, exceptions are used to make sure that your&lt;br&gt;
application delivers the expected result (or die trying).&lt;/p&gt;

&lt;p&gt;With that in mind, I hope that you find them as useful as I do. With&lt;br&gt;
the right mindset (and using exceptions) you can save much time since&lt;br&gt;
you do not have to track down why your database has a lot of data&lt;br&gt;
inconsistencies (which leads to bugs later).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article is part of our exception handling series. To learn more, visit our &lt;a href="https://coderr.io/exception-handling/" rel="noopener noreferrer"&gt;website&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>exceptions</category>
      <category>errors</category>
    </item>
  </channel>
</rss>
