<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jonathan E. Magen</title>
    <description>The latest articles on DEV Community by Jonathan E. Magen (@yonkeltron).</description>
    <link>https://dev.to/yonkeltron</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F62698%2F2517ec87-1a1d-40ec-9c08-f5890aa82660.png</url>
      <title>DEV Community: Jonathan E. Magen</title>
      <link>https://dev.to/yonkeltron</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yonkeltron"/>
    <language>en</language>
    <item>
      <title>A Compendium of Gen-Z Terminology in Technical Contexts</title>
      <dc:creator>Jonathan E. Magen</dc:creator>
      <pubDate>Wed, 29 May 2024 22:20:54 +0000</pubDate>
      <link>https://dev.to/yonkeltron/a-compendium-of-gen-z-terminology-in-technical-contexts-49k3</link>
      <guid>https://dev.to/yonkeltron/a-compendium-of-gen-z-terminology-in-technical-contexts-49k3</guid>
      <description>&lt;p&gt;I wonder if others like me, other non-sociologists, also find the whole notion of a &lt;a href="https://en.wikipedia.org/wiki/Generation#List_of_social_generations"&gt;generation&lt;/a&gt; irrelevant. Seems that more folks use generational designations to broadly label, disrespect, or deride others. So I (an elder-millenial, for those looking to label) would prefer to tell you how much my Gen-Z colleagues have taught me. Hopefully, when others have the chance to develop the appreciation I have gained.&lt;/p&gt;

&lt;p&gt;To facilitate this, I have collected yet another list of terms used by my contemporaries. However, thre are two differences. One difference is that I only include that which I have personally experienced. The other is that these expressions have been presented specifically in the context of technology and computing.&lt;/p&gt;

&lt;p&gt;Any essential expressions which are missing, are missing because I've never run into them myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expressions of Words and Speech
&lt;/h2&gt;

&lt;dl&gt;
  &lt;dt&gt;Bye&lt;/dt&gt;
  &lt;dd&gt;
    A response to something exceedingly humorous, as if to say something is so funny that a politely exiting the situation is one's only reprieve.
  &lt;/dd&gt;

  &lt;dt&gt;Cap / No Cap&lt;/dt&gt;
  &lt;dd&gt;
    A lie. One might use this as others might say "for real" or "honestly" as in the example "That code worked on my machine, no cap!"
  &lt;/dd&gt;

  &lt;dt&gt;Dead&lt;/dt&gt;
  &lt;dd&gt;
    When someone says "I'm dead" they wish to indicate they have experienced extreme laughter or amusement. Seems to descend from the expression "&lt;a href="https://en.wikipedia.org/wiki/Death_from_laughter"&gt;died laughing&lt;/a&gt;".
  &lt;/dd&gt;

  &lt;dt&gt;Drag&lt;/dt&gt;
  &lt;dd&gt;
    To harshly criticize to the point of insult. A self-deprecating example might be "Thank goodness I have ESLint to drag my code."
  &lt;/dd&gt;

  &lt;dt&gt;Extra&lt;/dt&gt;
  &lt;dd&gt;
    Intense or otherwise noticable, usually positive. Can be used sarcastically in sentences such as "With so much company surveillance software on my computer, no wonder the fan is always extra."
  &lt;/dd&gt;

  &lt;dt&gt;FR&lt;/dt&gt;
  &lt;dd&gt;
    Voiced or written abbreviation for "for real".
  &lt;/dd&gt;

  &lt;dt&gt;Gatekeep&lt;/dt&gt;
  &lt;dd&gt;
    To hoard useful knowledge. This differs from its previous usage of denying others' belonging in a given group.
  &lt;/dd&gt;

  &lt;dt&gt;Here for it
  &lt;/dt&gt;
&lt;dd&gt;
    Used to indicate a satisfactory approval such that it is, alone, enough motivation to justify one's presence.
  &lt;/dd&gt;

  &lt;dt&gt;High-Key and Low-Key&lt;/dt&gt;
  &lt;dd&gt;
    Either way this is an admission of approval or adoration in the face of relative distate within a given social group. It might be used conspiratorially to express an unpopular opinion "I low-key love Java". Alternatively you can use it as a proud declaration of enthusiasm in opposition to the conventional wisdom when saying "I high-key think Windows is right for this".
  &lt;/dd&gt;

  &lt;dt&gt;Hits different&lt;/dt&gt;
  &lt;dd&gt;
    If something hits different, it is uniquely positive. You may here it as "I thought Python had great docs but the Rust documentation hits different."
  &lt;/dd&gt;

  &lt;dt&gt;I love that for you&lt;/dt&gt;
  &lt;dd&gt;
    This term indicates both sincere and personal enthusiasm. It may be paired with a compliment in phrases such as "You are so good at explaining algorithms. I love that for you!" Though, it may also be used alone as a compliment.
  &lt;/dd&gt;

  &lt;dt&gt;IYKYK&lt;/dt&gt;
  &lt;dd&gt;
    An abbreviation, usually written, for "if you know, you know". This most often refers to insider knowledge or understanding, but could also highlight the presence of an &lt;a href="https://en.wikipedia.org/wiki/In-joke"&gt;in-joke&lt;/a&gt;.
  &lt;/dd&gt;

  &lt;dt&gt;Jail&lt;/dt&gt;
  &lt;dd&gt;
    Strong disapproval in response to learning of something undesirable. It most likely originated as shorthand for "that's so terrible, it should be imprisoned". If you were to tell how a cloud platform deleted virtual machines without warning, you might hear the  "jail" in response.
  &lt;/dd&gt;

  &lt;dt&gt;Main Character / Main Character Energy&lt;/dt&gt;
  &lt;dd&gt;
    A person who has main character energy has become, positively, the center of attention. Someone who is the prime mover of, or instigator in, a situation.
  &lt;/dd&gt;

  &lt;dt&gt;MFRN / MFW&lt;/dt&gt;
  &lt;dd&gt;
    Written abbreviations for "my face right now" and "my face when". Always coupled with a graphical depiction such an expressive emoji, GIF, or other image.
  &lt;/dd&gt;

  &lt;dt&gt;Obsessed&lt;/dt&gt;
  &lt;dd&gt;
    A spoken declaration of enthusiastic approval usually sprinkled throughout conversation. Those who hear it may safely &lt;a href="http://clhs.lisp.se/Body/f_mexp_.htm"&gt;macroexpand&lt;/a&gt; it to "I'm obsessed with that". It could be used in the same way as someone listening would say "uh-huh" or "go on" to informally confirm that their attention remains focused on the speaker. 
  &lt;/dd&gt;

  &lt;dt&gt;Sending me&lt;/dt&gt;
  &lt;dd&gt;
    Used to indicate when someone or something induces amusement, as in "Our tech lead's source comment in the integration code absolutely sent me."
  &lt;/dd&gt;

  &lt;dt&gt;Sheesh&lt;/dt&gt;
  &lt;dd&gt;
    An exclamation that someone is "looking good" or seems impressive. Often used alone as a reaction or for emphasis in usages like "Did you see her bugfix? Sheesh!"
  &lt;/dd&gt;

  &lt;dt&gt;Simp&lt;/dt&gt;
  &lt;dd&gt;
    Anything or anyone noticeably enamored with a given subject. Can be used appreciatively or cheekily in sentences like "The Rust compiler catches so many bugs for me, what a simp!"
  &lt;/dd&gt;

  &lt;dt&gt;Sus&lt;/dt&gt;
  &lt;dd&gt;
    Short for "suspicious" and used to indicate distrust or disbelief. You might hear it stated that "It's sus because the tests pass but it produces the wrong output in production."
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;h2&gt;
  
  
  Graphical or Pictoral Expressions
