<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Programming Missives]]></title><description><![CDATA[Opinionated Programmer that has spent many years taking notes on what not to do again.
Nothing you read here was "AI" generated.]]></description><link>https://blog.vertigrated.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1709168222323/k5jEq8Agi.png</url><title>Programming Missives</title><link>https://blog.vertigrated.com</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 18 May 2026 20:50:50 GMT</lastBuildDate><atom:link href="https://blog.vertigrated.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[No  more Load/Store use StorageLike]]></title><description><![CDATA[Motivation
The typical Pinia tutorial tells you to write a Load and Store function to manage, well loading and storing your state from and to the server. I have never seen a single one of them mention this approach, they all are some variation of the...]]></description><link>https://blog.vertigrated.com/no-more-loadstore-use-storagelike</link><guid isPermaLink="true">https://blog.vertigrated.com/no-more-loadstore-use-storagelike</guid><category><![CDATA[Vue.js]]></category><category><![CDATA[Pinia]]></category><category><![CDATA[storage]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[State Management ]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Wed, 05 Mar 2025 02:48:18 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-motivation">Motivation</h2>
<p>The typical Pinia tutorial tells you to write a Load and Store function to manage, well loading and storing your state from and to the server. I have never seen a single one of them mention this approach, they all are some variation of the <code>load</code>() function called in <code>onMounted()</code>.</p>
<p>I think that is a complete disservice to new users just discovering Pinia as for the majority of cases, it is not the easiest or simplest solution to be teaching those new to Pinia, and probably Vue as well.</p>
<p>There is a better way for the majority of use cases using the <a target="_blank" href="https://prazdevs.github.io/pinia-plugin-persistedstate/">PersistedState</a> plugin.</p>
<p>This plugin provides for configurable persistence of Pinia stores, and provides support for Session, LocalStorage and Cookie persistence out of the box.</p>
<p>It is trivial to provide custom persistence if you design your API calls in a consistent manner.</p>
<p>There are plenty of articles and tutorials on how to use <a target="_blank" href="https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/src/types.ts">pinia-plugin-persistedstate</a>, so I am not going to go into how to use it, but instead explain how to design your remote api so making using it is simple and secure as possible.</p>
<h2 id="heading-storagelike">StorageLike</h2>
<p>The main thing to know about this plugin is the following Interface, this is what you implement to allow the plugin to do its magic and relieve you of all the boilerplate error prone stuff it does.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/**
 * Synchronous storage based on Web Storage API.
 * @see https://developer.mozilla.org/en-US/docs/Web/API/Storage
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> StorageLike {
  <span class="hljs-comment">/**
   * Get a key's value if it exists.
   */</span>
  getItem: <span class="hljs-function">(<span class="hljs-params">key: <span class="hljs-built_in">string</span></span>) =&gt;</span> <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>

  <span class="hljs-comment">/**
   * Set a key with a value, or update it if it exists.
   */</span>
  setItem: <span class="hljs-function">(<span class="hljs-params">key: <span class="hljs-built_in">string</span>, value: <span class="hljs-built_in">string</span></span>) =&gt;</span> <span class="hljs-built_in">void</span>
}
</code></pre>
<p>This is what you want your remote api to look like as well, sort of.</p>
<p>Lets say you have a <code>User</code> and you want to load the current <code>User</code> after they authenticate. Here is what you should make your remote API look like.</p>
<p>I am going to use an actual <a target="_blank" href="https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf">REST</a>ful API over HTTP, because that is what most people will be familiar with and it illustrates the approach the simplest way possible.</p>
<pre><code class="lang-http"><span class="hljs-attribute">GET /user
PUT /user</span>
</code></pre>
<h2 id="heading-get-user">GET /user</h2>
<p>For security you should make these routes require authentication and enforce it in “middleware” or whatever your server calls request pre-processing interceptors.</p>
<p>You already know who the user is, so you do not need to pass in an <code>id</code> to either call. This is the most secure. It is also the simplest way to write the client and server code as well. The request handler is protected and should never receive anything that is not authenticated, and will get the user id to find and return as data that the authentication handler provides.</p>
<h2 id="heading-put-user">PUT /user</h2>
<p>contrary to what every TODO app tutorial you and whatever chat “ai” code generator you are using tells you, the <code>PUT</code> verb is NOT just for creation of resources.</p>
<p>As per the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT">official documentation</a>;</p>
<blockquote>
<p>The <code>PUT</code> HTTP method creates a new resource or replaces a representation of the target resource with the request <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/HTTP_Content">content</a>.</p>
</blockquote>
<p>semantically, you should use <code>PUT</code> for creating and updating resources when you are providing the entire resource. And if you are doing REST, you are providing the entire resource, right? RIGHT?</p>
<p>This is the most efficient way to updating the remote state, providing the entire resource, and is the entire point behind the <a target="_blank" href="https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf">REST</a> approach. <a target="_blank" href="https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf">REST</a> stands for <a target="_blank" href="https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf"><strong>Representational State Transfer</strong></a>, if you are not transferring state you are not doing REST<strong>.</strong> This example is a REST example so we are doing REST.</p>
<p>If you need to do partial updates to a resource for some reason, then <code>PATCH</code> is the correct way to do it, <strong>not</strong> <code>POST</code>! There may be reasons to do a partial update of a resource, but almost always they should because of some side effect of the business logic on the server side.</p>
<p>The only reasons to submit partial resource updates to the server are functional;</p>
<ul>
<li>you do not have the entire resource to submit with the updated part.</li>
</ul>
<ul>
<li><p>the entire resource is large and it would be inefficient to transmit such a large payload just to change a very small percentage of the data.</p>
</li>
<li><p>Whatever you are updating will cause some kind of side-effect on the system receiving the update that is not idempotent.</p>
</li>
</ul>
<p>Partial updates by definition are not RESTful. They are basically <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc1050">RPC</a> calls over HTTP. To be pedantic, I know they are not Remote Procedure Calls, but in they are remote calls to a procedure, and they are over HTTP, so semantically they are a form of <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc1050">RPC</a>. <em>Unless, the partial update is treated as a resource, and then it should be transmitted via</em> <code>PUT</code>. This gets into a kind of recursive rabbit hole quickly.</p>
<h2 id="heading-patch-user">PATCH /user</h2>
<blockquote>
<p>The <code>PATCH</code> HTTP method applies partial modifications to a resource.</p>
<p>In comparison with <code>PUT</code>, a <code>PATCH</code> serves as a set of instructions for modifying a resource, whereas <code>PUT</code> represents a complete replacement of the resource.</p>
<p>A <code>PUT</code> request is always idempotent (repeating the same request multiple times results in the resource remaining in the same state), whereas a <code>PATCH</code> request may not always be idempotent.</p>
</blockquote>
<p><code>PATCH</code> is not the correct choice to use for implementing your <a target="_blank" href="https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/src/types.ts">StorageLike</a> server side implementation.</p>
<h2 id="heading-post-user">POST /user</h2>
<blockquote>
<p>The <code>POST</code> HTTP method sends data to the server.</p>
<p>The difference between <code>PUT</code> and <code>POST</code> is that <code>PUT</code> is idempotent: calling it once is no different from calling it several times successively (there are no side effects). Successive identical <code>POST</code> requests may have additional effects, such as creating the same order several times.</p>
</blockquote>
<p><code>POST</code> is not the correct choice to use for implementing your <a target="_blank" href="https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/src/types.ts">StorageLike</a> server side implementation.</p>
<h2 id="heading-delete-user">DELETE /user</h2>
<p>There is no <code>DELETE</code> in the StorageLike interface, I am not sure how I feel about this, given how I feel about <code>null</code>. There will be a temptation for a lot of you that do not know better to implement <code>DELETE</code> by just setting the store state to <code>null</code> or whatever you want to <code>DELETE</code> to <code>null</code> and handle that as a special case in the <code>setItem(key,value)</code> function. Resist this urge! It will just lead to suffering.</p>
<p>A better approach would be to do your <code>DELETE</code> explicitly. Click button, call <code>DELETE</code> and then update the store state to reflect the server state. The client state should always represent the server state, not the other way around. This eliminates entire classes of bugs and will save you time in the long run.</p>
<p>If at some point in the future, you find out from profiling that you need to make it more efficient, then do that, but initially, stay as close to <em>client represents server state</em> as possible. The easiest way to do that is to mutate the server state and then sync the client state to match the server.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As I stated in already, I wrote this up because this approach is not the mainstream approach to using Pinia and I think it should be. This is my attempt to add to the information that might be found be people new to Pinia and trying to figure out how to best leverage it.</p>
]]></content:encoded></item><item><title><![CDATA[Use marker values instead of null or whatever your language calls a it!]]></title><description><![CDATA[What is NULL?
Tony Hoare introduced the concept of thenull reference in 1965 while designing the ALGOL W programming language.
A null reference means that a reference variable does not point to any object.
He has explicitly stated that the null refer...]]></description><link>https://blog.vertigrated.com/use-marker-values-instead-of-null-or-whatever-your-language-calls-a-it</link><guid isPermaLink="true">https://blog.vertigrated.com/use-marker-values-instead-of-null-or-whatever-your-language-calls-a-it</guid><category><![CDATA[Null]]></category><category><![CDATA[Null Safety]]></category><category><![CDATA[best practices]]></category><category><![CDATA[newbie]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Mon, 24 Feb 2025 08:28:21 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-null">What is NULL?</h2>
<p>Tony Hoare introduced the concept of the<code>null</code> reference in 1965 while designing the ALGOL W programming language.</p>
<p>A null reference means that a reference variable does not point to any object.</p>
<p>He has explicitly stated that the null reference was included <em>"simply because it was so easy to implement."</em> In the context of designing ALGOL W, it provided a quick and straightforward way to represent the absence of a value.</p>
<blockquote>
<p>"I call it my billion-dollar mistake" - Tony Hoare (QCon London 2009)</p>
</blockquote>
<p>Granted in hind sight it has been misused and abused like just about every other feature of every other language or language paradigm. <code>null</code> in and of itself is not “bad”. It is all the people that do not understand why they should not use it in modern code. There are plenty of alternatives that were not available in 1965.</p>
<p>Programs written in 1965 were tiny compared to even the 1980’s. They had to fit in even smaller amounts of RAM and had to use every bit of memory and processing cycle for something relevant. <code>null</code> was a convenient way to signal that lack of data both in time (cycles) and space (bits).</p>
<p><em>“You fathers null reference, This is a tool of the diligent programmer. Not as haphazard or reckless as a raw pointer; an elegant solution for a more civilized age”</em> - with apologies to Obi Wan Kenobi (and George Lucas)</p>
<p>While the concept of<code>null</code> was a valid solution to a real problem of its time, it is an anachronism that has no place in modern programming languages. Relying on <code>null</code> references in 2025 is just lazy and causes more work and harm than avoiding it.</p>
<h2 id="heading-there-is-no-reason-to-use-null-in-any-language">There is no reason to use null in any language</h2>
<p>Regardless of the language you are using, there is no reason to use <code>null</code> (or whatever your language calls it). We are not constrained by the memory or processor limitations of 1985. We are also dealing with code bases that are many orders of magnitude larger than they were in 1965.</p>
<p>Avoiding using <code>null</code> should be the default in modern languages, but it persists as something we all have to manually deal with in every popular language that is ubiquitous today.</p>
<p>And <code>Optional</code> types, <code>Maybe</code> or whatever copium you wrap a <code>null</code> with to check a <code>bool</code> value to see if the reference is <code>null</code> is no better than just returning <code>null</code>, because it carries with it no semantic meaning why <code>null</code> was returned.</p>
<h2 id="heading-this-page-left-intentionally-blank">This Page Left Intentionally Blank</h2>
<p>The phrase <em>"this page intentionally left blank"</em> will be familiar to anyone that remembers reading actual physical manuals.</p>
<p>It served a practical purpose rooted in the mechanics of printing and bookbinding. To avoid confusion and prevent readers from thinking that pages are missing, printers include the <em>"intentionally left blank"</em> notice when a page was blank because of layout or formatting.</p>
<p>In important documents, such as legal contracts or technical manuals, a missing page could have serious consequences. The phrase became more standard with the rise of mass printing and the need for unambiguous consistent documentation of the intent of the printer.</p>
<h2 id="heading-this-reference-left-intentionally-unassigned">This Reference Left Intentionally Unassigned</h2>
<p>The problem with <code>null</code> is there is no semantic meaning to it, it just means this variable does not point to any valid data. It tells you there is nothing to read, but nothing more. This is the <em>“mistake”</em> of <code>null</code>. Is there no data because of an error? Is there no data because the data was asked for and not supplied? Or, was it asked for and actively not provided?</p>
<p>Programming is all about unambiguous instructions to be carried out. We need programming languages to be unambiguous as possible, and we need programmers to use them in as unambiguous ways as possible.</p>
<p>In 1965, large programs were only a few thousand lines of code. 10K lines of code were on the high end of what was even possible given the constraints on memory available. This means one person could read through the code and figure out why some data was missing and hopefully a comment would explain why the value was not set.</p>
<h2 id="heading-null-has-no-default-value">Null has no default value</h2>
<p>The primary misuse of <code>null</code> was to use it as a marker value for a <code>default</code> value. This was propagated to databases and instead of storing default values, they would be converted to <code>null</code> values to save space and the converted back to some default value when they were read and found to be missing.</p>
<p>The problem with this is there is no way to tell if the value was intentionally set to <code>null</code> in the database or it was an error. If it is not an error, what is it supposed to represent down stream?</p>
<p>The source of the data may not even be consistent when converting values to <code>null</code> when storing them and what it converts them back to when they are <code>null</code> when read back from storage.</p>
<p>A <code>null</code> reference to a string is not <code>””</code>, that would be a valid reference to a string with a length of zero bytes. An empty string without any characters.</p>
<h2 id="heading-history-lesson">History Lesson</h2>
<p>I started writing programs in 6502 assembly language, in the early/mid 1980’s. I understand and appreciate the mistakes that we all made when the craft of programming was new. We were all learning, even 20 years after Tony Hoare invented <code>null</code> we still did not have any reason to think it was a problem. Programs were still written on the same scale in terms of lines of code.</p>
<p>In practice back then, the semantics of <code>null</code> vs <code>””</code> were not important. They were the same in practice, even if not in concept.</p>
<p>In C a <code>string</code> was an array of bytes terminated with a confusingly named <code>null</code> terminating character.</p>
<p>A <code>null</code> character was the a byte with all the bits set to ZERO, or a zero byte. Almost all numbers in programs that represented data were encoded in hexadecimal back then, and it was easy enough to convert in your head because every computer was only 8 bits. A single byte ranged from <code>00</code> to <code>FF</code>. That is <code>0</code> to <code>254</code> in value.</p>
<p>In C, a <code>string</code> was encoded as an array of one byte per character plus a terminating zero byte to mark the end of the data. “Hello, World!” would be encoded as; <code>48 6</code>cs theor<code>5 6C 6C 6F 2C 20 57 6F 72 6C 64 21 00</code> in memory in physical storage. The <code>00</code> was the <em>“This Page Left Intentionally Blank”</em> marker to say, no more valid data exists past this point.</p>
<p>In almost every other language since C, the <code>string</code> type is usually represented in memory as a pointer to the array of bytes and the length of the array and the terminating null character is not needed to mark the end of the data. If you with ASCII <code>string</code> values, even with <code>UTF-8</code> encoded Unicode, storing the pointer to the <code>string</code> data and its length is only slightly more data to store than just the pointer. It just depends on the <code>sizeof</code> the pointer itself. For zero length <code>string</code> representations the space trade off is marginal compared to benefits of eliminating entire classes of errors.</p>
<h2 id="heading-perversions-begat-perversions">Perversions begat Perversions</h2>
<p>With the perversion of Alan Kay’s ideas into <em>“Object Oriented Programming”</em> paradigm of the 1990’s came even more corruption of valid concepts debased into <em>“billion dollar mistakes”,</em> because of lack of reading comprehension skills or just plain laziness. Remember, this was pre-internet brained days still, there was no excuses, not that there should be today either.</p>
<p>OOPy programmers immediately saw the flaws and problems with “OO” languages like C++ and instead of fixing the languages, they created contrivances they called “Patterns” of design.</p>
<p>These work around were were so numerous and common place they filled an entire book written by a gang of four people. These “Patterns” were canonized as sliver bullet solutions for lazy or incompetent programmers and treated as religious truths over three decades later.</p>
<p>One of them was called the <em>“Null Object Pattern”</em>, first documented in <em>"Pattern Languages of Program Design"</em> by James Coplien in 1995.</p>
<p>Even though this was conceived during the height of the “OOP” madness. It is arguable the best solution to the problem of dealing with missing data. At least, to the extent that it semantically shows that data is missing on purpose and not by accident to a point.</p>
<h2 id="heading-no-data-value-gt-null-object-gt-optionalt">No Data Value &gt; Null Object &gt; Optional[T]</h2>
<p>A competing concept to the <em>“Null Object”</em> is <em>“Optional[T]”</em> which has its origins in functional programming. Specifically the <code>Maybe</code> type from the programming language Haskell.</p>
<p>In functional programming languages, where Monads work seamlessly in the language, <code>Optional</code> is an elegant solution. In OOPy languages, like that are C++ based syntax; Java, C#, etc and hybrid languages like Go that are not OOPy and not really functional either, they are nothing more than <code>if == null</code> checks with extra steps.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.Optional;

Optional&lt;String&gt; maybeName = getNameFromDatabase(userId);

<span class="hljs-keyword">if</span> (maybeName.isPresent()) {
    String name = maybeName.get();
    System.out.println(<span class="hljs-string">"Name: "</span> + name);
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"Name not found."</span>);
}
</code></pre>
<p>is nothing more code and more indirection than just doing</p>
<pre><code class="lang-java">String name = getNameFromDatabase(userId);