&lt;/h2&gt;

&lt;p&gt;It has been my experience that GIF reactions or messages are usually employed sparingly. On the other hand, emoji may be used liberally albeit with differing connotations.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;💀&lt;/dt&gt;
  &lt;dd&gt;See: Dead&lt;/dd&gt;

  &lt;dt&gt;😭&lt;/dt&gt;
  &lt;dd&gt;As if to day: "I'm laughing so hard that I'm crying!"&lt;/dd&gt;

  &lt;dt&gt;✍️&lt;/dt&gt;
  &lt;dd&gt;Communicates that the sender is paying attention so closely, it's as if they're taking notes.&lt;/dd&gt;
&lt;/dl&gt;

</description>
      <category>slang</category>
      <category>humor</category>
      <category>satire</category>
    </item>
    <item>
      <title>If SAFe was a programming language, would you use it?</title>
      <dc:creator>Jonathan E. Magen</dc:creator>
      <pubDate>Mon, 20 Feb 2023 14:05:22 +0000</pubDate>
      <link>https://dev.to/yonkeltron/if-safe-was-a-programming-language-would-you-use-it-2g02</link>
      <guid>https://dev.to/yonkeltron/if-safe-was-a-programming-language-would-you-use-it-2g02</guid>
      <description>&lt;p&gt;Even with all of &lt;a href="https://seandexter1.medium.com/beware-safe-the-scaled-agile-framework-for-enterprise-an-unholy-incarnation-of-darkness-bf6819f6943f"&gt;the&lt;/a&gt; &lt;a href="https://ibrahimcesar.cloud/blog/SAFe-considered-harmful/"&gt;many&lt;/a&gt; &lt;a href="https://jeffgothelf.com/blog/safe-is-not-agile/"&gt;criticisms&lt;/a&gt; of the Scaled Agile Framework (SAFe), people still seem to use it. So let's do a thought experiment and ask the question, "if SAFe were a programming language, would you use it?"&lt;/p&gt;

&lt;p&gt;To answer this question, let's hypothesize a satirical programming language.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introducing SafeScript: A DSL for building valuable software using the SAFe methodology
&lt;/h1&gt;

&lt;p&gt;SafeScript is a domain-specific language (DSL) geared toward building valuable software using the SAFe methodology.&lt;br&gt;
It is a statically typed, purely functional, expression-based language executed by a special interpreter called the Execution Train Engineer (ETE).&lt;/p&gt;

&lt;p&gt;Providing the SafeScript ETE with a SafeScript program enables you to get good, cheap, and fast execution thanks to its fully &lt;a href="https://en.wikipedia.org/wiki/Reversible_computing"&gt;reversible&lt;/a&gt; design.&lt;/p&gt;
&lt;h2&gt;
  
  
  Design principles
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Modular and functional:&lt;/strong&gt; The core building blocks of SafeScript are functions and modules.&lt;br&gt;
Functions can be contained within modules and modules are contained within files. Logic may be contained within either functions or modules, but modules cannot be within functions, though don't forget they are in files. Logic may not live outside of a function unless inside a module in the form of bindings. In this essay&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All functions are anonymous by default:&lt;/strong&gt; Functions are the backbone of your application, the workhorses of all modern software. Just as developers are the workhorses of a software product's construction! Because of this similarity, functions are anonymous by default, just like SAFe treats developers as nameless and faceless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Value is a top-level concept:&lt;/strong&gt; As part of SafeScript we’ve made &lt;code&gt;val&lt;/code&gt; a keyword so it becomes very clear where your software adds value. This makes it very easy for static analysis to determine how much business value a program adds by simply counting the prevalence of &lt;code&gt;val&lt;/code&gt; keywords.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax forged in the fire of conceptual theft:&lt;/strong&gt; Just like SAFe borrows a little bit from various project management frameworks, as well as adapting concepts from Agile software development, the syntax of SafeScript borrows from other languages. Mostly, it descends from OCaml, Elixir, and a car crash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total side-effect conversion:&lt;/strong&gt; All side-effecty program units are automatically converted to side-effect free code using a process called total disjoint removal. This functionally prohibits non-essential operations such as printing to the screen, which you probably didn't need to do anyhow. If management wanted developer input, they'd ask for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Objects, done right and done safely:&lt;/strong&gt; Object systems are a fantastic language feature which help to promote productive linkages between related data and behavior. However, they can also be a source of bugs, so SafeScript has a built-in safety net which uses pre-emptive inspection to actually optimize away any fallible code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security from the get-go:&lt;/strong&gt; The SafeScript compiler ships with an approval engine as part of the SafeScript Workflow Approval Platform (WAP). This means that it will only accept programs which have been pre-approved. To gain approval, submit your program to the appropriate team by opening a ticket. Please be sure to include the business rationale and a funding stream. You will receive approval within 5-10 business days, following which you may use the &lt;code&gt;--approve&lt;/code&gt; compiler flag. This will activate all instances of the &lt;code&gt;approve&lt;/code&gt; keyword in your source code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deliberately branchless:&lt;/strong&gt; While most programs make heavy use of conditional logic in the form of &lt;code&gt;if&lt;/code&gt; statements, SafeScript has no such concept. In SafeScript, you make a plan when you write your code, and you stick to it no matter what.&lt;/p&gt;
&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;While there is no hello world equivalent for SafeScript (why would there be, you should be getting to work and delivering value instead of standing around gabbing all day), the following is a valid program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Core&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="n"&gt;panda&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="s2"&gt;"bamboo"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;Core&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;panda&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>agile</category>
      <category>plt</category>
      <category>satire</category>
    </item>
    <item>
      <title>Yes, Lisp is useful for DevOps and automation</title>
      <dc:creator>Jonathan E. Magen</dc:creator>
      <pubDate>Fri, 14 Oct 2022 12:34:44 +0000</pubDate>
      <link>https://dev.to/yonkeltron/yes-lisp-is-useful-for-devops-and-automation-1dak</link>
      <guid>https://dev.to/yonkeltron/yes-lisp-is-useful-for-devops-and-automation-1dak</guid>
      <description>&lt;p&gt;&lt;em&gt;I originally published a less-good version of this post &lt;a href="https://typeshare.co/yonkeltron/posts/-NDAfJrD3tGMOFsJ3uLQ"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this article, I will show you modern examples of Lisp which can help you with DevOps tasks and automation in general. No, I'm not joking. No, I'm not drunk.&lt;/p&gt;