<span class="hljs-keyword">if</span> (name != <span class="hljs-keyword">null</span>) {
    System.out.println(<span class="hljs-string">"Name: "</span> + name);
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"Name not found."</span>);
}
</code></pre>
<p>This is just functional programming language have better abstractions but I really do not want to learn how to think in an actual functional manner so lets wedge the idea into Java brained stupidity.</p>
<p>The same people that promote <code>Optional</code> as the solution to <code>null</code> problem, are the same ones that complain about performance and think less lines of code means better. They have no internal consistency.</p>
<pre><code class="lang-java">String missingName = <span class="hljs-string">"\u0000"</span> <span class="hljs-comment">// zero byte character; traditionally null terminating character.</span>

String name = getNameFromDatabase(userId);

<span class="hljs-keyword">if</span> (!name.equals(missingName)) {
    System.out.println(<span class="hljs-string">"Name: "</span> + name);
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"Name not found"</span>);
}
</code></pre>
<p>Now this is not any fewer lines of code than the raw <code>null</code> check, but it is more semantically rich that it explicitly informs the reader that there was no name returned.</p>
<p>I use the traditional zero byte null character from C, to represent that no data was provided. This value is useful in that if you try and print it out, you do not get an error and you can test for what is a useless value that should not be in any valid data in any real world system.</p>
<p>If for some exceptionally rare case your system does treat a single zero by character (or the Unicode equivalent) as valid data there are literally hundreds (thousands if using Unicode) other characters you can choose from.</p>
<p>Here are some Unicode characters that are specifically suited for use as a marker character for intentionally missing data.</p>
<ul>
<li><p><strong>Null Character (U+0000):</strong></p>
<ul>
<li><p>As demonstrated in the previous Java example, this is a classic choice. It's explicitly designed to represent "null."</p>
</li>
<li><p>However, it can be difficult to display and handle in some environments.</p>
</li>
</ul>
</li>
<li><p><strong>Unit Separator (U+001F):</strong></p>
<ul>
<li><p>This is a control character that's rarely used in normal text.</p>
</li>
<li><p>It's intended for separating data units, this single character by itself can be seen as analogous to representing the absence of data.</p>
</li>
</ul>
</li>
<li><p><strong>Object Replacement Character (U+FFFC):</strong></p>
<ul>
<li><p>This character is often used to represent an unknown or unrenderable object.</p>
</li>
<li><p>While not strictly `null`, it can be used to indicate the absence of a meaningful value.</p>
</li>
</ul>
</li>
<li><p><strong>Zero Width No-Break Space (U+FEFF):</strong></p>
<ul>
<li>While this is often used as a Byte Order Mark, it is also a zero width character, and therefore would not visually show up. It is also very unlikely to be used in normal text.</li>
</ul>
</li>
</ul>
<h2 id="heading-but-how-do-you-communicate-why-the-data-missing">But how do you communicate why the data missing?</h2>
<p>“\u0000” is a better value to use than <code>null</code> to represent missing or no-value data.</p>
<p>It is not perfect, it is will missing the semantics of why the data is missing.</p>
<p>All you have to do is expand on this idea, of invalid printable/invisible characters and you can encode as much information into your missing data as you see fit.</p>
<p>If you look up some data from a data store or external system and the data is missing because it is not found then this would be an semantically appropriate return value.</p>
<p><strong>Object Replacement Character (U+FFFC):</strong></p>
<ul>
<li><p>This character is often used to represent an unknown or unrenderable object.</p>
</li>
<li><p>This can be used to indicate the absence of a meaningful value.</p>
</li>
</ul>
<p>You can always combine one of the above alternatives with one of the following 6400 values to create as many missing data and here is why reason codes as you need!</p>
<ul>
<li><p><strong>Private Use Characters (U+E000–U+F8FF):</strong></p>
<ul>
<li><p>These characters are reserved for private use, so you can choose any character within this range.</p>
</li>
<li><p>This guarantees that it won't conflict with any standard Unicode characters.</p>
</li>
<li><p>This however makes the code less portable.</p>
</li>
</ul>
</li>
</ul>
<p>If you want to get even more clever you can return an entire printable error message up into the Private User Character range by adding <code>0xF8FF</code> to each character so that none of them a printable and to print out the error message move them back down.</p>
<pre><code class="lang-java"><span class="hljs-function">function <span class="hljs-title">stringToByteArray</span><span class="hljs-params">(str)</span> </span>{
    <span class="hljs-keyword">const</span> encoder = <span class="hljs-keyword">new</span> TextEncoder();
    <span class="hljs-keyword">const</span> encoded = encoder.encode(str);
    <span class="hljs-keyword">return</span> Array.from(encoded).map(<span class="hljs-keyword">byte</span> =&gt; <span class="hljs-keyword">byte</span> ^ <span class="hljs-number">0xF8</span>); <span class="hljs-comment">// XOR with a byte value</span>
}

<span class="hljs-function">function <span class="hljs-title">byteArrayToString</span><span class="hljs-params">(byteArray)</span> </span>{
    <span class="hljs-keyword">const</span> decodedBytes = byteArray.map(<span class="hljs-keyword">byte</span> =&gt; <span class="hljs-keyword">byte</span> ^ <span class="hljs-number">0xF8</span>); <span class="hljs-comment">// XOR with the same byte value</span>
    <span class="hljs-keyword">const</span> decoder = <span class="hljs-keyword">new</span> TextDecoder();
    <span class="hljs-keyword">return</span> decoder.decode(<span class="hljs-keyword">new</span> Uint8Array(decodedBytes));
}

<span class="hljs-function">function <span class="hljs-title">isErrorMsg</span><span class="hljs-params">(byteArray)</span> </span>{
    <span class="hljs-keyword">for</span> (let i = <span class="hljs-number">0</span>; i &lt; byteArray.length; i++) {
        <span class="hljs-comment">// Basic printable character range (ASCII)</span>
        <span class="hljs-keyword">if</span> (i &gt;= <span class="hljs-number">0xF8FF</span>) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        }
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
}

<span class="hljs-comment">// Example usage:</span>
<span class="hljs-keyword">const</span> inputString = <span class="hljs-string">"Hello, world! 😊"</span>;
console.log(inputString);
<span class="hljs-keyword">const</span> byteArray = stringToByteArray(inputString);
console.log(<span class="hljs-string">"isError:"</span>,isErrorMsg(byteArray));
console.log(byteArray);

<span class="hljs-keyword">const</span> decodedString = byteArrayToString(byteArray);
console.log(decodedString);
</code></pre>
<p>This outputs the following.</p>
<pre><code class="lang-javascript">Hello, world! 😊
<span class="hljs-attr">isError</span>: <span class="hljs-literal">true</span>
[
  <span class="hljs-number">176</span>, <span class="hljs-number">157</span>, <span class="hljs-number">148</span>, <span class="hljs-number">148</span>, <span class="hljs-number">151</span>,
  <span class="hljs-number">212</span>, <span class="hljs-number">216</span>, <span class="hljs-number">143</span>, <span class="hljs-number">151</span>, <span class="hljs-number">138</span>,
  <span class="hljs-number">148</span>, <span class="hljs-number">156</span>, <span class="hljs-number">217</span>, <span class="hljs-number">216</span>,   <span class="hljs-number">8</span>,
  <span class="hljs-number">103</span>,  <span class="hljs-number">96</span>, <span class="hljs-number">114</span>
]
Hello, world! 😊
</code></pre>
<p>This is just an example using the lowly <code>string</code>, you are probably wondering how you would deal with a more complex data type like a <code>Person</code>?</p>
<pre><code class="lang-javascript">
<span class="hljs-comment">/**
 * string marker value for not being initialized
 * this is more semantically informational that using null or undefined
 * since this shows deliberate intention; ie:This Page Intentionally Blank
 * <span class="hljs-doctag">@type <span class="hljs-type">{string}</span></span>
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> no_string_data = <span class="hljs-string">'\u0000'</span>;

<span class="hljs-comment">/**
 * Date marker value for not being initialized
 * since this shows deliberate intention; ie:This Page Intentionally Blank
 * @type {Date}
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> no_date_data = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-string">'0001-01-01T00:00:00.000Z'</span>);

<span class="hljs-comment">/**
 * uint marker value for not being initialized
 * since there are only number types, this shows two things, that the variable
 * is intended to represent unsigned integers, by using a negative value
 * this shows deliberate intention; ie:This Page Intentionally Blank
 * @type {number}
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> no_uint_data = <span class="hljs-number">-1</span>;

<span class="hljs-comment">/**
 * this string represents the lack of a boolean value
 * the idea is to union string with boolean as valid values
 * and test for this specific string if the value is a string type.
 * Zero Width No-Break Space - \uFEFF
 * @type {string}
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> no_bool_data = <span class="hljs-string">"\uFEFF"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isNoBooleanData</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> value === <span class="hljs-string">'string'</span>) {
    <span class="hljs-keyword">return</span> value === no_bool_data;
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}

<span class="hljs-comment">/**
 *
 * <span class="hljs-doctag">@type <span class="hljs-type">{{id: string,
           first_name: string, 
           last_name: string, 
           opininated: boolean, 
           birthday: Date, 
           age: number
          }</span></span>}
 */</span>
<span class="hljs-keyword">const</span> no_person_data = {
    <span class="hljs-attr">id</span>: no_string_data,
    <span class="hljs-attr">first_name</span>: no_string_data,
    <span class="hljs-attr">last_name</span>: no_string_data,
    <span class="hljs-attr">opinionated</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">birthday</span>: no_date_data,
    <span class="hljs-attr">age</span>: no_uint_data,
}
</code></pre>
<p>The one obvious exception to these approaches, and there is always at least one, is the Boolean type.</p>
<p>In this example, I could have done the lazy thing and just set <code>opinionated = false</code> and been done with it, but that would not be the wise choice given that all the other datatypes have <code>no_data</code> alternatives to check for.</p>
<p>With only two values, both of which are equally valid as data how to you deal with missing data.</p>
<p>In languages that are not strongly typed like JavaScript you have alternatives.</p>
<p>Here I have used the <code>no_bool_data</code> value which I set to the Zero Width No-Break Space, the test becomes simple, <code>isNoBoolData()</code> is no more code that <code>== null</code> or <code>isPresent()</code> and much more semantically informational.</p>
<h2 id="heading-specific-no-data-types">Specific No Data Types</h2>
<p>In strictly typed languages you can create specific no data types and check for the type or use a language feature to test for missing data. This is just one example of one approach in Go.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-keyword">type</span> NotProvided <span class="hljs-keyword">string</span>

<span class="hljs-keyword">const</span> firstNameNotProvided = NotProvided(<span class="hljs-string">"\u0000\uF8FF"</span>)
<span class="hljs-keyword">const</span> lastNameNotProvided = NotProvided(<span class="hljs-string">"\u0000\uF900"</span>)


<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isNotProvidedType</span>[<span class="hljs-title">T</span> <span class="hljs-title">string</span> | <span class="hljs-title">NotProvided</span>]<span class="hljs-params">(val T)</span> <span class="hljs-title">bool</span></span> {
    _, ok := <span class="hljs-keyword">interface</span>{}(val).(NotProvided)
    <span class="hljs-keyword">return</span> ok
}


<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    fmt.Printf(<span class="hljs-string">"data provided: %t\n"</span>, isNotProvidedType(<span class="hljs-string">"this is a test"</span>))
    fmt.Printf(<span class="hljs-string">"first name provided: %t\n"</span>, isNotProvidedType(firstNameNotProvided))
    fmt.Printf(<span class="hljs-string">"last name provided: %t\n"</span>, isNotProvidedType(lastNameNotProvided))
}
</code></pre>
<p>this results in this output</p>
<pre><code class="lang-go">data provided: <span class="hljs-literal">false</span>
first name provided: <span class="hljs-literal">true</span>
last name provided: <span class="hljs-literal">true</span>
</code></pre>
<p>Language with matching syntax like Erlang make this even easier, but then again functional languages have elegant compositional chaining that procedural languages usually do not.</p>
<h2 id="heading-strongly-typed-languages">Strongly Typed Languages</h2>
<p>Even though languages like Go have the concept of <code>nil</code> which is effectively a strongly typed <code>null reference</code> and points to that types Zero Value. Which is different depending on the type.</p>
<p>It still suffers from lack of semantic meaning other than, <code>nothing</code> of a type and I find myself using No Data types that I can test against for reasons why something is not returning data.</p>
<p>Go is not the best example either because of its idiom of returning an error value when ever a return value could be <code>nil</code> to explain why it is <code>nil</code> and of course the way to check if there is no error is to check and see if the returned <code>error</code> is <code>nil</code>.</p>
<p>Yet some functions return back a boolean, <code>ok/exists/success</code> type value to signal that a value was returned successfully. As in when asserting an <code>interface{}</code> is of a type, or checking to see if <code>map</code> has a value for a key.</p>
<pre><code class="lang-go"><span class="hljs-comment">// pre-generics way to test if something is of a type</span>
<span class="hljs-keyword">var</span> val <span class="hljs-keyword">interface</span>{}
<span class="hljs-keyword">if</span> _, ok := val.(<span class="hljs-keyword">string</span>); ok {
   fmt.Println(<span class="hljs-keyword">string</span>(val))
}


<span class="hljs-comment">// does a map[string]interface{} contain a key</span>
<span class="hljs-comment">// if the value is a pointer type you could test</span>
<span class="hljs-comment">// v != nil but that is less informational than exists</span>
m := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">string</span>)
<span class="hljs-keyword">if</span> v, exists := m[<span class="hljs-string">"somekey"</span>]; exists {
    fmt.Println(v)
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>There is no reason to compromise your data integrity and code clarity by slinging <code>null</code> all over your code base.</p>
<p>The more important concept is downstream data consumers.</p>
<p>When others access your data they need to know why data is missing so they can feel confident in the validity of the data. Especially if you are the authoritative source of the data.</p>
<p>If you change your rules for what <code>null</code> represents as <code>default</code> when read back in, there is no way for downstream consumers to know about this change. They might have see that <code>null</code> actually means <code>0</code> for some datum, but you decide that it actually means <code>-1</code> now.</p>
<p>This causes confusion and havoc for downstream consumers use the data and forward what is now the wrong data downstream when they replace the <code>null</code> with what they think the <code>default</code> value should be.</p>
<p>When that data comes full circle back to the authoritative source more time and money will be lost than the time and money it takes to avoid the possibility in the first place.</p>
]]></content:encoded></item><item><title><![CDATA[iter.Seq in practice]]></title><description><![CDATA[FirstN
Returns the first N items from a sequence.
// FirstN takes an iter.Seq[int] and returns a new iter.Seq[int] that
// yields only the first 'limit' items without creating intermediate slices.
func FirstN[T any](original iter.Seq[T], limit int) i...]]></description><link>https://blog.vertigrated.com/iterseq-in-practice</link><guid isPermaLink="true">https://blog.vertigrated.com/iterseq-in-practice</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[iterator]]></category><category><![CDATA[Firebase]]></category><category><![CDATA[firestore]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Thu, 20 Feb 2025 00:35:14 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-firstn">FirstN</h2>
<p>Returns the first N items from a sequence.</p>
<pre><code class="lang-go"><span class="hljs-comment">// FirstN takes an iter.Seq[int] and returns a new iter.Seq[int] that</span>
<span class="hljs-comment">// yields only the first 'limit' items without creating intermediate slices.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">FirstN</span>[<span class="hljs-title">T</span> <span class="hljs-title">any</span>]<span class="hljs-params">(original iter.Seq[T], limit <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">T</span>]</span> {
    <span class="hljs-keyword">return</span> iter.Seq[T](<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(T)</span> <span class="hljs-title">bool</span>)</span> {
        count := <span class="hljs-number">0</span>
        <span class="hljs-keyword">for</span> item := <span class="hljs-keyword">range</span> original {
            <span class="hljs-keyword">if</span> count &lt; limit {
                <span class="hljs-keyword">if</span> !yield(item) {
                    <span class="hljs-keyword">return</span>
                }
                count++
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span>
            }
        }
    })
}
</code></pre>
<h2 id="heading-skipfirstn">SkipFirstN</h2>
<p>Skips the first N items and returns the rest of the sequence.</p>
<p>This could have been done with a regular push iterator, but it would take an intermediate count to keep up with how many items had been skipped and not be quiet as clear what was happening.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">SkipFirstN</span>[<span class="hljs-title">T</span> <span class="hljs-title">any</span>]<span class="hljs-params">(seq iter.Seq[T], skip <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">T</span>]</span> {
    <span class="hljs-keyword">return</span> iter.Seq[T](<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(T)</span> <span class="hljs-title">bool</span>)</span> {
       next, stop := iter.Pull[T](seq)
       <span class="hljs-keyword">defer</span> stop()

       <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt;= skip; i++ {
          _, ok := next()
          <span class="hljs-keyword">if</span> !ok {
             <span class="hljs-keyword">break</span>
          }
       }
       <span class="hljs-keyword">for</span> {
          v, ok := next()
          <span class="hljs-keyword">if</span> !ok {
             <span class="hljs-keyword">break</span>
          }
          <span class="hljs-keyword">if</span> !yield(v) {
             <span class="hljs-keyword">return</span>
          }
       }
    })
}
</code></pre>
<h2 id="heading-skipandlimit-aka-subseq">SkipAndLimit (aka: SubSeq)</h2>
<p>Example inline composition of <code>FirstN</code> and <code>SkipFirstN</code> this is just an example.</p>
<p>This is the equivalent of doing <code>[first:limit]</code> on a <code>slice</code> but on an <code>iter.Seq</code> as it is processed as a zero cost abstraction.</p>
<pre><code class="lang-go"><span class="hljs-comment">// I wrapped this in a function as straw man example just to get the highlighting to work</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">SkipAndLimit</span>[<span class="hljs-title">V</span> <span class="hljs-title">any</span>]<span class="hljs-params">(it iter.Seq[V],, skip <span class="hljs-keyword">int</span>, limit <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">V</span>]</span> {
    <span class="hljs-keyword">return</span> FirstN[V](SkipFirstN[V](it, skip), limit)
}

<span class="hljs-comment">// you could just inline the composition like this, but this is not as self documenting</span>
<span class="hljs-comment">// as calling a function that semantically shows intent  in its name.</span>
subSeq := FirstN[<span class="hljs-keyword">string</span>](SkipFirstN[<span class="hljs-keyword">string</span>](it, skip, limit)
</code></pre>
<h2 id="heading-chunk">Chunk</h2>
<p>creates a sequence of fixed size sequences from the original sequence without creating any intermediate slices or arrays.</p>
<p>This is useful when you are feeding an api data that only accepts N number of items at time. With some work this could be made to work with goroutines and channels to process the chunks in parallel as they are generated.</p>
<pre><code class="lang-go"><span class="hljs-comment">// Chunk returns an iterator over consecutive sub-slices of up to n elements of s.</span>
<span class="hljs-comment">// All but the last iter.Seq chunk will have size n.</span>
<span class="hljs-comment">// Chunk panics if n is less than 1.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Chunk</span>[<span class="hljs-title">T</span> <span class="hljs-title">any</span>]<span class="hljs-params">(sq iter.Seq[T], size <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">T</span>]]</span> {
    <span class="hljs-keyword">if</span> size &lt; <span class="hljs-number">0</span> {
       <span class="hljs-built_in">panic</span>(errs.MinSizeExceededError.New(<span class="hljs-string">"size %d must be &gt;= 0"</span>, size))
    }

    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(s iter.Seq[T])</span> <span class="hljs-title">bool</span>)</span> {
       next, stop := iter.Pull[T](sq)
       <span class="hljs-keyword">defer</span> stop()
       endOfSeq := <span class="hljs-literal">false</span>
       <span class="hljs-keyword">for</span> !endOfSeq {
          <span class="hljs-comment">// get the first item for the chunk</span>
          v, ok := next()
          <span class="hljs-comment">// there are no more items !ok then exit loop</span>
          <span class="hljs-comment">// this prevents returning an extra empty iter.Seq at end of Seq</span>
          <span class="hljs-keyword">if</span> !ok {
             <span class="hljs-keyword">break</span>
          }
          <span class="hljs-comment">// create the next sequence chunk</span>
          iterSeqChunk := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(T)</span> <span class="hljs-title">bool</span>)</span> {
             i := <span class="hljs-number">0</span>
             <span class="hljs-keyword">for</span> ; i &lt; size; i++ {
                <span class="hljs-keyword">if</span> ok {
                   <span class="hljs-keyword">if</span> !ok {
                      <span class="hljs-comment">// end of original sequence</span>
                      <span class="hljs-comment">// this sequence may be &lt;= size</span>
                      endOfSeq = <span class="hljs-literal">true</span>
                      <span class="hljs-keyword">break</span>
                   }

                   <span class="hljs-keyword">if</span> !yield(v) {
                      <span class="hljs-keyword">return</span>
                   }
                   v, ok = next()
                }
             }
          }
          <span class="hljs-keyword">if</span> !yield(iterSeqChunk) {
             <span class="hljs-keyword">return</span>
          }
       }
    }
}
</code></pre>
<h2 id="heading-chunk2">Chunk2</h2>
<p>Same idea as <code>Chunk</code> but works on <code>iter.Seq2</code></p>
<pre><code class="lang-go"><span class="hljs-comment">// Chunk2 returns an iterator over consecutive sub-slices of up to n elements of s.</span>
<span class="hljs-comment">// All but the last iter.Seq chunk will have size n.</span>
<span class="hljs-comment">// Chunk2 panics if n is less than 1.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Chunk2</span>[<span class="hljs-title">K</span> <span class="hljs-title">any</span>, <span class="hljs-title">V</span> <span class="hljs-title">any</span>]<span class="hljs-params">(sq iter.Seq2[K, V], size <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">iter</span>.<span class="hljs-title">Seq2</span>[<span class="hljs-title">K</span>, <span class="hljs-title">V</span>]]</span> {
    <span class="hljs-keyword">if</span> size &lt; <span class="hljs-number">0</span> {
        <span class="hljs-built_in">panic</span>(errs.MinSizeExceededError.New(<span class="hljs-string">"size %d must be &gt;= 0"</span>, size))
    }

    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(s iter.Seq2[K, V])</span> <span class="hljs-title">bool</span>)</span> {
        next, stop := iter.Pull2[K, V](sq)
        <span class="hljs-keyword">defer</span> stop()
        endOfSeq := <span class="hljs-literal">false</span>
        <span class="hljs-keyword">for</span> !endOfSeq {
            <span class="hljs-comment">// get the first item for the chunk</span>
            k, v, ok := next()
            <span class="hljs-comment">// there are no more items !ok then exit loop</span>
            <span class="hljs-comment">// this prevents returning an extra empty iter.Seq at end of Seq</span>
            <span class="hljs-keyword">if</span> !ok {
                <span class="hljs-keyword">break</span>
            }
            <span class="hljs-comment">// create the next sequence chunk</span>
            iterSeqChunk := <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(K, V)</span> <span class="hljs-title">bool</span>)</span> {
                i := <span class="hljs-number">0</span>
                <span class="hljs-keyword">for</span> ; i &lt; size; i++ {
                    <span class="hljs-keyword">if</span> ok {
                        <span class="hljs-keyword">if</span> !ok {
                            <span class="hljs-comment">// end of original sequence</span>
                            <span class="hljs-comment">// this sequence may be &lt;= size</span>
                            endOfSeq = <span class="hljs-literal">true</span>
                            <span class="hljs-keyword">break</span>
                        }

                        <span class="hljs-keyword">if</span> !yield(k, v) {
                            <span class="hljs-keyword">return</span>
                        }
                        k, v, ok = next()
                    }
                }
            }
            <span class="hljs-keyword">if</span> !yield(iterSeqChunk) {
                <span class="hljs-keyword">return</span>
            }
        }
    }
}
</code></pre>
<h2 id="heading-seqtoseq2">SeqToSeq2</h2>
<p>This function takes a sequence and a key generator function and returns an <code>iter.Seq2</code> without creating any intermediate slices or arrays.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">SeqToSeq2</span>[<span class="hljs-title">K</span> <span class="hljs-title">any</span>, <span class="hljs-title">V</span> <span class="hljs-title">any</span>]<span class="hljs-params">(is iter.Seq[V], keyFunc <span class="hljs-keyword">func</span>(v V)</span> <span class="hljs-title">K</span>) <span class="hljs-title">iter</span>.<span class="hljs-title">Seq2</span>[<span class="hljs-title">K</span>, <span class="hljs-title">V</span>]</span> {
    <span class="hljs-keyword">return</span> iter.Seq2[K, V](<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(K, V)</span> <span class="hljs-title">bool</span>)</span> {
       <span class="hljs-keyword">for</span> v := <span class="hljs-keyword">range</span> is {
          k := keyFunc(v)
          <span class="hljs-keyword">if</span> !yield(k, v) {
             <span class="hljs-keyword">return</span>
          }
       }
    })
}
</code></pre>
<h2 id="heading-map">Map</h2>
<p>Most of you probably think I should have put this one first. It is the most similar to a Monad with the <code>bind</code> and <code>map</code> behavior, it is named Map for a reason.</p>
<p>But that would completely miss the point of the <code>iter</code> package. It is not about functional programing, it is about a idiomatic way to create your own custom iterable types.</p>
<p>This is the closest to Monad behavior by definition, skipping the <code>bind</code> semantics and just applying the <code>map</code> function to the value. If your value object had a field called <code>ID</code> that should be the key, the <code>keyFunc</code> would be as simple as returning <code>v.ID</code> or as complex as calculating a <code>SHA256</code> hash of the object to use as the key. Or something that is not even a map, like returning <code>FirstName</code> and <code>LastName</code> from <code>Person</code> structs.</p>
<p>The fact that the <code>K</code> value is typed <code>any</code> and not <code>comparable</code> means it is not just for keys from maps.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Map</span>[<span class="hljs-title">T</span> <span class="hljs-title">any</span>, <span class="hljs-title">R</span> <span class="hljs-title">any</span>]<span class="hljs-params">(it iter.Seq[T], mapFunc <span class="hljs-keyword">func</span>(t T)</span> <span class="hljs-title">R</span>) <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">R</span>]</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(R)</span> <span class="hljs-title">bool</span>)</span> {
        <span class="hljs-keyword">for</span> i := <span class="hljs-keyword">range</span> it {
            <span class="hljs-keyword">if</span> !yield(mapFunc(i)) {
                <span class="hljs-keyword">return</span>
            }
        }
    }
}
</code></pre>
<h2 id="heading-map2">Map2</h2>
<p>Does the same thing as <code>Map</code> but allows to provide for both a <code>K</code> and <code>V</code> transform function.</p>
<p>A canonical <code>PassThruFunc</code> for the times when I did not want to change the key or value.</p>
<p>Using this instead of writing in inline is better because it shows intent to not do anything with the value. An inline function shows no intent. Much like “This Page Left Intentionally Blank” shows intent to the reader that they are not missing a page by accident. Very important for everyone reading it in the future, yourself included. It could also be used for the value when only the <code>K</code> needs to be transformed.</p>
<pre><code class="lang-go"><span class="hljs-comment">// PassThruFunc passes thru the value unchanged</span>
<span class="hljs-comment">// this is just a convience function for times when you do not want to transform the key or value in Map2</span>
<span class="hljs-comment">// so you do not have to write an inline function and clutter up the code more than it needs to be.</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">PassThruFunc</span>[<span class="hljs-title">T</span> <span class="hljs-title">any</span>]<span class="hljs-params">(t T)</span> <span class="hljs-title">T</span></span> {
    <span class="hljs-keyword">return</span> t
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Map2</span>[<span class="hljs-title">K</span> <span class="hljs-title">any</span>, <span class="hljs-title">V</span> <span class="hljs-title">any</span>, <span class="hljs-title">KR</span> <span class="hljs-title">any</span>, <span class="hljs-title">VR</span> <span class="hljs-title">any</span>]<span class="hljs-params">(it iter.Seq2[K, V], keyFunc <span class="hljs-keyword">func</span>(k K)</span> <span class="hljs-title">KR</span>, <span class="hljs-title">valFunc</span> <span class="hljs-title">func</span><span class="hljs-params">(v V)</span> <span class="hljs-title">VR</span>) <span class="hljs-title">iter</span>.<span class="hljs-title">Seq2</span>[<span class="hljs-title">KR</span>, <span class="hljs-title">VR</span>]</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(KR, VR)</span> <span class="hljs-title">bool</span>)</span> {
        <span class="hljs-keyword">for</span> k, v := <span class="hljs-keyword">range</span> it {
            <span class="hljs-keyword">if</span> !yield(keyFunc(k), valFunc(v)) {
                <span class="hljs-keyword">return</span>
            }
        }
    }
}
</code></pre>
<h2 id="heading-documentiteratortoseq">DocumentIteratorToSeq</h2>
<p>Firestore Document Iterator is one of the many non-standard iterator implementations that abound in Go libraries and clients</p>
<p>Here it is wrapped in an iter.Seq without any intermediate slices or arrays being generated.</p>
<pre><code class="lang-go"><span class="hljs-comment">// DocumentIteratorToSeq converts a firestore.Iterator to an iter.Seq.</span>
<span class="hljs-comment">// value is a pointer to the type V</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">DocumentIteratorToSeq</span><span class="hljs-params">(dsi *fs.DocumentIterator)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[*<span class="hljs-title">fs</span>.<span class="hljs-title">DocumentSnapshot</span>]</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(ref *fs.DocumentSnapshot)</span> <span class="hljs-title">bool</span>)</span> {
        <span class="hljs-keyword">defer</span> dsi.Stop()
        <span class="hljs-keyword">for</span> {
            doc, err := dsi.Next()
            <span class="hljs-keyword">if</span> errors.Is(err, iterator.Done) {
                <span class="hljs-keyword">return</span>
            }
            <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
                log.Error().Err(err).Msg(<span class="hljs-string">"error iterating through Firestore documents"</span>)
                <span class="hljs-keyword">return</span>
            }
            <span class="hljs-keyword">if</span> !yield(doc) {
                <span class="hljs-keyword">return</span>
            }
        }
    }
}
</code></pre>
<h2 id="heading-docsnapshotseqtotype">DocSnapShotSeqToType</h2>
<p>Here we create a semantically named function that represents something that needs to be done repeatedly. Iterator over a collection of DocumentSnapShots and convert them to actual Types.</p>
<p>The <code>seq.Map</code> function I wrote is usually simple enough to inline, but some cases are so common and repeated it makes sense to semantically name them for ease of use. And no naming it not that hard unless you are not a native English speaker or your function is so poorly designed it can not be named semantically specific.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">DocSnapShotSeqToType</span>[<span class="hljs-title">R</span> <span class="hljs-title">any</span>]<span class="hljs-params">(it iter.Seq[*fs.DocumentSnapshot])</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[*<span class="hljs-title">R</span>]</span> {
    <span class="hljs-keyword">return</span> seq.Map[*fs.DocumentSnapshot, *R](it, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(dss *fs.DocumentSnapshot)</span> *<span class="hljs-title">R</span></span> {
        <span class="hljs-keyword">var</span> t R
        err := dss.DataTo(&amp;t)
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            log.Error().Err(err).Msgf(<span class="hljs-string">"error unmarshalling Firestore document with ID %s"</span>, dss.Ref.ID)
            <span class="hljs-built_in">panic</span>(err)
        }
        <span class="hljs-keyword">return</span> &amp;t
    })
}
</code></pre>
<h2 id="heading-documentiteratortoseq2">DocumentIteratorToSeq2</h2>
<p>Same as above but the DocumentSnapShot.Ref.Id is used as the <code>K</code> value as a <code>string</code> in the returned <code>iter.Seq2</code>.</p>
<p>This is short enough to inline, but I need to do this in lots of places in library code over and over again so making a semantically intuitive named function makes my code clearer and more readable for intent.</p>
<p>I make a point of always using <code>string</code> types for document id so this is used everywhere I process collections.</p>
<pre><code class="lang-go"><span class="hljs-comment">// DocumentIteratorToSeq2 converts a firestore.Iterator to an iter.Seq2.</span>
<span class="hljs-comment">// doc.Ref.ID is used as the "key" or first value, second value is a pointer to the type V</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">DocumentIteratorToSeq2</span><span class="hljs-params">(dsi *fs.DocumentIterator)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq2</span>[*<span class="hljs-title">fs</span>.<span class="hljs-title">DocumentRef</span>, *<span class="hljs-title">fs</span>.<span class="hljs-title">DocumentSnapshot</span>]</span> {
    <span class="hljs-keyword">return</span> seq.SeqToSeq2[*fs.DocumentRef, *fs.DocumentSnapshot](DocumentIteratorToSeq(dsi), <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(v *fs.DocumentSnapshot)</span> *<span class="hljs-title">fs</span>.<span class="hljs-title">DocumentRef</span></span> {
        <span class="hljs-keyword">return</span> v.Ref
    })
}
</code></pre>
<p>Another <code>iter.Seq2</code> that is useful for Firestore manipulation is <code>[path, DocumentSnapshot]</code> which is easy to inline as the following and probably warrants its own function if it gets used often enough.</p>
<pre><code class="lang-go">pathDocumentSnapshot := seq.SeqToSeq2[<span class="hljs-keyword">string</span>, *fs.DocumentSnapshot](DocumentIteratorToSeq(dsi), <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(v *fs.DocumentSnapshot)</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> v.Ref.Path
})
</code></pre>
<h2 id="heading-imports">Imports</h2>
<p>Here is a list of the imports used in the code examples above.</p>
<p>I started using ZeroLog long before slog was added to the standard library and I have gotten spoiled by its features. Most of I rarely use, but when I do need them they are important and not in the slog implementation.</p>
<p>I do not want to have to maintain mixed logging APIs. I had to deal with that in the Java world where sometimes 4 or more different logging libraries were used in a code base and adapters and all that were a nightmare. So, it is easier to just stick with ZeroLog rather than convert all the dependencies I use that I have written to slog.</p>
<p>Errorx is also something I have come to rely on heavily, it makes it really easy to have semantically specific type safe errors so when things breaks in a server with dozens of nested calls in the tree it is not a mystery where, what and why something happened.</p>
<pre><code class="lang-go"><span class="hljs-keyword">import</span> (
    <span class="hljs-string">"iter"</span>
    <span class="hljs-string">"slices"</span>
    <span class="hljs-string">"strings"</span>

    fs <span class="hljs-string">"cloud.google.com/go/firestore"</span>
    <span class="hljs-string">"google.golang.org/api/iterator"</span>
    <span class="hljs-string">"github.com/rs/zerolog/log"</span>
    <span class="hljs-string">"github.com/joomcode/errorx"</span>
    errs <span class="hljs-string">"github.com/jarrodhroberson/ossgo/errors"</span>
)
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Go team is sneaking Monadish behavior into the standard library]]></title><description><![CDATA[standardizing an idiomatic approach to iterators can now make dealing with large slices and maps much more efficient, this is a much better approach than introducing a streaming specific syntax.
These new function definitions are much more flexible t...]]></description><link>https://blog.vertigrated.com/go-team-is-sneaking-monadish-into-the-standard-library</link><guid isPermaLink="true">https://blog.vertigrated.com/go-team-is-sneaking-monadish-into-the-standard-library</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Monad]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Thu, 20 Feb 2025 00:18:52 GMT</pubDate><content:encoded><![CDATA[<p>standardizing an idiomatic approach to iterators can now make dealing with large slices and maps much more efficient, this is a much better approach than introducing a streaming specific syntax.</p>
<p>These new function definitions are much more flexible that they might first look. I am writing wrappers around all the non-standard iterator like collection or streaming data access that I deal with daily and decided to share my solutions with you.</p>
<p>This is what the definitions of these functions look like.</p>
<p>The first one is for iterating over a stream of single return values. In Go this means slices and arrays.</p>
<p>The great thing is now you can define your own “Collection” types and provide an idiomatic iterator for them now.</p>
<pre><code class="lang-go"><span class="hljs-comment">// Seq is an iterator over sequences of individual values.</span>
<span class="hljs-comment">// When called as seq(yield), seq calls yield(v) for each value v in the sequence,</span>
<span class="hljs-comment">// stopping early if yield returns false.</span>
<span class="hljs-comment">// See the [iter] package documentation for more details.</span>
<span class="hljs-keyword">type</span> Seq[V any] <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(V)</span> <span class="hljs-title">bool</span>)</span>
</code></pre>
<p>The implementation of these seem to be confusing a lot of people. Some people think it is too complicated, some people think is it too simple.</p>
<p>I really want to say you are iterating over a <code>list</code> of items, but that is not correct, it might not be a list, so I will use the term <code>sequence</code> because that is the most semantically correct.</p>
<p>I think they reached a very good balance with minimal complexity for maximum functionality. Is this implementation as powerful as the iteration in functional languages. No, but it does 80% or more of what they do and pretty close to 100% of what the majority of people actually use day to day for minimal complexity.</p>
<p>Here is a non-contrived example that is short enough to be written inline if you need to generate a simple range of numbers. I put it in a function for some testing I was doing to generate data for more complex adapters and wrappers to use as contrived test data.</p>
<p>This does just what it says in the name of the function, it generates a sequence of <code>ints</code> from start to end inclusive.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">IntRange</span><span class="hljs-params">(start <span class="hljs-keyword">int</span>, end <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">int</span>]</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">bool</span>)</span> {
        <span class="hljs-keyword">for</span> i := start; i &lt;= end; i++ {
            <span class="hljs-keyword">if</span> !yield(i) {
                <span class="hljs-keyword">return</span>
            }
        }
    }
}