&lt;p&gt;In no uncertain terms, the power of Lisp is ideally suited for automation. This is not just because of how expressive it is. It's also because of how straightforward Lisp is for solving real-world problems.&lt;/p&gt;

&lt;p&gt;Now, let's dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  1: Racket's new &lt;a href="https://docs.racket-lang.org/zuo/index.html"&gt;Zuo&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Zuo is a huge step forward for both process automation as well as using Lisp for general scripting!&lt;/p&gt;

&lt;p&gt;Since Zuo is basically just a tiny Racket wrapped around an automation-friendly core, it's ideal for scripting build systems! Zuo is &lt;a href="https://blog.racket-lang.org/2022/08/racket-v8-6.html"&gt;new in Racket 8.6&lt;/a&gt; but it's already making a splash amongst language aficionados who also need to get stuff done. Pay special attention to ways in which &lt;a href="https://docs.racket-lang.org/zuo/zuo-build.html"&gt;&lt;code&gt;zuo/build&lt;/code&gt; can help replace make&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2: High-level automation with &lt;a href="https://bass-lang.org"&gt;Bass&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;From building container images to automating builds, Bass has you covered! I originally found out about Bass from &lt;a href="https://lobste.rs/s/faafm5/bass_is_low_fidelity_lisp_dialect_for"&gt;this Lobsters post&lt;/a&gt; and have been following it ever since.&lt;/p&gt;

&lt;p&gt;Bass lang is a bespoke, "low-fidelity" Lisp which runs on top of &lt;a href="https://en.wikipedia.org/wiki/Common_Lisp"&gt;Docker's buildkit&lt;/a&gt;. Unlike Zuo, it's a Lisp dialect designed and written exclusively for the purposes of making common project tasks cacheable. It does this through the enduring magic of &lt;a href="https://en.wikipedia.org/wiki/Thunk"&gt;thunks&lt;/a&gt;, or unevaluated functions. Make sure to check out it's growing &lt;a href="https://bass-lang.org/stdlib.html"&gt;standard library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3: Configure your server fleet with &lt;a href="https://github.com/cl-adams/adams"&gt;Adams&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Sure existing options are cool, but have you tried &lt;em&gt;not&lt;/em&gt; using YAML?&lt;/p&gt;

&lt;p&gt;While Adams might seem little more than a stylistic choice in favor of &lt;a href="https://en.wikipedia.org/wiki/S-expression"&gt;S-Expressions&lt;/a&gt;, this library packs a punch. Come for the efficient code-reuse, stay for the declarative nature of configs. As a bonus feature, it's written in Common Lisp and therefore has a ton of extension potential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now go forth and be awesome! Wishing you the best of luck as you Lisp!
&lt;/h2&gt;

&lt;p&gt;Update 2024-05: &lt;a href="https://simonsafar.com/2021/lisp_scripting/"&gt;Common Lisp for shell scripting&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>lisp</category>
      <category>automation</category>
    </item>
    <item>
      <title>Is it time to look past Git?</title>
      <dc:creator>Jonathan E. Magen</dc:creator>
      <pubDate>Wed, 06 Jul 2022 13:44:32 +0000</pubDate>
      <link>https://dev.to/yonkeltron/is-it-time-to-look-past-git-ah4</link>
      <guid>https://dev.to/yonkeltron/is-it-time-to-look-past-git-ah4</guid>
      <description>&lt;p&gt;I clearly remember the rough days of &lt;a href="https://en.wikipedia.org/wiki/Concurrent_Versions_System" rel="noopener noreferrer"&gt;CVS&lt;/a&gt; and how liberating the switch to &lt;a href="https://en.wikipedia.org/wiki/Apache_Subversion" rel="noopener noreferrer"&gt;Subversion&lt;/a&gt; felt all those years ago. At the time I was pretty sure that nothing would ever get as good as Subversion. As it turns out, I was wrong, and Git showed it to me! So, having learned &lt;a href="https://en.wikipedia.org/wiki/Distributed_version_control" rel="noopener noreferrer"&gt;distributed version control&lt;/a&gt; concepts and embraced &lt;a href="https://en.wikipedia.org/wiki/Git" rel="noopener noreferrer"&gt;Git&lt;/a&gt;, I was pretty zealous about my newfound super powers. Again, I felt sure that nothing would ever surpass it. Again, it turned out I was wrong.&lt;/p&gt;

&lt;p&gt;At the time of this writing, Git's been with us for over a decade and a half. During that time the ecosystem has absolutely exploded. From the rise of GitHub and GitLab to the myriad of new subcommands (just look at &lt;a href="https://github.com/dictcp/awesome-git" rel="noopener noreferrer"&gt;all this cool stuff&lt;/a&gt;), clearly Git has seen widespread adoption and success.&lt;/p&gt;

&lt;h1&gt;
  
  
  So what's wrong with Git?
&lt;/h1&gt;

&lt;p&gt;Well for starters, I'm not the only person who thinks that &lt;a href="https://changelog.com/posts/git-is-simply-too-hard" rel="noopener noreferrer"&gt;Git is simply too hard&lt;/a&gt;. While some apparently &lt;a href="https://ottovw.medium.com/forget-git-just-use-subversion-or-perforce-8412dc1b1644" rel="noopener noreferrer"&gt;yearn for the simpler Subversion days&lt;/a&gt;, my frustration comes from working with Git itself, some of which &lt;a href="https://stevebennett.me/2012/02/24/10-things-i-hate-about-git/" rel="noopener noreferrer"&gt;others have been pointing out for the last decade&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My frustrations are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I find the &lt;code&gt;git-*&lt;/code&gt; family of utilities entirely too low-level for comfort. I once read a quote that Git is a version control construction kit more than a tool to be used directly. I think about this quote a lot.&lt;/li&gt;
&lt;li&gt;Git's underlying data model is unintuitive, and I love me a good graph data structure. Conceiving of a project's history as a non-causal treeish arrangement has been really hard for me to explain to folks and often hard for me to think about. Don't get me started on &lt;code&gt;git rebase&lt;/code&gt; and friends.&lt;/li&gt;
&lt;li&gt;I can't trust Git's 3-way merge to preserve the exact code I reviewed. More &lt;a href="https://www.quora.com/Is-it-possible-for-Git-merging-to-make-a-mistake-without-detecting-a-conflict" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://www.caktusgroup.com/blog/2018/03/19/when-clean-merge-wrong/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two interesting projects I've discovered recently aim to add a Git-compatible layer on top of Git's on-disk format in order to simplify things. If not to simplify the conceptual model, then at least to provide an alternative UX.&lt;/p&gt;

&lt;p&gt;One such project is the &lt;a href="https://gitless.com/" rel="noopener noreferrer"&gt;Gitless&lt;/a&gt; initiative which has a Python wrapper around Git proper providing far-simpler workflows based on &lt;a href="https://gitless.com/#research" rel="noopener noreferrer"&gt;some solid research&lt;/a&gt;. Unfortunately it doesn't look like &lt;a href="https://github.com/gitless-vcs/gitless" rel="noopener noreferrer"&gt;Gitless' Python codebase&lt;/a&gt; has had active development recently, which doesn't inspire much confidence. &lt;/p&gt;