<span class="hljs-comment">// here is how you would use it</span>
ints := seq.IntRange(<span class="hljs-number">0</span>, <span class="hljs-number">99</span>)

<span class="hljs-keyword">for</span> i := <span class="hljs-keyword">range</span> ints { 
    fmt.Println(<span class="hljs-string">"%d"</span>, i
}
</code></pre>
<p>The great thing about these new iterator functions is you do not have to allocate a bunch of memory to process sequences of data that is being dynamically generated. Whether that is from an algorithm or from some I/O operations it makes everything “look” the same in the code.</p>
<p>This way of iterating a sequence is considered a “Push” method. It is very much like <code>.Each()</code>/<code>.ForEach</code>() would be in other languages. The implementation is very much like <code>generators</code> in Python. They even share the <code>yield</code> keyword. There are similar in some ways and different in others.</p>
<p>The most important difference is that the Go implementation is a specific function definition, not just a keyword you can put in any function.</p>
<h2 id="heading-monadish-composition">Monadish composition</h2>
<p>The most powerful thing about this new feature is you can chain them in a very Monadish manner.</p>
<p>This function takes any thing with a <code>.Stringer()</code> interface and returns the value of <code>.String()</code> in a lazy generative manner. It only does the processing when it is required.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">ToString</span>[<span class="hljs-title">T</span> <span class="hljs-title">fmt</span>.<span class="hljs-title">Stringer</span>]<span class="hljs-params">(it iter.Seq[T])</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">string</span>]</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(<span class="hljs-keyword">string</span>)</span> <span class="hljs-title">bool</span>)</span> {
        <span class="hljs-keyword">for</span> i := <span class="hljs-keyword">range</span> it {
            <span class="hljs-keyword">if</span> !yield(i.String()) {
                <span class="hljs-keyword">return</span>
            }
        }
    }
}
</code></pre>
<p>This basically wraps another <code>iter.Seq</code> and transforms the data as it requested. You can chain like this to filter things out or add things in very clearly and concisely.</p>
<p>This is one of the most important things to know about these new functions. They were designed for composition. If you do not understand Monads and you can learn how these functions work, then you are actually about 90% of the way there.</p>
<p>Go is not a functional language, and as we know with the attempts to shoehorn functional programming paradigms where they do not fit; Java, JavaScript. Go is no exception, but these iterator functions do not feel forced or out of place. They fit naturally into the idiomatic code that you have been writing for the last ten years.</p>
<h2 id="heading-iterseq2">iter.Seq2</h2>
<p>iter.Seq2 is the map-like iterator. It is not limited to maps and is not even specifically tied to the <code>map[]</code> type. If you read the source, the two values it returns are labeled <code>K,</code>V but the <code>k</code> type is <code>any</code> and not restricted to <code>comparable</code> like <code>map[]</code> would limit keys.</p>
<p>Therefore you can use it to iterator over sequences and expose their unique ids as the <code>K</code> and the actual item in the list as the <code>V</code>. There is a good argument to make that <code>iter.Seq2</code> could be more useful in almost every case where you are dealing with a sequence of <code>Entity</code> type data (data that has an identity). <code>iter.Seq</code> would still be the best semantic choice for sequences of scalar/value objects.</p>
<p>In this next example I create a <code>iter.Pull</code> wrapper around an inline <code>iter.Seq</code> that simply generates an integer one more than the last one. Do not worry about the <code>iter.Pull</code> I will explain it next, it is very simple to understand.</p>
<p>Then I pass that as a function to <code>seq.SeqtoSeq2</code> to use as a key generator for the values from ints.</p>
<pre><code class="lang-go">    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">SeqToSeq2</span>[<span class="hljs-title">K</span> <span class="hljs-title">any</span>, <span class="hljs-title">V</span> <span class="hljs-title">any</span>]<span class="hljs-params">(is iter.Seq[V], keyFunc <span class="hljs-keyword">func</span>(v V)</span> <span class="hljs-title">K</span>) <span class="hljs-title">iter</span>.<span class="hljs-title">Seq2</span>[<span class="hljs-title">K</span>, <span class="hljs-title">V</span>]</span> {
        <span class="hljs-keyword">return</span> iter.Seq2[K, V](<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(K, V)</span> <span class="hljs-title">bool</span>)</span> {
            <span class="hljs-keyword">for</span> v := <span class="hljs-keyword">range</span> is {
                k := keyFunc(v)
                <span class="hljs-keyword">if</span> !yield(k, v) {
                    <span class="hljs-keyword">return</span>
                }
            }
        })
    }

    <span class="hljs-comment">// key generator sequence</span>
    next, stop := iter.Pull(<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(start <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">iter</span>.<span class="hljs-title">Seq</span>[<span class="hljs-title">int</span>]</span> {
        index := start
        <span class="hljs-keyword">return</span> iter.Seq[<span class="hljs-keyword">int</span>](<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(yield <span class="hljs-keyword">func</span>(<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">bool</span>)</span> {
            <span class="hljs-keyword">for</span> {
                <span class="hljs-keyword">if</span> !yield(index) {
                    <span class="hljs-keyword">return</span>
                }
                index++
            }
        })
    }(<span class="hljs-number">0</span>)) <span class="hljs-comment">// creates an infinitely increating counter generator</span>

    ints := seq.IntRange(<span class="hljs-number">0</span>, <span class="hljs-number">99</span>)

    intMap := seq.SeqToSeq2[<span class="hljs-keyword">int</span>, <span class="hljs-keyword">int</span>](ints, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(v <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
        k, ok := next()
        <span class="hljs-keyword">if</span> !ok {
            stop()
            <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
        }
        <span class="hljs-keyword">return</span> k
    })
</code></pre>
<p>Now I can get the <code>index</code> of each item in <code>ints</code> as a <code>key</code> with <code>iter.Seq2</code> and the indexes are generated as they are needed and the <code>stop()</code> discards the key generator sequence when the wrapped sequence is done. No intermediate slices or array buffers are generated during this conversion.</p>
<h2 id="heading-iterpull">iter.Pull</h2>
<p><code>iter.Pull</code> is the inverse iterator paradigm of <code>iter.Seq</code>. <code>iter.Seq</code> is called a <code>push</code> iterator. It pushes you the next value of the sequence during the iteration loop.</p>
<p><code>iter.Pull</code> is obviously a pull iterator, or the opposite of push. You have to ask for the <code>next()</code> value when you want it and you have to test for the end of the sequence by looking at the value of <code>ok</code> and ending the iteration when <code>ok</code> is <code>false</code>.</p>
<p>In the above <code>key generator sequence</code> you could not do an infinite series of data without resorting to making the code much more complex with goroutines and channels to manage the key generator function and dispose of it when done with the data.</p>
<p><code>iter.Pull</code> makes this very easy with the <code>stop()</code> function that it provides.</p>
<p>the push iterators are going to do the job for the majority of iteration needs. The pull iterators are there to cover the times that the push iterators just will not work.</p>
]]></content:encoded></item><item><title><![CDATA[ReST vs GraphQL an invalid comparison]]></title><description><![CDATA[History
The original ReST idea, which is supposedly spelled out in the abbreviation, gets lost in the abbreviation.
It was simple, transfer a typically full representation of the state of your data in its entirety to every system that needs it to ena...]]></description><link>https://blog.vertigrated.com/rest-vs-graphql-an-invalid-comparison</link><guid isPermaLink="true">https://blog.vertigrated.com/rest-vs-graphql-an-invalid-comparison</guid><category><![CDATA[REST API]]></category><category><![CDATA[REST]]></category><category><![CDATA[restful]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[RESTful APIs]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Tue, 15 Oct 2024 15:42:46 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-history">History</h3>
<p>The original ReST idea, which is supposedly spelled out in the abbreviation, gets lost in the abbreviation.</p>
<p>It was simple, transfer a typically full representation of the state of your data in its entirety to every system that needs it to enable loose coupling and stateless distributed processing.</p>
<p>The idea behind ReST was perverted for the same reason that <em>“Object Oriented”</em> was perverted from the original meaning that Alan Kay, the creator of the term, used it for.</p>
<p><em>“I made up the term 'object-oriented', and I can tell you I didn't have C++ in mind”  -- Alan Kay, OOPSLA '97</em>  </p>
<p>People just did not understand that it was just that simple and wanted to make it more complex, or they realized it was that simple, but it was more complex to implement so they just decided to say it meant something else. What is now known as OOPy.</p>
<h3 id="heading-inevitable-perversions">Inevitable Perversions</h3>
<p>ReST became RPC over HTTP with JSON as the line format but using more than POST for extra steps. Throw in misusing PUT/POST and embedding versioning into the identifier as hold my beer extra points.</p>
<p>GraphQL is a reaction to so many people getting ReST so wrong for so many years. It is understandable, but I think that GraphQL had good intentions but did not learn from any of the REST mistakes in communication of the idea.</p>
<p>People getting microservices and ReST wrong at the same time and making way too many calls because they got the granularity of the calls and the data modeling wrong. Domain Driven Design and Behavior Driven Development are two of the most important reasons that microservices granularity is wrong, because both of those things were flawed, misinterpreted ideas and became more consultant dogma for billing hours than ideas for flexible approaches.</p>
<p>The idea behind GraphQL is sound for some solutions, the misinterpretation and implementation of it as a general query language for public api consumption is the problem. It is basically the flip side of the ReST/Microservice problem. It is the pendulum swung too far the other direction. Naïve implementations are no better than letting every end user submit adhoc SQL to an RDBMS.</p>
<h3 id="heading-history-ignored-is-history-repeated">History Ignored is History Repeated</h3>
<p>In practice GraphQL seems to be a not invented here syndrome implementation of OData. Maybe they created it without knowing about OData?</p>
<p>OData was a reaction to address the same things that GraphQL was supposed to and does it in a fairly declarative fashion. GraphQL is the Facebook <em>“not invented here”</em>  imperative version of OData.</p>
<p>I think that a combination of OData being an “extension” specification for RESTful paradigm, and more importantly, philosophical and/or political reasons for people picking GraphQL over OData or vice versa when they evaluate a protocol for their service.</p>
<p>It is more important to know what both of them do not support or at least make supporting extremely difficult than what they are supposed to do. I find fault with both specifications for many of the same reasons, they include too much kitchen sink functionality as “MUST” type behavior, they leave too much behavior as ambiguous to the point that implementations are not compatible. </p>
<h3 id="heading-bad-idea-in-the-1990s">Bad Idea in the 1990s.</h3>
<p>We did this in the 1990s before the internet with server side “dynamic SQL” generation and ORMs. It was a bad idea then and a worse idea by the early 2000s when the Internet became ubiquitous.</p>
<p>My experience reading “in the wild” accounts of implementations and at my employer was that GraphQL was implemented by inexperienced developers as a naive way to just let the “front end” ask for what they wanted in an adhoc manner instead of providing a way to narrow down or expand the Representation of the data they were requesting as needed.</p>
<p>At my employer, this caused complete chaos for the “legacy RDBMS” teams when applications were generating ad-hoc SQL that was far from optimized, grinding the servers to a halt with a single call from a single client, and in a few cases crashing the server down to the OS level repeatedly.  </p>
<p>In a couple of these cases, I had argued against it just for this very reason, and like Cassandra, was ignored. The reason was “the UI” will restrict what is requested. Nobody told the developers writing the UI this and they put selections that contradicted each other or created what were effectively cartesian joins from recursion. When asked why this did not come up in testing, they admitted there were so many fields that could be combined in so many permutations that there was no way to test it in a person's lifetime.</p>
<h3 id="heading-incompetent-people-misusing-things">Incompetent People misusing things</h3>
<p>Incompetent people misusing things and not being able to read for comprehension is not a reflection on ReST or GraphQL as good or bad.</p>
<p>ReST and GraphQL can both be done correctly. Understanding how not to do ReST or GraphQL is probably more important, since every other way is correct, even if not the most correct.</p>
<p>GraphQL leans into the community that did ReST as RPC with extra steps with JSON and POST/PUT wrong with a single endpoint and RPC semantics. This allowed an immediate comprehension, even if it is naive and at the expense of GraphQL being misinterpreted the same way the theory behind REST was.</p>
<h3 id="heading-rearranging-deck-chairs">Rearranging Deck Chairs</h3>
<p>The initial implementation of GraphQL servers was to act as a facade over existing RESTful microservices which did nothing to alleviate the <em>“too many calls at the wrong granularity”</em> level problem, it only moved aggregation of them to the server side network. </p>
<p>It also made these implementations “reference” implementations by default, which misrepresented the correct implementation of GraphQL which was to parse the request and only query the data source for all the data that was needed at the same time not requesting the data that was not needed. Many GraphQL servers to this day just use a naive ORM to generate a query that requests all the data from all the entities and then filters out unwanted fields or entities during the serialization process. It just moves the problem to a potentially more expensive location.</p>
]]></content:encoded></item><item><title><![CDATA[Freedom via Constraints]]></title><description><![CDATA[No one programming language is prefect for every situation, but some are perfect for specific situations.
Why should you decide to use something?
This is more important than any other decision you make in a project. If you pick the incorrect technolo...]]></description><link>https://blog.vertigrated.com/freedom-via-constraints</link><guid isPermaLink="true">https://blog.vertigrated.com/freedom-via-constraints</guid><category><![CDATA[Career]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[programming languages]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Thu, 25 Apr 2024 17:46:42 GMT</pubDate><content:encoded><![CDATA[<p>No one programming language is prefect for every situation, but some are perfect for specific situations.</p>
<h2 id="heading-why-should-you-decide-to-use-something">Why should you decide to use something?</h2>
<p>This is more important than any other decision you make in a project. If you pick the incorrect technology, the rest of the project is at best going to be a slog and slop in production or at worst doomed to failure.</p>
<h3 id="heading-it-should-be-very-easy-to-choose-the-correct-technology-to-use-what-you-know">It should be very easy to choose the correct technology to use what you know.</h3>
<p>This is a trap that many people fall into. The proverbial "<em>to a hammer everything looks like a nail</em> " trap.' Just because you "<em>know</em>" something does not mean it is the correct tool for a given problem, and if you really "<em>know</em>" your tools, you know when this is true.</p>
<p>The actual problem is too many people do not really know their tools to the depth they need to honestly evaluate them, and thus themselves for using them.</p>
<h3 id="heading-how-we-got-here">How we got here.</h3>
<p>You only really "<em>know</em>" something when you know what it either can not do or is completely unsuited for a given problem.</p>
<p>JavaScript is the current perfect example of this idea and people trying to use it for everything, even things it is the absolutely wrong choice because that is all they know.</p>
<p>NodeJS is almost 100% the reason for this. Previously it was Perl and before that it was Shell Scripting, mostly Bash. Ruby tried to replace Perl but failed as Python beat it out in mindshare and rightly so.</p>
<p>I leave off Python from this list of shame because Python was designed as a support language for other languages, specifically C and C++. The community has mostly stuck to its intended design and very open about writing performance oriented code in more appropriate languages and then calling that code from Python.</p>
<p>When NodeJS first came out, I saw it for what it was. A framework already existed in Python called <a target="_blank" href="https://twisted.org/">Twisted</a>, that did every thing NodeJS did. I was unimpressed. I knew it was not going to scale horizontally, the JS runtime it used was single threaded, just like CPython, which was the only production grade Python runtime at the time.</p>
<p>Much like Python, Twisted worked great for what it did. You got exactly what was promised. The problems started when you had to stray past these capabilities. Twisted was a solution to the problem that CPython was, and still is, single threaded.</p>
<p>Twisted introduced an async facility that allowed it to appear that Python was not single threaded and provided features for you to manage this illusion fairly well. With these new features, came new complexities but if you knew you needed to use Twisted, you should be able to understand these new concepts fairly quickly.</p>
<p>When I saw the hype around NodeJS and researched it a bit I realized that NodeJS was the same solution to the same problem with the same limitations, but in JavaScript. And JavaScript was not as capable as language as Python at the time.</p>
<p>NodeJS is a more appropriate technology to use than Python/Twisted in 2024 simply because it is the VHS of single threaded language async solutions. Twisted is the Beta, first to market and at the time a much superior solution in almost every way, but NodeJS rode the JavaScript hype mindshare wave and has more documentation, more support and extensions/features because of it.</p>
<h3 id="heading-things-work-until-they-do-not-anymore">Things work until they do not anymore.</h3>
<p><em>Note: Replace Python/Twisted with JavaScript/NodeJS and Hardware/Cloud in the following and you have the same problem and almost the same outcome for 2024.</em></p>
<p>It was about 2007 and our Python/Twisted project worked really well for what it was intended to do, on the hardware we intended it to run on. Then a Sun sales representative took someone at the company golfing and to an expensive dinner and all of a sudden we were switching from relatively beefy <a target="_blank" href="https://en.wikipedia.org/wiki/List_of_Intel_Xeon_processors_(Nehalem-based)#%22Bloomfield%22_(45_nm)">Intel Xenon W5590</a> based servers that easily scaled vertically to <a target="_blank" href="https://en.wikipedia.org/wiki/UltraSPARC_T2">relatively weak Sun Niagara T2 servers</a> that were supposed to scale horizontally.</p>
<p>So when were were scheduled to go to production, we had a bunch of them available because they were not suitable for any of our existing applications. All new applications were required to be provisioned on all these idle servers. This should tell you everything you need to know about what the immediate problem was.</p>
<p>Our application was an I/O bottlenecked application. It just read some data from an RDBMS on first access and then cached that data and updated the server occasionally. It easily scaled vertically, just add more RAM and you can service more clients since most of them were idle. These Intel Xenon machines only had 4 cores and 8 thread but that was plenty, they just needed fast I/O and lots of RAM since the CPU was extremely fast for the time.</p>
<p>The Niagra servers were designed to be web servers, which in many ways were appropriate for our task. Lots of sporadic short lived connections that were I/O bound. The ones we had were about the same cost as the Intel machines were had been using, but were speced with less RAM. This and the fact that each core was approximately as powerful as a Pentium Pro 200 made them the absolutely wrong choice for our Twisted/Python application.</p>
<p>These machines were designed to scale horizontally. A single threaded application no matter how async only scales vertically. These machines were a terrible choice for this application.</p>
<p>I did what any reasonable Principal Engineer would do, I improvised.</p>
<p>The RPM already deployed a start, restart, stop script to the was modified to use a script that started one instance of the app per core on the current machine. This was an incredibly hacky way to solve this problem, but we were not given any time to devise a better solution before it had to go to production. We told ourselves, "this is fine" it will get replaced soon with some more appropriate, I had just gotten comfortable with Erlang at the time and figure, porting this simple app would be a good exercise.</p>
<p>It was, I re-wrote the application in Erlang, it preformed orders of magnitude better and only one instance was required. When we tried to get this version moved to production after testing it reality set in. Management told us we were correct "this is fine", the hacky solution was another teams problem now and we were not allowed to deploy the Erlang version until what was in production broke. It never did, it had 100% uptime for the almost 3 years that application was in service.</p>
<p>I just did not know enough Erlang to write the application eight weeks earlier or I would have just written it in Erlang to begin with. The fact that the other Principal Engineers I worked with tried to convince management that the Python version would never work and after they said that Erlang was a bad choice. They wanted to use C or Java and estimated a 6 - 9 month design and architecture timeline and about as much development and testing. I wrote 2 versions, in series, while running and overseeing three other projects in a span of about six weeks, eight if you include two weeks of learning Erlang.</p>
<h2 id="heading-constraints-are-your-friend">Constraints are your friend</h2>
<p>What it will not do are constraints that actually free you up to come up with better solutions most of the time. Novel solutions, not "clever" ones, that you come up with from working around arbitrarily imposed constraints or limitations forces you to approach problems from directions you would normally not consider.</p>
<p>This is how technology gets used for things they were not designed for, hopefully in a good way. It also forces you to re-think your ideas about what you "know" about solutions to similar problems with slightly different constraints in the future.</p>
]]></content:encoded></item><item><title><![CDATA[Java is the new COBOL]]></title><description><![CDATA[No one programming language is prefect for every situation, but some are perfect for specific situations. How do you choose what to know or learn in 2024.
What programming languages you need to know.
You must know Java!
Note that I did not say you mu...]]></description><link>https://blog.vertigrated.com/java-is-the-new-cobol</link><guid isPermaLink="true">https://blog.vertigrated.com/java-is-the-new-cobol</guid><category><![CDATA[Java]]></category><category><![CDATA[Career]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Wed, 24 Apr 2024 15:08:51 GMT</pubDate><content:encoded><![CDATA[<p>No one programming language is prefect for every situation, but some are perfect for specific situations. How do you choose what to know or learn in 2024.</p>
<h2 id="heading-what-programming-languages-you-need-to-know">What programming languages you need to know.</h2>
<h3 id="heading-you-musthttpsdatatrackerietforgdochtmlrfc2119section-1-know-java">You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> <strong>know</strong> Java!</h3>
<p>Note that I did not say you <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> <strong><em>write</em></strong> Java, but you <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> <strong>know</strong> it. Just like in the early 2000's, I knew CORBA but I did not write CORBA, it got me plenty of work, porting CORBA "Orbs" from C++ to Java. I also knew C++, but at the time I only wrote C++ for game mods/side projects.</p>
<p>The world runs on Java today, like it or not, trillions of lines of code have been written in Java since 1.2 was released in 2000. You will have to deal with a Java system at some point, and you <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-5"><strong>may</strong></a> need to integrate with an existing Java system so you will have to read through JavaDoc to know how it works. You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-5"><strong>may</strong></a> need to port Java source code to a new language. Just like those that came before you had to know COBOL to port a COBOL application to Java, this is the way.</p>
<p>You also <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> know Java to write Groovy, Scala or Kotlin because it all ends up in the JVM so you <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> know how the JVM works and what it does not do.</p>
<p>I have not written any significant Java code in about 7 years. I wrote a good bit of Groovy code about 6 years ago, but the most significant amount of code I have written in the last 6 years has been Go, JavaScript and Rust.</p>
<h3 id="heading-you-musthttpsdatatrackerietforgdochtmlrfc2119section-1-know-javascript">You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1">must</a> know JavaScript!</h3>
<p>The web runs in a browser and the browser runs JavaScript.</p>
<p>You also <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> know JavaScript if you want to write programs for the browser in languages other than JavaScript for the same reasons you must know Java and I had to know COBOL. You still <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1">must</a> interact with it at some non-trivial level to not use it.</p>
<p>If you want to use Web Assembly instead of JavaScript you still need JavaScript to load the Web Assembly to begin with.</p>
<p>You use another language that cross compiles to JavaScript, you still need to know JavaScript to debug why the cross compiled code is breaking and map it back to whatever you cross compiled from.</p>
<p>I really like using JavaScript for actual scripting the last few years. NodeJS and its other runtime competitors as well as having mature dependency management tools.</p>
<p><a target="_blank" href="https://github.com/google/zx">ZX</a> is the obvious conclusion for every developer that already has to deal with JavaScript in their toolchain.</p>
<p>Even if you are not doing JavaScript development directly, some tooling or support tool you rely on is going to be written in JavaScript, which means you are going to have to have NodeJS install and all the tooling around it, so <a target="_blank" href="https://github.com/google/zx">ZX</a> is just one more package to install, is managed and updated by your package manager. Why bother with switching to Python when you <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> already deal with JavaScript.</p>
<h3 id="heading-you-shouldhttpsdatatrackerietforgdochtmlrfc2119section-3-know-go">You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-3">should</a> know Go!</h3>
<p>You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> know a relevant general purpose programming language.</p>
<p>Go is an obvious choice for a modern, relevant general purpose programming language in 2024. There are plenty of articles about why Go an S tier general purpose language so I do not need to waste time or space writing about that here.</p>
<h3 id="heading-you-shouldhttpsdatatrackerietforgdochtmlrfc2119section-3-know-rust">You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-3">should</a> know Rust!</h3>
<p>If you <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> know a relevant programming language to do high performance, resource constrained or system level programming. You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-3"><strong>should</strong></a> know Rust.</p>
<p>Rust is an obvious choice for a modern, relevant high performance, low level, purpose programming language in 2024. There are plenty of articles about why Rust an S tier modern language for all the constraints listed above, but also as a general purpose programming language, but you still <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> know C++.</p>
<p>C++ has not lost its relevance and will not for a significant number of years for the same reasons that Java will not. The trillions of lines of code and the momentum that goes along with that kind of mindshare. C++ continues to be developed and adopt more modern approaches to its language and runtime libraries, this is what keeps it relevant. It is not going anywhere anytime soon.</p>
<p>Rust would not be my first choice for DOM manipulation in the Browser, but for network libraries for accessing a server endpoint, a Rust based Web Assembly client would not be the worst choice. It would be more work than JavaScript, but if it needed to do some advanced high performance operations it is the S tier language for Web Assembly.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>I ignored platform specific languages because if you are writing for iOS or Android you know what your options are already. The same is true if you are targeting Windows only applications, you have that constraint and your options are limited or obvious for them.</p>
<p>Regardless of your platform, to be a well rounded programmer, you <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> know a good general purpose language, Go is my platform agnostic recommendation. You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-1"><strong>must</strong></a> know JavaScript if you want to do anything browser related or work with any JavaScript based tools in your toolchain. You <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2119#section-3"><strong>should</strong></a> know at least one low level systems language like, Rust is my platform agnostic recommendation. C or C++ will be the obvious winner in some cases which will be obvious.</p>
]]></content:encoded></item><item><title><![CDATA[Sane approach to Go project directory structure!]]></title><description><![CDATA[Loose Coupling/High Cohesion
The first is easy the second hard that is why everyone ignores it.

Group your packages by types and the functions that manipulate those types. More functional organization means looser coupling and high cohesion.

This i...]]></description><link>https://blog.vertigrated.com/sane-approach-to-go-project-directory-structure</link><guid isPermaLink="true">https://blog.vertigrated.com/sane-approach-to-go-project-directory-structure</guid><category><![CDATA[Go Language]]></category><category><![CDATA[projects]]></category><category><![CDATA[Google Cloud Platform]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Wed, 17 Apr 2024 21:33:00 GMT</pubDate><content:encoded><![CDATA[<h3 id="heading-loose-couplinghigh-cohesion">Loose Coupling/High Cohesion</h3>
<p>The first is easy the second hard that is why everyone ignores it.</p>
<blockquote>
<p>Group your packages by types and the functions that manipulate those types. More functional organization means looser coupling and high cohesion.</p>
</blockquote>
<p>This is the project directory layout I have adopted for all my projects. It is intuitive, semantically rich and most importantly it is loosely coupled and highly coherent.</p>
<h3 id="heading-context">Context</h3>
<p>This is a project that is deployed to Google Cloud Platform.</p>
<p>Specifically Google App Engine. But this project layout works equally well for command line only tools and stand along desktop apps so far.</p>
<p>Each package is a specific domain or feature. Do not get caught up on the the term "domain", there is some "domain driven design" ideas but none of the dogma associated with it.</p>
<p>Specifically having a <code>models</code> package that has all the models in it. I started trying to do that and it was just a tightly coupled incoherent mess to navigate around, even in the awesome Goland IDE from Jetbrains.</p>
<p>So I inverted that idea and put all the code supporting a specific type(s) together like you would do in most functional languages and this worked very well.</p>
<p>The filenames are semantically descriptive and should be self explanatory to anyone that checks out the code base for the first time. They should be able to intuitively find what they are interested in very quickly without a lot of searching.</p>
<p>For a particular domain/feature/functionality package the files that are most common are going to be. They are detailed after the example tree.</p>
<pre><code class="lang-plaintext">
├── account
│   ├── functions.go
│   ├── handlers.go
│   ├── tasks.go
│   └── types.go
├── cuid2
│   └── cuid2.go
├── gcp
│   ├── auth
│   │   ├── functions.go
│   │   ├── handlers.go
│   │   ├── middleware.go
│   │   ├── tasks.go
│   │   └── types.go
│   └── secrets
│   ├── functions.go
│   └── types.go
├── go.mod
├── go.sum
├── main.go
├── server
│   ├── functions.go
│   ├── middleware.go
│   ├── must_functions.go
│   └── types.go
├── timestamp
│   ├── functions.go
│   ├── functions_test.go
│   ├── types.go
│   └── types_test.go
└── youtube_service
 ├── errors.go
 ├── datastore.go
 ├── functions.go
 ├── handlers.go
 ├── secrets.go
 ├── service.go
 ├── tasks.go
 └── types.go
└── stripe_service
 ├── errors.go
 ├── datastore.go
 ├── functions.go
 ├── handlers.go
 ├── secrets.go
 ├── service.go
 ├── tasks.go
 └── types.go
</code></pre>
<h3 id="heading-files-that-will-be-in-most-every-package">Files that will be in most every package:</h3>
<h3 id="heading-typesgo"><code>types.go</code></h3>
<p>This file contains all the types for the package, both exported and non-exported.</p>
<p>For most packages both interfaces and structs and any struct receiver functions are all in the <code>types.go</code> file.</p>
<p>In rare cases the <code>types.go</code> file may need to be split up into an <code>interfaces.go</code> and a <code>structs.go</code> just because the number of interfaces and structs ends up becoming cumbersome. This should make you take pause of your package and see if it is overly generalized, or the types are too granular, or that you are just doing it wrong.</p>
<p>I have a well rounded background in functional and imperative programming languages and I find that I use receiver functions very sparingly in Go. If your types look like Java classes then you are doing it wrong.</p>
<p>My types in Go usually only have interfaces that make sense on the type, like <code>Stringer</code> or <code>Marshal/UnmarshalJson</code> or <code>Marshal/UnmarshalBinary</code> and <code>Marshal/UnmarshalText</code></p>
<p>Instead of putting a <code>AsTime() time.Time</code> receiver function on my custom <code>Timestamp</code> type, I would rather have it a stand along <code>func AsTime(ts Timestamp) time.Time</code> function. It makes my <code>Timestamp</code> type loosely coupled to the <code>time.Time</code> type and still maintains high cohesion/locality. It also limits interface explosion. You can also pass the function into other functions if you need a different implementation for some reason as long as the signature is <code>func(ts Timestamp) time.Time</code>.</p>
<h3 id="heading-functionsgo"><code>functions.go</code></h3>
<p>This file contains all the functions for the package, both exported and non-exported.</p>
<p>These are functions that are actually functions, not receiver functions, those should be in the same file as the struct they are on for high cohesion.</p>
<h3 id="heading-exceptions">Exceptions:</h3>
<p><strong><em>There are always exceptions!</em></strong></p>
<p>For the <code>cuid2</code> package there is only one type and a handful of functions, so I just put them all in a single file with the same name of the package. This indicates that everything is self contained in this single file. If that file should grow to be more complicated or unwieldy from size it would then be refactored into <code>types.go</code> and <code>functions.go</code> at the minimum.</p>
<p>This is in service to the high cohesion principle. If everything can easily be in a single file, then it should be.</p>
<p>You will also notice there are no packages or files with names like <code>util</code> or <code>common.go</code> or <code>helper</code>, those names might as well just be <code>djjsdfiyhfye</code>, they are actually worse; they do not convey anymore more useful information than line noise, but since they are words you infer what they mean without actually knowing what the intent was. They are misinformation at best, where as random characters would at least tell you immediately that those files were suspect and obfuscations at best.</p>
<h3 id="heading-web-applications-apis">Web Applications / APIs</h3>
<h3 id="heading-app"><code>app</code></h3>
<p>The <code>app</code> package is a horizontal cross cutting package that should not import any of the application specific packages but be imported by many of them to access high level application specific functionality. This would commonly be named <code>utils</code> or <code>common</code> or some other lazy unimaginative and non-descriptive name.</p>
<h3 id="heading-server"><code>server</code></h3>
<p>When I am working on web service and it gets even the least bit complex, I introduce a <code>server</code> package and put the <code>server</code> implementation in that package. I usually use <code>gin</code> so this is where the <code>gin</code> instance(s) get initialized and configured instead of in <code>main.go</code>.</p>
<h3 id="heading-mustfunctionsgo"><code>must_functions.go</code></h3>
<p>This file is functions that <em>must</em> not fail, and will stop the server if they do. In most cases these are functions that are either critical to the server and errors are unrecoverable, or they are wrappers around things in <code>functions.go</code> that are processing known <em>good</em> data that if an error does occur it is because of major data corruption and should stop the server.</p>
<p>Things like <code>must_parse_time(s string) time.Time</code> where you know the format of the string is valid because it came from a know source or has been previously validated in the code path.</p>
<p>I put functions that do not return errors and that <code>panic</code> or <code>os.exit</code> in this file. This makes it extremely clear that these functions will stop your application if they encounter errors of any kind.</p>
<h3 id="heading-handlersgo"><code>handlers.go</code></h3>
<p>This is where exported API handler functions would be found, and any non-exported support functions that might be specific to these handlers.</p>
<h3 id="heading-middlewarego">middleware.go</h3>
<p>This is handlers that are middleware that support the package they are in. Server wide middleware would be in the <code>server</code> package. <code>authentication</code> middleware would be in the <code>authentication</code> package. You get the idea, loosely coupled and highly coherent.</p>
<h3 id="heading-servicego"><code>???_service.go</code></h3>
<p>This particular project access the YouTube Data API V3 so there is a <code>youtube</code> package. The <code>service.go</code> file contains all the functions to actually make the calls to the youtube API. These could be stand alone functions or a struct with receiver functions that implemented the calls so they could share construction and pooling of an API specific client object and its creation.</p>
<p>It also uses <code>stripe</code> so there is a <code>stripe_service</code> package, naming them <code>XXX_service.go</code> tells you what they do an removes import collisions inside the package when the service package name would conflict without the <code>_service</code> suffix. There are other naming conventions you could use, just be consistent.</p>
<h3 id="heading-secretsgo"><code>secrets.go</code></h3>
<p>This file contains package specific functions and types to access the Google Cloud Secrets Manager API calls that are in <code>server/secrets.go</code>. That file contains general abstractions over the secret manager client and calls, like creating a secret, adding a version and enabling it and disabling/deleted previous versions all in one transaction.</p>
<h3 id="heading-datastorego"><code>datastore.go</code></h3>
<p>This project stores data in the Google Cloud Datastore. This could be called <code>repository.go</code>, and it was, I decided that was to generalized and did not convey enough semantics. <code>datastore.go</code> tells you it is a <code>datastore</code> implementation in the context that this is a Google Cloud Platform application.</p>
<p>If I was going to support multiple storage implementations I would put that interface into <code>repository.go</code> and the specific stores in <code>datastore.go</code>, <code>postgres.go</code>, <code>redis.go</code>, etc.</p>
<h3 id="heading-tasksgo"><code>tasks.go</code></h3>
<p>This file contains the functions to create Google Cloud Tasks submissions. If they take specific structs that are only used in the task functions to create the tasks, then I make then non-exported and put them in the <code>tasks.go</code> file, if they are used elsewhere I put them in <code>types.go</code>. Cohesion over rote consistency.</p>
<h3 id="heading-errorsgo"><code>errors.go</code></h3>
<p>I am experimenting with custom error structs in the on package in this project, that is what this file contains, the error types and the functions to create new instances.</p>
<p>I have toyed with making this a sub-package, but since Go does not support sub-package namespaces (pet peeve of mine) and flatter packages are idiomatic Go, I am doing it this way for right now. This is an experiment, it may change depending on how successful it is.</p>
<h3 id="heading-gcpauth-gcpsecrets"><code>gcp/auth gcp/secrets</code></h3>
<p>I am still debating these nested packages. This is a Google Cloud Project application and these packages contain Google Cloud Project specific authentication and secrets manager code.</p>
<p>I initially put all the code just under <code>gcp</code> package, but mixing the authentication functions and types with the secrets manager functions and types go messy very quickly. Tightly coupling the disparate features to each other in location if nothing else. And weakening cohesion at the same time, because it was hard to see what was related and unrelated with both features mixed in the same <code>types.go</code> and <code>functions.go</code> files.</p>
<p>I am satisfied with this right now, but still not completely. Putting an <code>auth</code> and <code>secret</code> package in the root of the project would lose the information that the outer <code>gcp</code> package conveys semantically, so it stays until I have a better solution. There may not be one.</p>
<h2 id="heading-there-is-no-one-correct-project-layout">There is no one correct project layout:</h2>
<p>There are ones that are more correct and this is the most semantically rich, intuitive and idiomatic one I have seen anyone come up with so far.</p>
<ul>
<li><p>It is adaptable but consistent and predictable.</p>
</li>
<li><p>It is simple but scales out to more complex cases when needed.</p>
</li>
<li><p>It is minimal without being terse and expressive without being verbose.</p>
</li>
<li><p>It is opinionated without being dogmatic.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Considered Harmful Test Driven Development]]></title><description><![CDATA[TL;DR

Dogmatic Driven Adherence to things is bad. Especially things that are like this idea. Testing is good, more testing is more better, testing everything is all the best. Not! TDD is the ultimate "created by consultants" to sell certificates, co...]]></description><link>https://blog.vertigrated.com/considered-harmful-test-driven-development</link><guid isPermaLink="true">https://blog.vertigrated.com/considered-harmful-test-driven-development</guid><category><![CDATA[TDD (Test-driven development)]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Wed, 17 Apr 2024 21:12:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1714170301519/35fe6612-7ad9-4421-87f9-c600e252556d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-tldr">TL;DR</h3>
<blockquote>
<p>Dogmatic Driven Adherence to things is bad. Especially things that are like this idea. Testing is good, more testing is more better, testing everything is all the best. <strong>Not!</strong> TDD is the ultimate "created by consultants" to sell certificates, courses and to bill hours.</p>
</blockquote>
<p><strong>The stated goal is diametrically opposed to what it aspires to.</strong></p>
<blockquote>
<p>Software engineer Kent Beck, who is credited with having developed or "rediscovered"[1] the technique, stated in 2003 that TDD <strong><em>encourages simple designs and inspires confidence.</em></strong></p>
</blockquote>
<h3 id="heading-reality">Reality</h3>
<blockquote>
<p>TDD encourages writing complex speculative code that gets thrown away, never used or worse, hangs around in your code base as "<em>zombie</em>" code whose only function is to make you feel good at the end of the day about not getting anything useful actually done. Because LOC ... 100% CC ... writing code is fun, solving actual problems is work.</p>
</blockquote>
<p>For any non-trivial project, any intermediate experienced programmer can tell you writing tests before you write the code as a way to design the code is a non-starter.</p>
<p>Now, who in their right mind would promote something so proven not viable, maybe <a target="_blank" href="https://en.wikipedia.org/wiki/SUnit">someone who really likes writing testing frameworks</a> more than actual applications?</p>
<p><strong><em>Tests are code</em></strong>*, so when do you write the tests that test the tests?*</p>
<h3 id="heading-on-a-team-that-is-being-held-to-a-budget-and-a-deadline">On a team, that is being held to a budget and a deadline.</h3>
<p>Writing tests as a design tool is ridiculous in practice. Especially when in the real world, where the requirements are malleable and you are working on an "agile" team.</p>
<h3 id="heading-tdd-target-audience-beginners-looking-for-a-success-without-having-to-think">TDD target audience <code>#beginners</code> looking for a success without having to think.</h3>
<p>But, this TDD idea is not aimed at intermediate or expert programmers, it is aimed at beginners. The very audience that does not know any better and thinks this sounds like a good way for them to focus and structure their design process. When it is just a Turing tarpit of wasted time.</p>
<p><a target="_blank" href="https://youtu.be/kre-xcveGTY?t=12">"Speed is important in business, time is money ..."</a></p>
<p>They do the course or video series on TDD that they discover and it "makes so much sense", in the strawman case of a boot camp "TODO app".</p>
<p>Then when they can not get anything done, are behind schedule and over budget and all they have to show at the end of each sprint is a bunch of tests that "fail successfully", they are told, they are just not "doing it right", they need more paid courses, and need to convince their team and/or management to drink the TDD Kool-Aid.</p>
<p>They just need to evangelize to the business that having as close to 100% test coverage of an 80% working application is better than having a 100% working app with 20% test coverage.</p>
<p>As a contractor, I worked a couple projects where you could not merge any code at the end of a sprint that did not have 100% coverage, yes 100%, that meant you had to write or generate tests for every <code>toString()</code> method on every <code>class</code>, yes this was Java, it was 2005/6, the height of this madness that perpetuates to today.</p>
<p>It was the most moronic waste of time, but hey, I was just a warm butt in a a seat behind a keyboard pressing keys. As such, all the badged employees delegated all this useless test code to me; the most expensive person on the team, because the other work was more <strong>fun</strong> and more <strong>important for clout</strong>.</p>
<p>I ended up having to do redo most of their stuff anyway because I was actually hired to write all the complex concurrent and cache code that they could not get to work without dead locking or working on stale data.</p>
<h3 id="heading-here-is-what-and-how-you-need-to-test">Here is what and how you need to test</h3>
<p>As you are writing the logic for your application, you are by definition writing your testing in your code. To make sure it does what you need it to do. You write a function, write code that calls it and iterate until it does what you intend it to do. <strong><em>Using a step debugger hopefully!</em></strong></p>
<p>Once it is working, it is tested, it does not need to be tested every build after that <a class="post-section-overview" href="#when-to-write-tests">until it gets changed!</a></p>
<p>Then you move onto the next thing until you get your application working and ready for production.</p>
<h3 id="heading-here-is-when-you-need-to-write-formal-tests">Here is when you need to write formal tests</h3>
<p><strong>1. Bugs</strong></p>
<p>When your application is working, and a bug is found you write a test that exposes the bug, then you fix the bug until the test passes.</p>
<p><strong>2. Logic Changes - Addition/Deletion</strong></p>
<p>When your application logic needs to change or be added to, you write a test to show that the current behavior works. This way when you change something, you can be sure that you did not break the behavior you need to keep when you added the new behavior you needed. Assuming you testing the new code, no need to write any tests for the new code as long as it does what you intended and your existing logic that you needed to keep still works.</p>
<p><strong>3. Logic Changes - Modifying Behavior</strong></p>
<p>This one is similar to the last one, if you are changing a behavior completely, then there is no real reason to write a formal test. This is logically the equivalent of deleting the existing logic and writing new logic, which you will test as you write it by default.</p>
<p>If you are keeping some of the existing behavior and changing some, then write a test to make sure the behavior you want to keep is not affected. Then you can modify with this safety net.</p>
<h3 id="heading-once-your-tests-pass-and-you-are-ready-for-production">Once your tests pass and you are ready for production.</h3>
<p>What I do is then disable all the tests. Running tests on code that is not modified on every build is just willful ignorance at best.</p>
<h3 id="heading-tests-are-code">Tests Are Code</h3>
<p>Code needs to be maintained. Code cost money and time. Especially "non-functional" code, that is code that does make it to production. Test code is code and it has to be maintained.</p>
<h3 id="heading-cliches-exist-for-a-reason">Clichés exist for a reason</h3>
<p>The best code is code that does not need to be written, the next best code is code that you delete. Tests that you do not write are the best code, test you delete is even better. Version Control exists for a reason.</p>
<h3 id="heading-this-presses-your-buttons">This presses your buttons?</h3>
<p>Follow so you can tell me how wrong I am when I post the Considered Harmful series entries about BDD, DDD and all the other Consultant Driven Design religions.</p>
]]></content:encoded></item><item><title><![CDATA[Only two questions you need to ask to determine if someone really "knows" a thing.]]></title><description><![CDATA[Everyone claims to be an "expert" in their thing. The reality is they rarely are. They either honestly think they are, or they know they are not but adhere to the George Costanza philosophy to lies, "It is not a lie, if you believe it". Which is the ...]]></description><link>https://blog.vertigrated.com/only-two-questions-you-need-to-ask-to-determine-if-someone-really-knows-a-thing</link><guid isPermaLink="true">https://blog.vertigrated.com/only-two-questions-you-need-to-ask-to-determine-if-someone-really-knows-a-thing</guid><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Tue, 09 Apr 2024 17:38:07 GMT</pubDate><content:encoded><![CDATA[<p>Everyone claims to be an "expert" in their thing. The reality is they rarely are. They either honestly think they are, or they know they are not but adhere to the George Costanza philosophy to lies, "<a target="_blank" href="https://youtu.be/uD7n_p7zAqo?t=128">It is not a lie, if you believe it</a>". Which is the honest version of the extremely toxic "Fake it until you make it!" advice.</p>
<h2 id="heading-this-took-me-to-long-to-figure-this-out">This took me to long to figure this out</h2>
<p>After almost two decades of doing technical interviews I have been able to distill a technical interview down to just two questions. And my "technical" interviews, I mean, does someone really know the subject they claim to know and how well they actually know the subject. I can end an interview with someone that claims to be an "expert" quicker than someone that claims "intermediate/competent" or "beginner".</p>
<h2 id="heading-this-is-the-hardest-question-you-can-ever-ask-someone">This is the hardest question you can ever ask someone.</h2>
<h3 id="heading-what-do-you-like-most-about-insert-technical-skill-here">What do you like most about [insert technical skill here]?</h3>
<p>The only wrong answer to this question are non-answers. Answers that do not directly specifically answer the question with an opinion are non-answers. These are answers that do not offer an opinion because they apply to anything.</p>
<p>Here are some examples of non-answers:</p>
<ul>
<li><p>"I like everything about ..."</p>
</li>
<li><p>"I like it because it is popular/easy to find work in/etc"</p>
</li>
<li><p>"I like it because it is easy to use"</p>
</li>
</ul>
<p>These types of answers are immediately disqualifying. But just to to make sure they are not just being shy or evasive because they do not want to come across argumentative or insult something that I might not agree with I prompt them for something specific.</p>
<p>Like "Why do you think it is easy to use", "Why do you think it is popular", at least those answers give you something to follow up on and see if they are just bad at giving opinions and expressing themselves and actually have a opinion in there somewhere.</p>
<p>Granted, you can have too much of a "weak personality", just as you can have too much of a "strong personality". That is not about technical interview stuff, that is more about, person than what the person knows or does not know about something.</p>
<p>If I still get a non-answer, after some leading follow up chances I move on to the next question, which should be guaranteed to draw out an answer for everyone. And like they <a target="_blank" href="https://youtu.be/YRwK8SyVeJE">Daily Double on Jeopardy</a> gives them a chance to dig themselves out of the hole they have dug.</p>
<h2 id="heading-this-is-the-most-softball-question-you-can-ask-someone">This is the most softball question you can ask someone.</h2>
<h3 id="heading-what-do-you-like-least-about-insert-technical-skill-here">What do you like least about [insert technical skill here]?</h3>
<p>A strong answer here can rescue the interviewee from a non-answer from the first question. And give them another chance to revisit the first question in the context of this answer.</p>
<p>Now everyone has something they hate about everything, especially things they are extremely knowledgeable about, even beginners have stuff they hate. Every Java programmer hates the original <code>Date</code> class, regardless of their experience level. Same with the boilerplate verbosity. Every new Go programmer starts off hating error handling in Go. Even most intermediate and a few experts hate on it, even though they understand it and realize it is a reaction to <code>try/catch</code> and is a better solution.</p>
<p>Ask a couple about what they like/love about their partner and you will get some generic stuff or one or two specific things. Ask them what drives them bonkers and they hate about their partner and you will get an "ok you can stop at any time list". And the longer the relationship the love/like list does not change in length, but the hate list will have grown.</p>
<p>A non-answer here is pretty much "<a target="_blank" href="https://youtu.be/A_j8W-SDefU">That's it man, Game over man, game over.</a>" I am going to wrap up the interview as quickly and politely as possible.</p>
<h2 id="heading-what-the-answers-mean">What the answers mean.</h2>
<p>Here is how to score the answers. You are looking for opinions, the more experienced they are the stronger their opinion needs to be, and the better they should be able to articulate why your opinion is what it is.</p>
<p>Whether you are agree or disagree and to what extent is irrelevant at this point. On a scale of <code>1</code> to <code>10</code>, with a non-answer being a <code>0</code> and a really passionate opinion with a well thought out and reasoned argument supporting that opinion, even if you think they are absolutely wrong, should score a <code>10</code>.</p>
<p>I weight the "like/love" question higher than the "dislike/hate" question. Simply because negative feedback is always easier to solicit than positive feedback. The reason this is such a powerful and effective approach to technical interviews is it gets you to the "I know enough that I do not need to know anymore" point very quickly.</p>
<p>It gives you a platform to get some back and forth engagement with the other person and see how they think and why they think what they think. It is easier to dig into someone that you disagree with their opinion than when you agree, so even if you agree with their opinion on what they like/dislike and why, you should still take the contrary side and play the part of someone that disagrees with them.</p>
<p>This gives you detailed insight to their thought processes, but it also gives you some insight into their personality; how someone argues tells you a lot about how they will fit into the team. You want experts that can argue persuasively and effectively, you need them to help drive growth in the less experienced members of the team as well as use them to convince peers and higher ups why what they want you to do is not the way something needs to be done.</p>
<p>Even if someone is not a very senior expert personal technically, if they have opinions that means they are learning and if they can argue effectively and persuasively they are way more valuable than someone who is an expert level but is ineffective a arguing their position, or worse someone who can win an argument but lose the respect of everyone in the discussion in doing so.</p>
<h2 id="heading-if-you-do-not-believe-me">If you do not believe me</h2>
<p>The brilliant thing about this approach is, it does not matter if you are an expert in the technical subject, you can find out if the other person is just by their answers.</p>
<p>Call up a friend, tell them you want to practice some new interviewing approach, but do NOT tell them what it is. Ask, them to self assess if they are an "expert", "intermediate" or "beginner" in the subject. This is like question zero, usually resumes will tell you what the person thinks their skill level is, or it is implied by "years of experience", which is a false measure, but that is an entirely another article.</p>
<p>Then ask them these two questions I detailed above in order. The order is important, just like I presented them.</p>
<p>The "Like" question and then the "Dislike" question.</p>
<p>If they give you non-answers, that is ok, it gives you a chance to practice the follow up, redirect approach questions I mention.</p>
<p><strong>You can get to what someone actually knows or does not know with these two simple questions and some trivial follow up conversation.</strong></p>
]]></content:encoded></item><item><title><![CDATA[It is not an ITruck it is a Truck]]></title><description><![CDATA[Note: This is my original answer, if you look through the edits this is the basically the original version that is actually my opinion. The edits that change my opinion to the opposite of what I actually said is one of the main reasons I requested my...]]></description><link>https://blog.vertigrated.com/it-is-not-an-itruck-it-is-a-truck</link><guid isPermaLink="true">https://blog.vertigrated.com/it-is-not-an-itruck-it-is-a-truck</guid><category><![CDATA[OOPy]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[naming]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Sun, 25 Feb 2024 02:25:05 GMT</pubDate><content:encoded><![CDATA[<p><em>Note: This is my original answer, if you look through the edits this is the basically the original version that is actually my opinion. The edits that change my opinion to the opposite of what I actually said is one of the main reasons I requested my name to be removed from all my contributions on all the stackexchange sites when I left.</em></p>
<p>Name your <code>Interface</code> what it is. <code>Truck</code>. Not <code>ITruck</code> because it isn't an <code>ITruck</code> it is a <code>Truck</code>.</p>
<p>An <code>Interface</code> in Java is a <a target="_blank" href="http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html">Type</a>. Then you have <code>DumpTruck</code>, <code>TransferTruck</code>, <code>WreckerTruck</code>, <code>CementTruck</code>, etc that <code>implements Truck</code>.</p>
<p>When you are using the <code>Interface</code> in place of a sub-class you just cast it to <code>Truck</code>. As in <code>List&lt;Truck&gt;</code>. Putting <code>I</code> in front is just crappy hungarian style notation <a target="_blank" href="http://en.wikipedia.org/wiki/Tautology_%28rhetoric%29">tautology</a> that adds nothing but more stuff to type to your code.</p>
<p>All modern Java IDE's mark Interfaces and Implementations and what not without this silly notation. Don't call it <code>TruckClass</code> that is <a target="_blank" href="http://en.wikipedia.org/wiki/Tautology_%28rhetoric%29">tautology</a> just as bad as the <code>IInterface</code> tautology.</p>
<p>If it is an implementation it is a class. The only real exception to this rule, and there are always exceptions, could be something like <code>AbstractTruck</code>. Since only the sub-classes will ever see this and you should never cast to an <code>Abstract</code> class it does add some information that the class is abstract and to how it should be used. You could still come up with a better name than <code>AbstractTruck</code> and use <code>BaseTruck</code> or <code>DefaultTruck</code> instead since the <code>abstract</code> is in the definition. But since <code>Abstract</code> classes should never be part of any public facing interface I believe it is an acceptable exception to the rule. Making the constructors <code>protected</code> goes a long way to crossing this divide.</p>
<p>And the <code>Impl</code> suffix is just more noise as well. More tautology. Anything that isn't an interface is an implementation, even abstract classes which are partial implementations. Are you going to put that silly <code>Impl</code> suffix on every name of every <a target="_blank" href="http://java.sun.com/docs/books/tutorial/java/concepts/class.html">Class</a>?</p>
<p>The <code>Interface</code> is a contract on what the public methods and properties have to support, it is also <a target="_blank" href="http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html">Type</a> information as well. Everything that implements <code>Truck</code> is a <a target="_blank" href="http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html">Type</a> of <code>Truck</code>.</p>
<p>Look to the Java standard library itself. Do you see <code>IList</code>, <code>ArrayListImpl</code>, <code>LinkedListImpl</code>? No, you see <code>List</code> and <code>ArrayList</code>, and <code>LinkedList</code>. Here is a nice <a target="_blank" href="https://web.archive.org/web/20130331071928/http://isagoksu.com/2009/development/java/naming-the-java-implementation-classes">article</a> about this exact question. Any of these silly prefix/suffix naming conventions all violate the <a target="_blank" href="http://www.artima.com/intv/dry.html">DRY</a> principle as well.</p>
<p>Also, if you find yourself adding <code>DTO</code>, <code>JDO</code>, <code>BEAN</code> or other silly repetitive suffixes to objects then they probably belong in a <a target="_blank" href="http://java.sun.com/docs/books/tutorial/java/package/packages.html">package</a> instead of all those suffixes. Properly packaged namespaces are self documenting and reduce all the useless redundant information in these really poorly conceived proprietary naming schemes that most places don't even internally adhere to in a consistent manner.</p>
<p>If all you can come up with to make your <code>Class</code> name unique is suffixing it with <code>Impl</code>, then you need to rethink having an <code>Interface</code> at all. So when you have a situation where you have an <code>Interface</code> and a single <code>Implementation</code> that is not uniquely specialized from the <code>Interface</code> you probably don't need the <code>Interface</code> in most cases.</p>
]]></content:encoded></item><item><title><![CDATA[Go is Not Java]]></title><description><![CDATA[Forty year old Gang of Four patterns, designed to deal with the short comings of “Object Oriented” Design in C++, misunderstood and poorly implemented by Java programmers continue to drag down the world of computing in 2023.
Many of these "Patterns" ...]]></description><link>https://blog.vertigrated.com/go-is-not-java</link><guid isPermaLink="true">https://blog.vertigrated.com/go-is-not-java</guid><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Mon, 19 Feb 2024 03:19:40 GMT</pubDate><content:encoded><![CDATA[<p>Forty year old Gang of Four patterns, designed to deal with the short comings of “<em>Object Oriented”</em> Design in C++, misunderstood and poorly implemented by Java programmers continue to drag down the world of computing in 2023.</p>
<p>Many of these "Patterns" are even considered anti-patterns and poor design choices in every language (Singleton), but you insist on flexing your new found Go knowledge less than 20 hours after writing your first hello world by posting about "Patterns in Go - Singleton" and embarrassing yourself.</p>
<ol>
<li><p>Almost every one of these “patterns” are not idiomatic for Go.</p>
</li>
<li><p>They are not even Object Oriented Patterns, but people keep posting them as they are.</p>
</li>
<li><p>And even if they were, as it is very easy to discover, Go is not an Object Oriented language; <em>or is it?</em></p>
</li>
</ol>
<p><strong>What is Object Oriented then?</strong></p>
<p>The language decisions that were made when the Go syntax was created were a direct reaction to the the wasteful verbose boilerplate of C++ (and ironically inheritance of the same things in Java ).</p>
<p>Object Oriented programming is actually not even about the Objects it is about message passing.</p>
<blockquote>
<p>"I regret the word 'object'. It gets many people to focus on the lesser idea. The real issue is messaging. Messaging is the abstraction of the communication mechanism. It's what allows different parts of a system to interact without knowing anything about each other. That's the power of objects, and it's what makes them so useful."</p>
<p>— Alan Kay in an interview with Peter Seibel for Dr. Dobb's Journal in 1997.</p>
</blockquote>
<p>So why are C++ and Java called “Object Oriented”?</p>
<blockquote>
<p>I made up the term 'object-oriented', and I can tell you I didn't have C++ in mind</p>
<p>— Alan Kay, OOPSLA '97</p>
</blockquote>
<p>If C++ is not what you should think about when hearing “Object Oriented” then neither is Java. Especially since Java does not have “message passing”.</p>
<blockquote>
<p>"Java and C++ make you think that the new ideas are like the old ones. Java is the most distressing thing to hit computing since MS-DOS." — Alan Kay in an interview with Peter Seibel for Dr. Dobb's Journal in 1997.</p>
</blockquote>
<p>Guess what does? Go. Specifically <a target="_blank" href="https://go.dev/tour/concurrency/1"><em>goroutines</em></a>, and they were inspired by Erlang <a target="_blank" href="https://www.erlang.org/doc/reference_manual/processes.html"><em>processes</em></a>.</p>
<p>Does that make Go “Object Oriented” by the creator of the term. Not by itself, but it does make it considerably more “Object Oriented” than C++ or Java.</p>
<p>Way more, if you consider other statements he made on the definition later. Lets look for more evidence to support my argument.</p>
<p>So what should C++ and Java be called? Well that is enough for another article or more, but anything else would be a way better term, given what the inventor of the term says.</p>
<p>I personally think “Class Type Oriented” would be semantically more appropriate considering Alan Kay focuses on the term “class” even less than “object” and C++ and Java are all about classes and type systems first and foremost.</p>
<p><strong>So what does Alan Kay think defines an “Object Oriented” language in his own words?</strong></p>
<blockquote>
<p>OOP to me means <strong>only messaging</strong>, <strong>local retention and protection and hiding of state-process</strong>, and <strong>extreme late-binding of all things</strong>.</p>
<p>— Alan Kay from an email to Stefan Ram on 2003-07-23</p>
</blockquote>
<p><strong>How would you do that in Go?</strong></p>
<p>Make every <a target="_blank" href="https://go.dev/tour/moretypes/2">struct field</a> non-exported (starts with a lowercase letter in its name) and have nothing but exported functions that work with the hidden data. Make every function take an <code>Interface</code> and return nothing but <code>struct</code> that implements an exported <code>Interface</code> .</p>
<p><strong>To spell it out:</strong></p>
<ul>
<li><p><strong>only messaging:</strong> Export only functions and <code>Interface</code> which is just a collection of <code>function</code> signatures that are public, so you are effectively passing functions or collection of functions to functions, thus <em>messaging</em>.</p>
</li>
<li><p><strong>local retention and protection and hiding of state-process:</strong> non-exported <code>struct</code> fields meets all these criteria outside the package level, <em>package</em> == <em>local</em>.</p>
</li>
</ul>
<p><strong>So what languages are “Object Oriented” as per clarifying statements by the originator of the term?</strong></p>
<p>The one that I am most familiar with because I have written real world production applications with is Erlang. I learned it because it was created for real world scenarios that needed 9 “nines” uptime. I learned it because the thing I needed to create, it needed similar uptime. I am sure that other Functional languages will be mentioned in the comments, but it is the only one I have first hand experience with in a deployed commercial production environment.</p>
<p><strong>As a former Java main, it is embarrassing …</strong></p>
<p>Please stop pushing “Object Oriented Pattern Implementations” on Go like you are informing the ignorant and unwashed masses that have been using Go for the past 10+ years and saving them from themselves. It is embarrassing, I say that as a former Java main myself.</p>
<p>What you are pushing is not even “Object Oriented” it is a perversion of it to the point that it is not even recognizable.</p>
<p>It is especially embarrassing when your implementation does not even begin to use Go idioms and ignores go specific things that were implemented specifically to do the thing you think you are being “informative” about.</p>
<p><strong>What triggered the compulsion to post this article.</strong></p>
<p>Let us take the most beloved Gang of Four Pattern of all time. Especially to the Java faithful. The one most people have their first epiphany with when introduced to “Patterns Of Reusable Design”; probably because it is the easiest to comprehend. <strong>Singleton</strong>.</p>
<p><strong>Just to make sure my point is not misinterpreted this is not about Singleton</strong>!</p>
<p><em>My point is about the articles that are nothing more than terrible ideas in Java ported to Go syntax.</em></p>
<p><strong>For this example:</strong></p>
<p><em>Let us ignore the fact that it was a terrible anti-pattern when it was first documented, because it is by definition global state and the #1 goto Java pattern. “Singleton Considered Harmful” has been a thing for decades. See what I did there; goto, singleton …</em></p>
<p><em>Let us also ignore the fact that in the JVM you can not even implement Singleton correctly because by design the JVM can not guarantee that one and only one instance of a class is ever created. Here is a hint to the all the self professed Java experts that are about to write a comment about how I am wrong; Multiple Classloaders.</em></p>
<p>If you see someone post “Patterns in Go - Singleton” first look at the implementation they post; if you do not see <code>sync.Once()</code> anywhere in the code.</p>
<p>That is what you should call them out on, their promotion of misinformation. The hubris in posting a “teaching” article about something they barely know the basics on. That is a malicious disservice to those that know even less than they do.</p>
<p>The rest of the internet has already proven all the other points, that is why I prefaced this with “Let us ignore …” caveats.</p>
<p><em>I tried to research everything in this article for factual accuracy, but I am sure the internet will tell me what their opinion about it is. If there are any factual inaccuracies, and you want to point them out in the comments, provide the source and I will correct them. Otherwise, do not waste everyone else’s time. If it is important enough to correct, it is important enough to site sources like I did for the quotes and technical specs.</em></p>
]]></content:encoded></item><item><title><![CDATA[I understand why Go does not have a native `set` type.]]></title><description><![CDATA[When I was a Java main
I would pedantically always used the collection type that was most appropriate semantically correct for the data it was collecting. If I was storing a list that only contained unique items, I would always use a Set, usually a T...]]></description><link>https://blog.vertigrated.com/i-understand-why-go-does-not-have-a-native-set-type</link><guid isPermaLink="true">https://blog.vertigrated.com/i-understand-why-go-does-not-have-a-native-set-type</guid><category><![CDATA[Design]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Wed, 07 Feb 2024 19:18:22 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-when-i-was-a-java-main">When I was a Java main</h2>
<p>I would pedantically always used the collection type that was most appropriate semantically correct for the data it was collecting. If I was storing a list that only contained unique items, I would always use a <code>Set</code>, usually a <code>TreeSet</code> so I would get insert order iteration. Same for non-unique item collections, I would use a <code>List</code> instead. This had the advantage of documenting intention to anyone reading the code months later, usually me, so they would get that extra bit of context and information about what and why the data was being used.</p>
<h2 id="heading-when-i-became-a-go-main">When I became a Go main</h2>
<p>I chafed at not having all these distinctly semantically rich type safe collections. I chafed at not having type safe collections; I went Go main well before Generics were added.</p>
<p>I searched for the reasoning behind the omission of the <code>set</code> type as a built in. I mean if you look at the <code>Set</code> implementation in Java, it is <code>Map</code> all the way down just like the recommended way of doing it Go.</p>
<p>Except, it <em>"looks ugly"</em> to have to <em>"repeat yourself"</em> to <em>"twist a map into a set"</em> in Go. I searched for <code>Set</code> implementations, I never found one that really resonated with me and Go.</p>
<p>All of them were not very <em>"Goish"</em>. They were either copies of the Java <code>Set</code> interface, or littered with receiver methods for all the different <code>set</code> operations, which in Go should be normal functions that just take two sets and do the operation on them.</p>
<p>I will not even get into all the Java/C++ iterator implementations that are so rejected by the Go community and for good reason.</p>
<h2 id="heading-so-i-build-my-own">So I build my own</h2>
<p>I did what every self respecting, at least until they have done this, programmer does, <a target="_blank" href="https://github.com/jarrodhroberson/go-set">I wrote a <code>set</code> implementation</a> that I thought was the most idiomatic Go way of doing a <code>set</code>.</p>
<h2 id="heading-then-i-never-actually-used-it">Then, I never actually used it</h2>
<p>That is not entirely true but it is accurate. I did use it, just like I <em>"used"</em> all the ones I found on <code>github.com</code>, and I ripped them all out shortly after I put them in.</p>
<p>I mean, I used my implementation, until I ripped it out as well. I found that I did not really <em>need</em> to enforce uniqueness in a list of things, often enough to warrant having to look up how this thing worked the few times I used it.</p>
<p>I work with unique lists of things all the time, I just do not need to pedantically enforce the uniqueness at creation and modification, because I found out I really never modified them after creation.</p>
<p>I created them once and just referred to them many times. Think enums and looking them up by <code>string</code>. These cases end up being both rare enough and similar enough to in a common way to just create a "Live Template" in GoLand to generate the boilerplate for their creation on a keystroke.</p>
<p>No "AI" generation required. If I am actually needing to process some data dynamically where uniqueness needs to be guaranteed as the data is added to a container, it is going to have space and or time requirements for me to use some numerical library that does this for me anyway.</p>
<h2 id="heading-it-took-a-few-years-to-finally-come-to-this-realization">It took a few years to finally come to this realization</h2>
<p>I did not really come to this realization that quickly. It took a few years and thousands of lines of Go and dozens of applications, servers, cli, desktop, etc, for this to reach this epiphany.</p>
<h2 id="heading-i-still-want-a-proper-set-type-in-go">I still want a proper <code>set</code> type in Go.</h2>
<p>But, I do not want it as a module you import. Not for silly reasons about "too many dependencies". It is about it being a "first class citizen" as a Go built in just like <code>slice</code>, <code>map</code> and <code>channel</code>. The syntax I want is:</p>
<pre><code class="lang-go">s := <span class="hljs-built_in">make</span>(set[<span class="hljs-keyword">string</span>],<span class="hljs-number">0</span>,<span class="hljs-number">7</span>)
s = <span class="hljs-built_in">append</span>(s, \<span class="hljs-string">"Sunday\")
// you get the idea
s = append(s, \"Saturday\")</span>
</code></pre>
<p><em>I intentionally picked a</em><code>comparable</code><em>type so I can ignore that issue entirely. But,</em><code>set</code><em>without support for</em><code>struct</code><em>s that do not conform to</em><code>comparable</code><em>is pretty useless.</em></p>
<h3 id="heading-what-i-wanted-was-a-native-solution">What I wanted was a native solution</h3>
<p>I want a <code>slice</code> that has enforced uniqueness, I do not want a <code>map[string]interface{}</code>, even if I get more functionality out of the <code>map</code> by being able to associate a value (abbreviation, or whatever) with the unique day of the week name.</p>
<p>It is illogical, but I really like the semantic of a unique <code>array</code> or <code>slice</code> being just that, not "keys in a map".</p>
<h3 id="heading-pedantic-reason-i-am-autistic-i-own-it">Pedantic reason, I am Autistic, I own it.</h3>
<p>I was digging through the Go compiler source <a target="_blank" href="https://github.com/golang/go/blob/master/src/runtime/map.go"><code>map.go</code></a></p>
<p>If you look at <code>makemap</code>, <code>makeslice</code> and <code>makechan</code> and it would be fairly easy to add <code>makeset</code> and update the parser to support a native <code>set</code> type that is actually a <code>slice</code> and support <code>setsorted</code>.</p>
<p>I am not sure it is worth the effort, especially since the non-trivial <code>comparable</code> issue needs to be solved. I will probably try to add it just as an exercise to get to know the Go runtime source better. I assumed until I saw the source that <code>make()</code> was some native code or something embedded into the runtime, but it is just plain Go code.</p>
]]></content:encoded></item><item><title><![CDATA[Consider "Stop using Else" and other "Stop Doing" nonsense Harmful!]]></title><description><![CDATA[I keep seeing articles that demand the reader "Stop doing" something that is fine practice, if not good/best practices just because they saw some demo on youtube and that person was not doing that thing and it now gospel to never do it again.
Stop wi...]]></description><link>https://blog.vertigrated.com/saying-stop-using-else-and-other-nonsense</link><guid isPermaLink="true">https://blog.vertigrated.com/saying-stop-using-else-and-other-nonsense</guid><category><![CDATA[software development]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Design]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Tue, 30 Jan 2024 22:37:36 GMT</pubDate><content:encoded><![CDATA[<p><em>I keep seeing articles that demand the reader "Stop doing" something that is fine practice, if not good/best practices just because they saw some demo on youtube and that person was not doing that thing and it now gospel to never do it again.</em></p>
<h2 id="heading-stop-with-the-stop-using-else-and-other-nonsense">Stop with the "Stop using Else" and other nonsense!</h2>
<p>This is a very concrete example of advice that is at best ignorance and at worse malicious misinformation.</p>
<p>If you google <em>"stop using else"</em> you will get pages and pages of articles written mostly by people that only have passing experience in a single language, usually JavaScript, and have never had to maintain a program with total lines of code greater than 10K, espousing this nonsense as if it was a revelation of some new gospel.</p>
<p>Its not, it is an ancient screed from the <em>Cult of the Lines of Code Gospel</em> or the <em>Followers of the Optional Braces</em> disciples repeat these mantras and have no experience with what they are saying in the larger picture.</p>
<h2 id="heading-explicit-is-better-than-implicit">Explicit Is Better Than Implicit!</h2>
<p>This is from <a target="_blank" href="https://peps.python.org/pep-0020/">PEP 20 - The Zen of Python</a> but it applies to all higher level languages and is knowledge that was learned from working with previous languages that were dominated by the "Cult of the Lines of Code" acolytes, this cult still preaches such things as the <em>First 80 Columns are the only holy columns</em> fallacy in 2022 as well.</p>
<p>This statement should be self explanatory and non-controversial. Program code that is explicit is unambiguous in its intent on what its behavior is expected to be.</p>
<p>That is not to say that its behavior is correct, it is just that it is not a mystery what the desired output of any input is expected to be. Executable Code should be the definitive source of logic, and comments are not executable even if they are semantically code.</p>
<h2 id="heading-else-is-explicit-its-absence-is-intentional-obfuscation">Else is explicit, its absence is intentional obfuscation!</h2>
<p>The same cult that is espousing this nonsense now is the same cult that exposed the nonsense of leaving off <code>{}</code> from <code>if</code> statements and for the exact same reasons.</p>
<p>The most popular ones are, "they are not needed", "they increase lines of code or keypresses", "they are more to read", etc. All of them are backed by <a target="_blank" href="url">logical fallacies</a> as why they are correct.</p>
<p>Leaving off an <code>else</code> statement never adds any information, it removes information about what the code is intended to do. Anything that removes information in this case is harmful.</p>
<h2 id="heading-some-languages-are-harmed-more-than-others">Some languages are harmed more than others!</h2>
<p>Leaving off the <code>else</code> block in languages like Python are even more harmful than the languages most of these authors are using to justify their ideology. <em>Go</em> and <em>JavaScript</em> I am looking at you.</p>
<p>The lack of block characters, or leaving off block characters (which is worse), makes these types of logic bombs even harder to reason about when they explode and you can not <em>see</em> where the issue is just looking at the code. Especially, when they cause <em>intermittent</em> bugs because the bad logic only triggers occasionally based on some state machine that is not defined and impossible to reason about when the application is running much when you are looking at the source.</p>
<h2 id="heading-garbage-ingarbage-out">Garbage In/Garbage Out</h2>
<p>This <em>stop using ???</em> advice is primarily predicated on bad advice <a target="_blank" href="https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect">that the reader does not comprehend as bad advice because of lack of comprehension from lack of experience</a>.</p>
<p>These same people will mindlessly espouse concepts like DRY and SOLID, avoid side-effects and completely ignore that this advice introduces implicit logic solely based on <strong>side effects</strong>.</p>
<p>The <em>reasoning</em> in this case is basically some form of <em>"</em><code>else</code> is just fluff and adds nothing useful" and then follows with <em>"you should code the</em><code>if</code> clause and <code>return</code> inside it and then do whatever the <code>else</code> is without the <code>else</code> statement and <code>return</code> there". There is a <a target="_blank" href="https://youtu.be/2sRS1dwCotw">Luke Skywalker quote from a terrible movie</a> that applies to this but I will not subject you to here.</p>
<p>This is terrible practice and it immediately introduces an impossible to detect bug into the logic of the code. Maybe not one that causes incorrect output immediately, but one that can the very first time someone adds any code outside that initial <code>if</code> block.</p>
<h2 id="heading-all-logic-is-special-case">All logic is special case!</h2>
<p>The misinformation is that the <code>if</code> statement is a <em>special</em> case in some way and that the <code>else</code> is the <em>default/non-special</em> case and does not need <em>special</em> treatment or demarcation.</p>
<p>The fact that you can transpose this <em>specialness</em> just by changing the initial <code>if</code> to <code>if not</code> tells you this is a flawed reasoning.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> somethingSpecial:
    doSomethingElseNotSpecial()