&lt;p&gt;An alternative project to both Git and Gitless is a little Rust project called &lt;a href="https://github.com/martinvonz/jj" rel="noopener noreferrer"&gt;Jujutsu&lt;/a&gt;. According to the project page Jujutsu aims, at least in part, to preserve compatibility with Git's on-disk format. Jujutsu also boasts its own "native" format letting you choose between using the &lt;code&gt;jj&lt;/code&gt; binary as a front-end for Git data or as a net-new tool.&lt;/p&gt;

&lt;h1&gt;
  
  
  What have we learned since Git?
&lt;/h1&gt;

&lt;p&gt;Well technically one alternative I am going to bring up predates Git by several years, and that's &lt;a href="http://darcs.net/" rel="noopener noreferrer"&gt;DARCS&lt;/a&gt;. Fans of DARCS have written &lt;a href="http://komar.in/en/git-sucks-or-why-do-I-use-darcs-instead" rel="noopener noreferrer"&gt;plenty of material&lt;/a&gt; on Git's perceived weaknesses. While DARCS' Haskell codebase apparently had some issues, its underlying "change" semantics have remained influential. For example, &lt;a href="https://pijul.org/" rel="noopener noreferrer"&gt;Pijul&lt;/a&gt; is a Rust-based contender currently in beta. It embraces a huge number of the paradigms, including &lt;a href="https://pijul.org/manual/why_pijul.html" rel="noopener noreferrer"&gt;the concept of commutative changes&lt;/a&gt;, which made DARCS effective and ergonomic. In my estimation, &lt;a href="https://pijul.org/manual/theory.html" rel="noopener noreferrer"&gt;the very concept of change commutation greatly improves any graph-based models&lt;/a&gt; of repositories. This led me to have a really wonderful user experience when taking Pijul out for a spin on some smallish-local projects.&lt;/p&gt;

&lt;p&gt;While Pijul hasn't yet reached production-quality maturity, the &lt;a href="https://fossil-scm.org" rel="noopener noreferrer"&gt;Fossil project&lt;/a&gt; has a pretty good track record. Fossil styles itself as the batteries-included SCM which has long been used as the primary VCS for development of &lt;a href="https://www.sqlite.org/index.html" rel="noopener noreferrer"&gt;the venerable SQLite project&lt;/a&gt;. In trying out Fossil, I would rate its usability and simplicity as being roughly on par with Pijul, plus you get all the extras like a built-in web interface complete with forums, wiki, and an issue tracker.&lt;/p&gt;

&lt;p&gt;Ultimately I prefer the Pijul model more than Fossil's but still can't realistically see either of them replacing Git.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why I'm not ditching Git (yet)
&lt;/h1&gt;

&lt;p&gt;While my frustrations have lead me to look past Git, I've come to the conclusion that I can't ditch it quite yet. Git's dominance is largely cemented and preserved by its expansive ecosystem. It's so much more than &lt;a href="https://code.visualstudio.com/docs/editor/versioncontrol" rel="noopener noreferrer"&gt;the Git integration which ships standard in VSCode&lt;/a&gt; and even more than the ubiquity of platforms like GitHub and GitLab. It comes down to hearts and minds insofar as folks have spent so much time "getting good at Git" that they lack the motivation to switch right now. Coupled with the pervasiveness of Git in software development shops, it's hard to envision any alternatives achieving the requisite critical mass to become a proper success. &lt;/p&gt;

&lt;p&gt;Granted, just as Git had &lt;a href="https://git-scm.com/docs/git-svn" rel="noopener noreferrer"&gt;a built-in feature&lt;/a&gt; to ease migration from Subversion, Fossil has &lt;a href="https://fossil-scm.org/home/doc/trunk/www/mirrortogithub.md" rel="noopener noreferrer"&gt;a similar feature&lt;/a&gt; to help interface with Git. That certainly helps, but I honestly don't know if it'll be enough.&lt;/p&gt;

</description>
      <category>git</category>
      <category>scm</category>
      <category>devops</category>
    </item>
    <item>
      <title>Illustrating the duality of closures and objects</title>
      <dc:creator>Jonathan E. Magen</dc:creator>
      <pubDate>Tue, 14 Jun 2022 01:10:07 +0000</pubDate>
      <link>https://dev.to/yonkeltron/illustrating-the-duality-of-closures-and-objects-2nfm</link>
      <guid>https://dev.to/yonkeltron/illustrating-the-duality-of-closures-and-objects-2nfm</guid>
      <description>&lt;p&gt;I'd heard it before but this time it really sunk in. Let me explain a bit more.&lt;/p&gt;

&lt;p&gt;I was recently reading the first few chapters of &lt;a href="https://mitpress.mit.edu/books/software-design-flexibility" rel="noopener noreferrer"&gt;Software Design for Flexibility&lt;/a&gt; (SDF). Doing so reminded of the duality between closures in Functional Programming (FP) and object instances in Object-Oriented Programming (OOP). When I'd heard it previously this connection had seemed tenuous at best and irrelevant at worst. However when I considered this duality this last time, I was able to internalize its significance.&lt;/p&gt;

&lt;p&gt;I further chatted about this realization with my friend &lt;a href="https://twitter.com/reuvenmlerner" rel="noopener noreferrer"&gt;Reuven Lerner&lt;/a&gt; who quoted one of his teachers saying that "closures are outside-in objects" and it blew my mind. As a concession to Reuven being one of the world's most successful &lt;a href="https://lerner.co.il/" rel="noopener noreferrer"&gt;Python trainers&lt;/a&gt;, code examples below are written in typed Python.&lt;/p&gt;

&lt;p&gt;Let's dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an object?
&lt;/h2&gt;

&lt;p&gt;When you ask this question to different communities you will get different answers. For example a Smalltalker will likely leverage message passing in their definition while the Java kids' explanations might hinge on inheritance and encapsulation. Still, a Lisper will likely get very excited to tell you about generic functions and the importance of the &lt;a href="https://en.wikipedia.org/wiki/Metaobject" rel="noopener noreferrer"&gt;metaobject protocol&lt;/a&gt;. None of these responses would be incorrect, strictly speaking.&lt;/p&gt;

&lt;p&gt;For our purposes, we're going to use a more linguistically neutral definition and say that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An object is a logical grouping of related data and behavior.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, an object is the "what" and the "how" packaged together. In the words of Hanson and Sussman, the authors of SDF, the data and state of an object are "curated" together so that they can subsequently influence the actions of the object.&lt;/p&gt;