doSomethingSpecial()
</code></pre>
<p><sub>Note that there is something even more fundamentally wrong with one of these pseudo-code logic above other than the missing </sub> <code>else</code> <sub> but that is another religious argument where the zealots are wrong as well.</sub></p>
<h2 id="heading-not-just-one-billion-dollar-mistake">Not Just One Billion Dollar Mistake!</h2>
<p><code>null</code> has been called a <a target="_blank" href="https://youtu.be/ybrQvs4x0Ps">Billion Dollar Mistake by its creator</a>. It is arguable that he was off by at least an order of magnitude initially, multiple orders by 2022 standards.</p>
<p>It was just one of many terrible ideas that language creators implement because most of them were not trained in formal logic or even trained in writing computer languages or they are trying to design for <em>flexibility</em> in the future.</p>
<h2 id="heading-necessity-is-the-mother">Necessity is the Mother</h2>
<p>Many popular programming languages were created out of some need as a tool as a means to a very specific end, until <code>C</code>. <code>C</code> was created to be a <em>general purpose</em> language, and as such includes a kitchen sink of bad ideas that are only obvious in hind sight, sometimes even with 50 years of hindsight they are still obvious to some people.</p>
<p>One of the most subtle bugs in <code>C</code> is the one line <code>if</code> statement, that leaves off the <code>{}</code>. If someone comes along and just adds another line of code below the initial line in the <code>if</code> statement, what were their intentions?</p>
<p>Usually their intention was to add that line to the <code>if</code> statement, but that is not what happens. It is just executed regardless, which introduces can be an extremely subtle bug that can decimate data in an very quiet way that may not become apparent for hours, days, weeks or even months later.</p>
<p>Leaving off the <code>else</code> introduces the same <strong>class</strong> of bug, if not always the same level of subtly.</p>
<p>Languages like Go that are planned and designed for a reason just as a reaction to some problem leave a lot of these organic mistakes behind.</p>
<p>Unfortunately Go has as many opinion based mistakes baked into them to replace the mistakes they avoided. Which personally I think is worse, because these mistakes are based on intention instead of accident. They become dogma immediately, no matter how bad they reveal themselves to be.</p>
<p>This dogma becomes a defining aspect of the language that drives away adoption because it is expected to be adopted by everyone; regardless of how bad an idea it actually ends up being, instead of cautionary tale features that are accepted as being avoided.</p>
<p><em><sub>NOTE: I do not hate Go, I have moved to using Go over all the previous languages I usually reached for before I learned Go. Go is a great compromise that can completely replace Java and Python at the same time. Instant compiles of even huge programs means it can be used for rapid development scripting type tasks, cross platform single executables with robust libraries and frameworks ticks the Java boxes. It is great, but not perfect.</sub></em></p>
<h2 id="heading-new-ideas-are-not-always-new-or-correct">New ideas are not always new or correct!</h2>
<p>One of the most offending languages right now to this is Go. There is a preponderance of effort into pushing the idea that <code>else</code> is not needed, and if it is your code is not <code>structured</code> enough or some other hand wavy non-sense that is your failing and not the failing that it is a terrible practice.</p>
<p>Another, <em>idiom</em> of Go is the normalization of negative Boolean checks in <code>if</code> statements.</p>
<p>This is the idiom in Go, and it is terrible for many reasons.</p>
<p>First off, the general and correct consensus is that the initial <code>if</code> statement should be not be testing for a negative because it forces more processing on the organic computer that is parsing and interpreting the intent of the logic.</p>
<p>Who in their right mind would let the following type of code construct into an application that was used for anything non-trivial?</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> x != <span class="hljs-literal">true</span> &amp;&amp; y != <span class="hljs-literal">false</span> &amp;&amp; z == <span class="hljs-literal">true</span> {
    <span class="hljs-comment">// do something for some reason</span>
}
</code></pre>
<p>Yet, I have seen thousands of lines of such checks in 20+ year old Java code that the original author insisted was <em>"best practices"</em> 20+ years later. Lucky for me that IntelliJ idea was able to automatically convert them all to something easier to reason about using structural search and replace.</p>
<p>We still had to reason about the multiple checks and normalize that, but it did save time and make writing tests for this code possible.</p>
<p>The Go idiom is not exactly the same, but is in the same class of obfuscated logic for the sake of brevity, even if you consider it less harmful than the Java example. Less harmful is not harmless.</p>
<h2 id="heading-religious-arguments-codified-as-idioms-are-dogma">Religious Arguments Codified As Idioms are Dogma</h2>
<p>Go codifies the "multiple return" religious argument dogma by making it an idiom. It does not solve the argument, it justifies it as "everyone says so", which is just a <a target="_blank" href="https://philosophy.lander.edu/logic/popular.html#apf_captandum">logical fallacy</a>.</p>
<p>It does this, by making this the idiom in all the official Go source code.</p>
<p>This also has the side effect of justifying that <code>else</code> is never needed and thus it is idiomatic as well to always leave it out.</p>
<p>Leading many people to twist otherwise clear logic in obfuscated knots and write spaghetti code to be able to leave it out.</p>
<h2 id="heading-this-page-left-intentionally-blank">This Page Left Intentionally Blank</h2>
<p>Documents that had important information that needed to be unambiguous in their facts and intention always have blank pages that say <a target="_blank" href="https://en.wikipedia.org/wiki/Intentionally_blank_page">THIS PAGE LEFT INTENTIONALLY BLANK</a>, on them in huge block letters. That way no one would wonder if that blank page was supposed to be blank and missing information? Was it a printing error? Is there missing information that could be a cause a serious error? No one would argue these semantic place holders were redundant or not important in the explicit context that they provide.</p>
<p>The <code>else</code> in the <code>if/else</code> symmetry serves this same semantic function. It says explicitly, <strong>THIS AND ONLY THIS</strong> is what is supposed to happen if the other thing is not true and leave no ambiguity.</p>
<p>It says, if you want something to happen if that special case is not true put it here. If you want something to happen regardless of that space put it outside here.</p>
<pre><code class="lang-go"><span class="hljs-comment">// something that might return an error</span>
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">return</span> err, <span class="hljs-literal">nil</span>
}

<span class="hljs-comment">// something ELSE or something unrelated to the previous if we </span>
<span class="hljs-comment">// have to look and parse to know that might return an error</span>
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">return</span> err, <span class="hljs-literal">nil</span>
}

<span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, somethingNotNil
</code></pre>
<p>is what most would consider idiomatic the following is not wrong but is preferable because of it is explicit and unambiguous to the expected behavior</p>
<pre><code class="lang-go"><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    <span class="hljs-keyword">return</span> err, <span class="hljs-literal">nil</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>, somethingNotNil
}
</code></pre>
<p>the needlessly laconic idiom version saves an entire 7 characters, but is introduces the possibility of endless subtle bugs as unattended side effects, incorrect logic and just bad output.</p>
<p>Thankfully, even this idiomatic structure is being challenge by the new/late comers to Go, but in an early enough stage and by enough seasoned developers that it can hopefully be corrected as harmful dogma from early zealots.</p>
<p>The fact that <code>if err != nil</code> is well considered to be just copy paste boilerplate with dozens of macros, libraries, frameworks, and code generator solutions to this should tell you it was never a good idea.</p>
<h3 id="heading-ignore-advice-that-makes-the-world-worse">Ignore advice that makes the world worse!</h3>
<p>It is very simple:</p>
<p>If the advice in any way makes your code less explicit, introduces any kind of possibly ambiguousness or obfuscation to the intent of the logic expressed as code, then ignore that advice.</p>
<p>This should tell you that all these <em>stop using else</em> articles just as bad for the industry as the <a target="_blank" href="https://groups.google.com/g/comp.lang.c/c/tnr2bEcBZbw/m/JlIMVw82ok4J">same arguments espoused on Usenet in the 1980s promoting omitting <em>optional</em> braces in C</a> for the same incorrect reasons.</p>
]]></content:encoded></item><item><title><![CDATA[What to do when someone writes a technical article and says you are doing it wrong.]]></title><description><![CDATA[before posting an angry comment full of logical fallacies about how they are wrong, stop and seriously consider that they are might be right and if what you were going to post is just going to expose your lack of competence and/or self-awareness.
The...]]></description><link>https://blog.vertigrated.com/what-to-do-when-someone-writes-a-technical-article-and-says-you-are-doing-it-wrong</link><guid isPermaLink="true">https://blog.vertigrated.com/what-to-do-when-someone-writes-a-technical-article-and-says-you-are-doing-it-wrong</guid><category><![CDATA[social media]]></category><category><![CDATA[Self Improvement ]]></category><category><![CDATA[software development]]></category><category><![CDATA[Technical writing ]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Jarrod Roberson]]></dc:creator><pubDate>Tue, 30 Jan 2024 21:41:18 GMT</pubDate><content:encoded><![CDATA[<p><em>before posting an angry comment full of logical fallacies about how they are wrong, stop and seriously consider that they are might be right and if what you were going to post is just going to expose your lack of competence and/or self-awareness.</em></p>
<h3 id="heading-the-truth-hurts">The truth hurts!</h3>
<p>The amount of insult you are feeling is inversely proportionally to how much you know that you they are probably correct, at least more correct than wrong. You might not even know why they are correct, but you know it hit a nerve and you are angry.</p>
<h3 id="heading-experience-taught-me-this">Experience taught me this!</h3>
<p>I originally went to study art after high school, commercial art to be specific. <a target="_blank" href="https://en.wikipedia.org/wiki/LaserWriter#:~:text=The%20LaserWriter%20is%20a%20laser,available%20to%20the%20mass%20market.">Apple introduced the laser writer the end of my freshman year</a>, and I saw the writing on the wall. Let the <a target="_blank" href="https://en.wikipedia.org/wiki/Ageism">#ageism</a> comments begin.</p>
<p>The hardest part of commercial art, <a target="_blank" href="https://en.wikipedia.org/wiki/Rubylith"><em>mechanicals</em></a>, had just been completely commoditized and I added a video production/animation major as insurance. Which was a good idea, I was right about commercial art salaries cratering, video took another couple decades.</p>
<h3 id="heading-but-how-did-i-end-up-writing-software-professionally-for-almost-40-years">But, how did I end up writing software professionally for almost 40 years.</h3>
<p>I wrote my own 3D animation modeling and rendering and machine control automation software as a means to an ends. Long story short, I realized I like working with machines more than people.</p>
<h3 id="heading-why-is-all-this-relevant">Why is all this relevant?</h3>
<p>Well the first thing they teach you in art school is how to give and take criticism. Both constructive and non-constructive. It is crucial to your growth as an artist and growing your career.</p>
<p>Everyone has an opinion about art, and you have to learn to consider all of them. So you can separate the constructive from the non-constructive.</p>
<p>Even the ones that insult you the most, especially those. Understanding why they insult you the most is very important to your growth as a person if nothing else.</p>
<p>More importantly you have to learn how to give constructive criticism.</p>
<p>Anyone can yell <em>"you are wrong"</em> to the void. Those with experience can tell someone they need to change and back it up with logic and reason without resorting to <a target="_blank" href="https://owl.purdue.edu/owl/general_writing/academic_writing/logic_in_argumentative_writing/fallacies.html#:~:text=Begging%20the%20Claim%3A%20The%20conclusion,be%20banned%20would%20be%20logical.">Begging the Claim</a> and other logical fallacies or ad hominem attacks.</p>
<h3 id="heading-there-are-four-types-of-criticism">There are four types of criticism.</h3>
<p>There are four types of criticism and you need to learn how to tell the difference between them. Because, only two of the types are worth your time considering.</p>
<p>There is positive and negative criticism, and there is constructive and non-constructive. Thus you can have four distinct types.</p>
<h3 id="heading-which-types-do-you-consider-and-which-do-you-ignore">Which types do you consider and which do you ignore?</h3>
<p>Constructive criticism should always be considered, both positive and negative. Non-constructive criticism, which is the majority of what you will get from random anonymous internet is easy to disregard, but can be hard to ignore. Especially about things that are <a target="_blank" href="https://www.google.com/search?q=empirical&amp;rlz=1C1CHBF_enUS1005US1005&amp;sourceid=chrome&amp;ie=UTF-8">empirical</a> and not just opinion based.</p>
<h3 id="heading-how-do-you-tell-the-difference">How do you tell the difference.</h3>
<p>Constructive criticism does not just tell you that it agrees or disagrees with you, but why and gives an alternatives to whatever is being criticized in a measured informed manner that sticks to the topic and is not littered with logical fallacies.</p>
<h3 id="heading-this-is-the-big-differentiating-factor">This is the big differentiating factor.</h3>
<p>If someone agrees or disagrees with you and their reasoning is based on one or more logical fallacies then you should realize very quickly it is a waste of your time and ignore it and move on.</p>
<p>But with publishing on the internet, it gets really hard to just ignore misinformation, especially misinformation that can make your peers make mistakes and by extension make your life harder and your chosen career worse.</p>
<p>I think we all have a responsibility <a target="_blank" href="https://xkcd.com/386/">to correct or at least call out misinformation</a> that <em>makes the internet worse</em>.</p>
<h3 id="heading-critical-thinking-debate-and-formal-logic-is-no-longer-taught-to-the-general-public">Critical thinking, Debate, and formal Logic is no longer taught to the general public.</h3>
<p>Public schools used to have debate clubs. Teachers used to teach how to learn, how to think about things objectively and logically and identify logical fallacies. Not only in others debates or reasoning but in your own.</p>
<p>I think that is why the <a target="_blank" href="https://www.verywellmind.com/an-overview-of-the-dunning-kruger-effect-4160740">Dunning/Kruger Effect</a> seems to be on the rise.</p>
<p>It was always there, but putting a name on it and how to identify it formally makes you more cognizant of it.</p>
<p>Now they just teach how to take and pass tests. DotCom bubble certification farms proved that is worse than worthless to our industry.</p>
<h3 id="heading-i-did-my-own-research">I did my own research!</h3>
<p>The massive audience and scope of the internet has made a lot of the problems with people that do not have these skills much worse.</p>
<p>The <a target="_blank" href="https://www.google.com/search?q=populist+idea&amp;rlz=1C1CHBF_enUS1005US1005&amp;sourceid=chrome&amp;ie=UTF-8">populist idea</a> that everyone has an equal weight opinions about subjects that require formal study, are extremely complex, and nuanced or require years if not decades of experience in them to understand, much less master is a huge problem.</p>
<p>Doing "your own research" usually means, "I read a few things on the internet that confirm what I am already thinking", confirmation bias is extremely seductive.</p>
<h3 id="heading-so-this-is-a-criticism-of-criticism-which-kind-is-it">So, this is a criticism of criticism, which kind is it?</h3>
<p>If you made it this far, then I hope I made it <em>Constructive</em>, if your receive it as positive or negative, is probably up to <a target="_blank" href="https://www.google.com/search?q=confirmation+bias&amp;rlz=1C1CHBF_enUS1005US1005&amp;sourceid=chrome&amp;ie=UTF-8">confirmation bias</a> more than anything else. So this is my attempt at a solution</p>
<h3 id="heading-so-before-you-leave-a-comment">So before you leave a comment</h3>
<p><em>Re-read this entire article for comprehension, then write your comment, but before you publish it. Delete it. Then re-read this entire article again, write your comment. Delete it. Re-read this, and then consider if you really have something to unique to contribute that has not already been said. Re-read this article.</em></p>
<p>You get the idea, when and if your comment becomes constructive, publish it. If it isn't constructive and just a salad of logical fallacies with populist dressing, you are not making the internet (and the world) a better place.</p>
]]></content:encoded></item></channel></rss>