&lt;p&gt;Assume our problem domain has the concept of a "pipeline job". How might we represent this entity using a classical object system like the one found in Python?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pipeline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PIPELINE[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the string construction is merely a stand in for the business logic of our pipeline for the sake of simplicity.&lt;/p&gt;

&lt;p&gt;That seems simple enough, right? With this approach we can also hold onto one or many &lt;code&gt;Pipeline&lt;/code&gt; instances and execute them whenever we please!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Conjure up a pipeline
&lt;/span&gt;&lt;span class="n"&gt;my_pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Use it whenever
&lt;/span&gt;&lt;span class="n"&gt;my_pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What is a closure?
&lt;/h2&gt;

&lt;p&gt;A closure is a special function which retains references to the environment in which it was defined. Let's look at a simple example!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;vanilla_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;closure_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we define three variables, where the first is a number and the latter two are functions. The first function, &lt;code&gt;vanilla_func&lt;/code&gt;, simply adds 10 to its argument. The second one, &lt;code&gt;closure&lt;/code&gt;, adds 5 to its argument. You'll also likely notice that &lt;code&gt;closure_func&lt;/code&gt; references &lt;code&gt;external&lt;/code&gt; which is defined outside its body. Since &lt;code&gt;external&lt;/code&gt; is not in the parameter list of &lt;code&gt;closure_func&lt;/code&gt; but appears in the body, it is a &lt;em&gt;free variable&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;closure_func&lt;/code&gt; references a free variable from the (lexical) environment in which it was defined, it is a closure as that reference persists for the life of &lt;code&gt;closure_func&lt;/code&gt;. Hence, we say that a function is a closure because it &lt;em&gt;closes over&lt;/em&gt; the variables in its environment! If my explanation wasn't quite right and this doesn't make sense to you yet, there's some great material out there to help&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An entire &lt;a href="https://www.pythontutorial.net/advanced-python/python-closures/" rel="noopener noreferrer"&gt;article, replete with examples, illustrating closures&lt;/a&gt; in Python using regular old functions.&lt;/li&gt;
&lt;li&gt;A fantastic explainer on closures with JavaScript examples &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" rel="noopener noreferrer"&gt;over on the MDN Web Docs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://medium.com/@bdov_/javascript-typescript-clarifying-closures-e9c17d10c4e2" rel="noopener noreferrer"&gt;article using TypeScript examples&lt;/a&gt; with some excellent illustrations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In languages which support FP, functions can be returned from other functions. So let's see what our pipeline conception from earlier would look like when modeled as a closure. Again, with a Python example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Callable&lt;/span&gt;&lt;span class="p"&gt;[[],&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;

    &lt;span class="c1"&gt;# closure is here
&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_pipeline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PIPELINE[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;destination&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;

    &lt;span class="c1"&gt;# return the closure as a thunk
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;execute_pipeline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, &lt;code&gt;make_pipeline&lt;/code&gt; returns a closure, &lt;code&gt;execute_pipeline&lt;/code&gt; which is enriched with the same data and behavior as the &lt;code&gt;Pipeline&lt;/code&gt; object from the previous section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Conjure up a pipeline
&lt;/span&gt;&lt;span class="n"&gt;my_pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Use it whenever
&lt;/span&gt;&lt;span class="nf"&gt;my_pipeline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrap-up discussion
&lt;/h2&gt;

&lt;p&gt;We can immediately see some surface-level parallels between the closure and object approaches to expressing our domain's pipeline concept. The two Python code examples make it clear that you can achieve the same level of ahead-of-time data and behavior curation with closures as you can with objects. In short, we've highlighted a duality linking OOP object instances with FP closures. In my gut, I believe this should be explored and formalized further.&lt;/p&gt;

&lt;p&gt;If you like this stuff, please reach out to me since I would love to discuss it further!&lt;/p&gt;

</description>
      <category>oop</category>
      <category>functional</category>
      <category>python</category>
    </item>
    <item>
      <title>A modern, ergonomic Unix shell configuration with Fish</title>
      <dc:creator>Jonathan E. Magen</dc:creator>
      <pubDate>Sun, 21 Nov 2021 18:11:28 +0000</pubDate>
      <link>https://dev.to/yonkeltron/a-modern-ergonomic-unix-shell-configuration-with-fish-4dio</link>
      <guid>https://dev.to/yonkeltron/a-modern-ergonomic-unix-shell-configuration-with-fish-4dio</guid>
      <description>&lt;p&gt;Like many others, I spend enough time in the shell that even small improvements can yield huge productivity gains. This post is an attempt to catalog several of quality-of-life enhancements I've made over recent months to my shell setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  History
&lt;/h2&gt;

&lt;p&gt;Like most folks I know, I began my command-line life with good 'ol Bash and actually still do most of my shell scripting in Bash. Even if I eventually rewrite the command in another language, many of my tools begin life as a Bash script.&lt;/p&gt;

&lt;p&gt;At some point, perhaps ~10 years ago, I was introduced to ZSH with the venerable &lt;a href="https://ohmyz.sh/"&gt;Oh My ZSH&lt;/a&gt; framework. For me, this was a huge awakening because it taught me about how much shell improvements can impact your life. I gradually evolved my ZSH setup to use package managers like &lt;a href="https://github.com/zsh-users/antigen"&gt;antigen&lt;/a&gt; and began to invest more in creature comforts.&lt;/p&gt;

&lt;p&gt;Since that time, while the productivity gains have compounded, friends recommended Fish to me, the Friendly Interactive SHell. For my workflows this was the major boost which catapulted my shell configuration from "good enough" to actually "working well".&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Fish?
&lt;/h2&gt;

&lt;p&gt;The first thing I noticed was that the default configuration of Fish was equivalent to about 30-45 lines of ZSH config. So even starting fresh with Fish was already roughly on-par with my previous ZSH configuration. Moreover, I find that the modern Fish dialect, especially its error-case semantics, are vastly superior considering the frequency with which things go wrong. In this way, Fish gives me a much more solid foundation on which to build a proper environment for myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diving into my Fish config
&lt;/h2&gt;

&lt;p&gt;The core of any Fish config is the &lt;code&gt;config.fish&lt;/code&gt; file found at &lt;code&gt;~/.config/fish/config.fish&lt;/code&gt; on most systems.&lt;/p&gt;

&lt;p&gt;Mine looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env fish

# Configure my shell's prompt
starship init fish | source

# Make it easy to switch to commonly-used directories
zoxide init fish | source

# Set up my ruby environment with rbenv
status --is-interactive; and source (rbenv init -|psub)
set -gx PATH "$HOME/.rbenv/bin" $PATH

# Use VS Code as the default editor and block until the file is closed
set -x EDITOR 'code --wait'

# Make skim do the right thing by default
set -x SKIM_DEFAULT_COMMAND "fd --type f"

## Elixir and Erlang
# Elixir package timeout to prevent stalled downloads
set -x HEX_HTTP_TIMEOUT 59
# Elixir IEx history config
set -x ERL_AFLAGS '-kernel shell_history enabled'

## Rust
# Enable a shared Cargo target directory to cut down on disk usage
set -x CARGO_TARGET_DIR $HOME/.cargo/shared_target
# Ensure that Cargo binaries are in the PATH
set PATH $HOME/.cargo/bin/ $PATH

# Helpful expansions
abbr -a -g gp git push
abbr -a -g gc git commit -asm
abbr -a -g gst git status

# Helpful aliases
command -q exa; and alias la="exa -abghl --git --color=automatic"
command -q exa; and alias ll="exa -bghl --git --color=automatic"

# Fisher!
if not functions -q fisher
    set -q XDG_CONFIG_HOME; or set XDG_CONFIG_HOME ~/.config
    curl https://git.io/fisher --create-dirs -sLo $XDG_CONFIG_HOME/fish/functions/fisher.fish
    fish -c fisher
end

## Node
# Volta config
set -gx VOLTA_HOME "$HOME/.volta"
set -gx PATH "$VOLTA_HOME/bin" $PATH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Analysis
&lt;/h3&gt;

&lt;p&gt;In order of appearance, here are some of the tools which feature in the above Fish config:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://starship.rs/"&gt;Starship&lt;/a&gt; prompt is a terrific alternative to slower prompts written in pure shell. It supports a whole variety of status features, is quite performant, and has easy-to-understand configuration options.&lt;/li&gt;
&lt;li&gt;I use &lt;a href="https://github.com/ajeetdsouza/zoxide"&gt;zoxide&lt;/a&gt; to quickly switch to recently used directories, or to paths which I use particularly commonly. It can be hard to remember to use &lt;code&gt;z&lt;/code&gt; instead of &lt;code&gt;cd&lt;/code&gt; but once you get the hang of it you'll never go back.&lt;/li&gt;
&lt;li&gt;My setup relies heavily on &lt;a href="https://github.com/rbenv/rbenv"&gt;rbenv&lt;/a&gt; since I use Ruby for automation all over the place.&lt;/li&gt;
&lt;li&gt;Tools like &lt;a href="https://github.com/lotabout/skim"&gt;skim&lt;/a&gt; work great with others like &lt;a href="https://github.com/sharkdp/fd"&gt;fd&lt;/a&gt; to provide additional functionality when it comes to locating files and filtering through search results. I also use skim's &lt;code&gt;sk&lt;/code&gt; command pretty heavily in other scripts when interactivity is required.&lt;/li&gt;
&lt;li&gt;Even though &lt;code&gt;ls&lt;/code&gt; is a good-old standby, I prefer the aliases for &lt;code&gt;ll&lt;/code&gt; and &lt;code&gt;la&lt;/code&gt; that rely on &lt;a href="https://the.exa.website/"&gt;exa&lt;/a&gt;. These aliases default to showing important information like git status and can even prevent me from needing to launch subsequent, exploratory commands.&lt;/li&gt;
&lt;li&gt;I really fancy the &lt;a href="https://github.com/jorgebucaran/fisher"&gt;Fisher&lt;/a&gt; package manager for installing Fish libraries, tools, and commands!&lt;/li&gt;
&lt;li&gt;Since I'm a big fan of toolchains as code, I've fallen in love with &lt;a href="https://volta.sh/"&gt;volta&lt;/a&gt; for managing my Node.js and Yarn versions. Don't forget commands like &lt;code&gt;volta pin&lt;/code&gt; in Node.js projects to lock in versions to your &lt;code&gt;package.json&lt;/code&gt; file!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So I guess you could say that Fish really hooked me. Get it? Anyway, thanks for reading this post and feel free to reach out to me with your favorite shell tricks and quality-of-life improvements! I really love this stuff and would love to hear from you.&lt;/p&gt;

</description>
      <category>fish</category>
      <category>unix</category>
      <category>linux</category>
      <category>shell</category>
    </item>
    <item>
      <title>The coming era of OS kernel modularity</title>
      <dc:creator>Jonathan E. Magen</dc:creator>
      <pubDate>Wed, 29 May 2019 15:28:33 +0000</pubDate>
      <link>https://dev.to/yonkeltron/the-coming-era-of-os-kernel-modularity-5emc</link>
      <guid>https://dev.to/yonkeltron/the-coming-era-of-os-kernel-modularity-5emc</guid>
      <description>&lt;p&gt;There used to be &lt;a href="https://en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate" rel="noopener noreferrer"&gt;a debate&lt;/a&gt; between folks about whether monolithic kernels or microkernels were the superior architecture. It might have been interesting, but it got pretty ugly at times. While the flame war raged on, research and development continued in parallel within both the academic and industrial worlds. Looking back on it now, it's clearly not merely a matter of monolith vs. microkernel architecture. Rather, it's a larger discussion about code modularity. &lt;/p&gt;

&lt;p&gt;The last few years have shown us a few key trends hidden among the often-overlooked activity in the world of Operating System (OS) development. Chief among them is the idea that the future need not look like the past. From &lt;a href="https://en.wikipedia.org/wiki/Google_Fuchsia" rel="noopener noreferrer"&gt;Google's Fuchsia&lt;/a&gt; project to &lt;a href="https://en.wikipedia.org/wiki/Berkeley_Packet_Filter" rel="noopener noreferrer"&gt;BPF&lt;/a&gt; in Linux, the era of kernel modularity has arrived.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2Fz508Zk08HNU" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2Fz508Zk08HNU"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Modular kernels currently under development
&lt;/h1&gt;

&lt;p&gt;If you keep your ear to the ground, you'll inevitably hear the excited rumblings of folks watching the not-so-secret development of Google's new open source &lt;a href="https://fuchsia.googlesource.com/?format=HTML" rel="noopener noreferrer"&gt;Fuchsia operating system&lt;/a&gt;. The Fuchsia kernel is called &lt;a href="https://fuchsia.googlesource.com/zircon" rel="noopener noreferrer"&gt;Zircon and is written in C++&lt;/a&gt;. Zircon is notable for a variety of reasons, not the least of which is the eschewing of the traditional POSIX standard in favor of what it's supporters refer to as "more modern" conventions. Of particular note is the intentional &lt;a href="https://fuchsia.googlesource.com/fuchsia/+/master/docs/the-book/dotdot.md" rel="noopener noreferrer"&gt;deprecation of dotdot filesystem conventions&lt;/a&gt; for security reasons. Anyone interested in what else Google's Fuchsia team considers to be modern conventions should be referred to the &lt;a href="https://fuchsia.googlesource.com/fuchsia/+/master/docs" rel="noopener noreferrer"&gt;Fuchsia docs&lt;/a&gt;, with the most popular destination being &lt;a href="https://fuchsia.googlesource.com/fuchsia/+/master/docs/the-book/" rel="noopener noreferrer"&gt;The Book&lt;/a&gt;. This recent &lt;a href="https://bzdww.com/article/163937/" rel="noopener noreferrer"&gt;set of notes&lt;/a&gt; from China may also be of interest.&lt;/p&gt;

&lt;p&gt;Though Google Fuchsia has forsaken POSIX, not all modular kernels have followed suit. For example, the &lt;a href="https://www.redox-os.org/" rel="noopener noreferrer"&gt;Redox&lt;/a&gt; project has opted to continue the POSIX tradition while clearly going for a microkernel approach. Since the goal of Redox is to make a reliable, secure, general purpose OS, the team chose to write everything in the &lt;a href="https://www.rust-lang.org/" rel="noopener noreferrer"&gt;Rust programming language&lt;/a&gt;. This seems like a great idea as Rust has really wonderful safety guarantees and very ergonomic error handling.&lt;/p&gt;

&lt;p&gt;On the Rust front, Redox isn't the only game in town as the new &lt;a href="https://www.tockos.org/" rel="noopener noreferrer"&gt;Tock&lt;/a&gt; OS receives more attention for targeting embedded and low-power systems. The website touts the ability for Tock to run on everything from industrial sensors to security keys to watches. If you're into IoT and value security and reliability, keep an eye on Tock.&lt;/p&gt;

&lt;p&gt;Moreover, there's even an experimental research OS called &lt;a href="https://github.com/manticoreos/manticore" rel="noopener noreferrer"&gt;Manticore&lt;/a&gt;, also written in Rust, aiming to explore the world and concepts of &lt;a href="http://penberg.org/parakernel-hotos19.pdf" rel="noopener noreferrer"&gt;parakernels&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No discussion of modular kernels would be complete without a mention of the &lt;a href="https://genode.org/" rel="noopener noreferrer"&gt;Genode&lt;/a&gt; project. Genode isn't an actual kernel so much as a microkernel construction kit. Even though it's written in C++, Genode claims that it offers a security-first approach to OS development with sights set on both IoT as well as more traditional workloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FxFjti9rYILo" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FxFjti9rYILo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The monolith strikes back
&lt;/h1&gt;

&lt;p&gt;Despite its roots as a monolithic kernel, Linux was always able to sidestep an entire class of problems by leveraging &lt;a href="https://en.wikipedia.org/wiki/Loadable_kernel_module#Linux" rel="noopener noreferrer"&gt;dynamically linked kernel modules&lt;/a&gt; at run time. However, while this has proven a successful strategy, the discussion of modularity has shifted with the advent of kernel support for running programs written using the &lt;a href="https://en.wikipedia.org/wiki/Berkeley_Packet_Filter" rel="noopener noreferrer"&gt;Berkeley Packet Filter (BPF)&lt;/a&gt; mechanism. Originally developed for controlling network IO, BPF has since been extended (eBPF) to allow for attaching filters to various OS functions. The upshot of ePBF support in Linux is that it allows for tying code deep into the kernel without modifying the kernel itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.brendangregg.com/blog/2019-01-01/learn-ebpf-tracing.html" rel="noopener noreferrer"&gt;Brendan Gregg has a terrific compilation&lt;/a&gt; of eBPF learning resources available on his blog and the &lt;a href="https://www.iovisor.org/technology/ebpf" rel="noopener noreferrer"&gt;IO Visor project also maintains&lt;/a&gt; a pretty solid overview. Also, there is a &lt;a href="https://learning.oreilly.com/library/view/linux-observability-with/9781492050193/" rel="noopener noreferrer"&gt;performance-oriented BPF book&lt;/a&gt; set to be published in October of 2019.&lt;/p&gt;

&lt;p&gt;Even though they're certainly smaller than classical OSes, the newer world of &lt;a href="http://unikernel.org/" rel="noopener noreferrer"&gt;Unikernels&lt;/a&gt; borrows heavily from the research world's development of nanokernels carrying with them the concept of a &lt;a href="https://en.wikipedia.org/wiki/Operating_system#Library" rel="noopener noreferrer"&gt;LibraryOS&lt;/a&gt;. Standing tall among them is the venerable &lt;a href="https://mirage.io/" rel="noopener noreferrer"&gt;MirageOS&lt;/a&gt; project, a library OS written entirely in &lt;a href="https://en.wikipedia.org/wiki/OCaml" rel="noopener noreferrer"&gt;OCaml&lt;/a&gt;. For people interested in the "mini-monolith" (minilith?) approach of Unikernels looking to develop in languages other than OCaml, the &lt;a href="http://unikernel.org/projects/" rel="noopener noreferrer"&gt;Unikernels website maintains a list of projects&lt;/a&gt; from which you can pick anything from Go to BEAM languages.&lt;/p&gt;

&lt;p&gt;Another exciting option, geared more toward traditional development, is the &lt;a href="http://unikernel.org/" rel="noopener noreferrer"&gt;UniK project started by my friend Idit Levine&lt;/a&gt;, which can take almost any existing program and produce a Unikernel from it. There are examples for common languages and platforms such as &lt;a href="https://github.com/solo-io/unik/blob/master/docs/getting_started_node.md" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;, &lt;a href="https://github.com/solo-io/unik/blob/master/docs/getting_started_python3.md" rel="noopener noreferrer"&gt;Python3&lt;/a&gt;, and even &lt;a href="https://github.com/solo-io/unik/blob/master/docs/getting_started_java.md" rel="noopener noreferrer"&gt;Java&lt;/a&gt;. One of the cooler things about UniK is how clean the code is, you can read through the (Go) source and understand a great deal about how it provides a pluggable backend supporting flavors such as &lt;a href="https://github.com/solo-io/unik/blob/master/docs/compilers/rump.md" rel="noopener noreferrer"&gt;rumprun&lt;/a&gt; and even &lt;a href="https://firecracker-microvm.github.io/" rel="noopener noreferrer"&gt;Firecracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FhsPFuudRg5I" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FhsPFuudRg5I"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What about a language VM as the kernel?
&lt;/h1&gt;

&lt;p&gt;There have been multiple attempts to write OS kernels in interpreted or semi-compiled languages. Two of the most notable are actually the now defunct &lt;a href="http://jnode.org/" rel="noopener noreferrer"&gt;JNode&lt;/a&gt; and &lt;a href="http://www4.cs.fau.de/Projects/JX/index.html" rel="noopener noreferrer"&gt;JX&lt;/a&gt; projects. However, one additional effort from the past also stands out as significant.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Singularity_(operating_system)" rel="noopener noreferrer"&gt;Singularity OS&lt;/a&gt; research project at Microsoft has been discontinued now for the better part of a decade, but has continued to intrigue me whenever I think about it. An attempt to make an entire OS in nothing but C# and a minimal VM, it was rumored to have heavily leveraged a Just-In-Time (JIT) compiler to provide runtime profile and optimizations far beyond what a traditional Ahead-Of-Time (AOT) compiled kernel could offer. Additionally, the supposed memory safety of such &lt;a href="https://en.wikipedia.org/wiki/Managed_code" rel="noopener noreferrer"&gt;managed&lt;/a&gt; languages could offer some terrific security guarantees like runtime memory inspection and execution supervision.&lt;/p&gt;

&lt;p&gt;In recent months, I have watched the development of WebAssembly (WASM) and the &lt;a href="https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/" rel="noopener noreferrer"&gt;announcement&lt;/a&gt; of the &lt;a href="https://wasi.dev/" rel="noopener noreferrer"&gt;WebAssembly System Interface (WASI)&lt;/a&gt; with great interest. While tools like &lt;a href="https://wasmer.io/" rel="noopener noreferrer"&gt;wasmer&lt;/a&gt; make it easy to run applications compiled to WASM, I was just exposed to &lt;a href="https://nanovms.com/dev/tutorials/running-wasm-unikernels" rel="noopener noreferrer"&gt;this effort by the NanoVM folks to run WASM unikernels&lt;/a&gt;. Pretty cool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FeMc0lpn1P60" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FeMc0lpn1P60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Great, so what's the point?
&lt;/h1&gt;

&lt;p&gt;There's clearly a larger discussion happening about code and system modularity in a variety of areas. As people explore techniques like &lt;a href="https://microservices.io/" rel="noopener noreferrer"&gt;microservice architectures&lt;/a&gt; (which are NOT a solution for every problem), the community continues to develop a variety of viewpoints. Therefore, it seems only natural that OS development would have a contribution to make to such discussions and that it would be influenced in return. Let's see what develops (pun intended).&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>operatingsystems</category>
      <category>linux</category>
      <category>fuchsia</category>
    </item>
    <item>
      <title>Graceful degradation: Harvest and Yield in the age of microservices</title>
      <dc:creator>Jonathan E. Magen</dc:creator>
      <pubDate>Tue, 30 Apr 2019 01:19:15 +0000</pubDate>
      <link>https://dev.to/yonkeltron/graceful-degradation-harvest-and-yield-in-the-age-of-microservices-58cj</link>
      <guid>https://dev.to/yonkeltron/graceful-degradation-harvest-and-yield-in-the-age-of-microservices-58cj</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FjW8hkB_Qmj8" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FjW8hkB_Qmj8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terms like "graceful degradation" are coming into vogue alongside the emerging discipline of &lt;a href="https://arxiv.org/pdf/1702.05843.pdf" rel="noopener noreferrer"&gt;chaos engineering&lt;/a&gt; and evolving understandings of what it means to make a distributed system fault-tolerant.&lt;/p&gt;

&lt;p&gt;Take, for example, the case of Netflix, where the term "chaos engineering" got its start. If they experience a hiccup and can't stream their normal catalog of movie titles, they might display a polite error message and instead offer a more limited selection of "featured titles". If your personalized recommendations can't be retrieved as they normally would, the platform might opt to show you the 50 most popular movies as chosen by viewers. The point is that, to their credit, Netflix will rarely "fail hard" but instead will "fail soft" by gracefully degrading the functionality they provide to ensure a reasonable user experience.&lt;/p&gt;

&lt;p&gt;In short, systems which degrade gracefully are those which prioritize availability over completeness. This is a hard, but often-necessary tradeoff when evaluating service quality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FnwbkAleBwbw" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FnwbkAleBwbw"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yet, prioritizing availability over other core functionality is nothing new to the distributed systems community. The &lt;a href="https://en.wikipedia.org/wiki/CAP_theorem" rel="noopener noreferrer"&gt;CAP theorem&lt;/a&gt;, otherwise known as &lt;a href="https://fenix.tecnico.ulisboa.pt/downloadFile/845043405442708/10.e-CAP-3.pdf" rel="noopener noreferrer"&gt;Brewer's Theorem&lt;/a&gt;, has long shown us that in the presence of network partitions within a distributed system, you must choose between that system's availability (ability to serve clients) and its data consistency (all parts of the system must agree on the same values at the same time). Therefore, it should be no surprise that a subsequent paper, by Armando Fox and Eric Brewer, lays out a foundation for following through on this sort of tradeoff.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://github.com/papers-we-love/papers-we-love/blob/master/distributed_systems/harvest-yield-and-scalable-tolerant-systems.pdf" rel="noopener noreferrer"&gt;Harvest, Yield, and Scalable Tolerant Systems&lt;/a&gt;, Fox and Brewer say quite a lot in just a few short pages. Leaving aside the fascinating statements that the authors make regarding the interpretation of the CAP theorem (strong and weak!), the paper introduces the super-useful concepts of harvest and yield.&lt;/p&gt;

&lt;p&gt;In short, Fox and Brewer borrow from engineering and define the two terms as such:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We assume that clients make queries to servers, in which case there are at least two metrics for correct behavior: yield, which is the probability of completing a request, and harvest, which measures the fraction of the data reflected in the response, i.e. the completeness of the answer to the query.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So now we have two definitions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yield&lt;/strong&gt;: a measure of a distributed system's ability to provide an answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Harvest&lt;/strong&gt;: a measure of that answer's completeness.&lt;/p&gt;

&lt;p&gt;To illustrate this concept, let's consider a simplified scenario involving a constellation of four microservices feeding data to the fictional online store for Captain Carolina's Dive Shop. Now, Captain Carolina cares just as much about designing effective software systems as she does about selling scuba lessons or surfboards so her engineers have split things up into four logical units.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Search service&lt;/strong&gt;: Provides a searchable accounting of the store's product inventory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shopping cart service&lt;/strong&gt;: Facilities for aggregating orders based on product inventory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Account service&lt;/strong&gt;: Managing everything from first-time marketing traffic through customer preferences and contact details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Recommendation engine&lt;/strong&gt;: Based on browsing habits and purchase history, provides the sort of "you might like" suggestions someone would come to expect from an online store.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every user who comes to the site is a potential customer so we want to make sure that we provide them with the best experience possible. However, we also know that not all software works all the time and even with backing-service SLAs sitting squarely in the four-nines region, no service works perfectly all the time. Therefore, we may use the dual concepts of harvest and yield to reason about the behavior of Captain Carolina's website storefront.&lt;/p&gt;

&lt;p&gt;Since things have been broken up into the aforementioned microservices, any, but not all of them, can fail and the site will still be up. In the event that the shopping cart fails, the site will still work such that visitors may still search the catalog. If the search service fails, users can still browse. If the account service fails, users can always purchase as a guest. If recommendations can't be provided, it doesn't impede the general operation of the store and merely sacrifices a chance to up sell.&lt;/p&gt;

&lt;p&gt;By isolating and compartmentalizing logic, we have also isolated and compartmentalized failure. Furthermore, in this example we have traded harvest (completeness) for yield (availability).&lt;/p&gt;

&lt;p&gt;While Brewer and Fox remind us that yield is usually measured in nines of uptime, they don't provide much guidance on harvest. In the world of microservices, you might define harvest as a measure of responding services:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;H&lt;/strong&gt;arvest = &lt;strong&gt;R&lt;/strong&gt;esponding Services / Total &lt;strong&gt;S&lt;/strong&gt;ervices&lt;/p&gt;

&lt;p&gt;Or more compactly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;H&lt;/strong&gt; = &lt;strong&gt;R&lt;/strong&gt; / &lt;strong&gt;S&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Therefore, if just one of Captain Carolina's services went down, then we could concludes that H = 3/4 = 0.75. In fact, it would only be if all of our services became unavailable, H = 0/4 = 0, that our yield would be compromised!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FlxH4ZeXXKMI" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsource.unsplash.com%2FlxH4ZeXXKMI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Wrapping up
&lt;/h1&gt;

&lt;p&gt;This article uses microservices as an example even though a microservices architecture isn't for every product, team, or problem. Generally, I hope that the paired terms of harvest and yield help you to have better conversations about service quality in distributed systems. If you liked anything about this post, please go ahead and &lt;a href="https://github.com/papers-we-love/papers-we-love/blob/master/distributed_systems/harvest-yield-and-scalable-tolerant-systems.pdf" rel="noopener noreferrer"&gt;read the paper&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>architecture</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
