<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Courageous Software</title>
  <subtitle>Do Our Best; Make Our Best Better; Help Others</subtitle>
  <icon>/images/headshot.jpg</icon>
  <link rel="alternate" type="text/html" href="https://randycoulman.com/"/>
  <link rel="self" type="application/atom+xml" href="https://randycoulman.com/atom.xml"/>
  <id>https://randycoulman.com/</id>
  <updated>2026-05-04T09:07:43-07:00</updated>
  <generator uri="http://octopress.org/">Octopress</generator>
  
  <rights>Copyright © 2026, Randy Coulman</rights>

  <entry>
    <title type="html">Looking For a New Role</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2026/05/04/looking-for-a-new-role/"/>
    
    <id>/blog/2026/05/04/looking-for-a-new-role</id>
    <published>2026-05-04T09:07:43-07:00</published>
    <updated>2026-05-04T09:07:43-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>If you need someone who can lead software teams in shipping high-quality,
sustainable software, mentor newer developers, work effectively with
stakeholders, and generally be a force-multiplier, let’s talk.</p>

<p>As of last week, my time at <a href="https://www.mechanical-orchard.com/">Mechanical
Orchard</a> has come to an end and it’s time
to look for what’s next.</p>

<p>I really enjoyed my time there and learned a ton from the great people I got to
work with. It’s amazing what you can accomplish when you put together a group of
brilliant, empathetic people that know how to work well together and pull in the
same direction.</p>

<p>I’m thankful that I had the opportunity to help solve some really hard problems.</p>

<p>What I’m looking for hasn’t changed much since the last time I was on the
market. I’ve reproduced the list below. Not much below is a deal-breaker for a
new role, but if I was able to write my own ticket, this is what it would look
like.</p>

<ul>
  <li>
    <p>I do my best work when I’m making life better for other people. That can
involve building systems that help people do their jobs more effectively,
refactoring to make a codebase easier to work in, mentoring and teaching
others, or bridging gaps to resolve conflicts between teams and individuals.
Work like this is my “happy place”.</p>
  </li>
  <li>
    <p>I want to stay on the technical side. I don’t necessarily need to have my
hands on the code all day every day, but I still enjoy building software. I’m
not interested in moving into management.</p>
  </li>
  <li>
    <p>I’d prefer to have a technical leadership role. I believe everyone can lead
from wherever they are (and I do that), but I’ve also found that having the
title matters sometimes.</p>
  </li>
  <li>
    <p>I’d love to work somewhere that is all-in on Elixir and the BEAM (Erlang
virtual machine), or is moving that direction. While I’m open to other
technology stacks, I’ve really enjoyed working in Elixir and would love to be
able to continue to take advantage of what it offers.</p>
  </li>
  <li>
    <p>I’m not focused on any single industry or business domain, but I want to work
on things that are designed to serve people and not enslave them.</p>
  </li>
  <li>
    <p>I prefer to work remotely. I’m open to some travel for in-person
meetings/work.</p>
  </li>
</ul>

<p>If you know of any opportunities that match these criteria, please <a href="https://randycoulman.com/contact/">get in
touch</a>. You can find more details about my work on <a href="https://www.linkedin.com/in/randycoulman/">my LinkedIn
profile</a>.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Mix test.interactive</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2024/10/16/mix-test-interactive/"/>
    
    <id>/blog/2024/10/16/mix-test-interactive</id>
    <published>2024-10-16T07:24:28-07:00</published>
    <updated>2024-10-16T07:24:28-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p><a href="https://hexdocs.pm/mix_test_interactive/readme.html"><code class="highlighter-rouge">mix test.interactive</code></a> is
an interactive test runner for Elixir’s <code class="highlighter-rouge">ExUnit</code>. It automatically runs your
tests using <code class="highlighter-rouge">mix test</code> whenever you save a change to your code or tests and
allows you to interactively modify the arguments passed to <code class="highlighter-rouge">mix test</code>.</p>

<p>While I released the initial version of this project almost four years ago, I’ve
never written about it or publicized it, other than a <a href="https://randycoulman.com/blog/2021/10/11/elixir-mix-podcast/">podcast
appearance</a>.</p>

<h2 id="background">Background</h2>

<p>While doing test-driven development in a number of languages, I’ve come to
appreciate a workflow where my tests run automatically every time I save changes
to my source code or tests. I even open-sourced an <a href="https://randycoulman.com/blog/2013/04/10/sunittools-autotest-run-visualworks-tests-automatically/">automatic test runner for
Smalltalk</a>
when I was working in that language.</p>

<p>When I started working in Elixir, I quickly found and adopted Louis Pilfold’s
<a href="https://github.com/lpil/mix-test.watch">mix test.watch</a>. This was (and still
is) a wonderful tool that largely gave me the workflow I’d become used to.</p>

<p>I later started working on some JavaScript projects where we used
<a href="https://jestjs.io/">Jest</a>.</p>

<p>One of Jest’s features is an interactive watch mode, where Jest stays running
and re-runs tests on every change, much like <code class="highlighter-rouge">mix test.watch</code>. However, it also
provides a number of commands that can interactively modify which tests will be
run.</p>

<p>I found this feature of Jest very handy, and realized that I often wanted to
change the arguments I was passing to <code class="highlighter-rouge">mix test.watch</code>. I’d then have to exit it
and restart it with the new arguments. Or, I’d run <code class="highlighter-rouge">mix test</code> separately in
another shell when I needed different arguments.</p>

<p>After I spent some time wishing quietly that someone would build a Jest-like
interactive test runner based on <code class="highlighter-rouge">mix test.watch</code>, I realized that it probably
wasn’t going to happen unless I did it.</p>

<p>So, back in late 2020/early 2021 I started experimenting with the idea. Once I
had the basics working, I asked Louis if he’d like me to contribute this back to
<code class="highlighter-rouge">mix test.watch</code>. He’s been busy building
<a href="https://github.com/gleam-lang/gleam/">Gleam</a>, so <a href="https://github.com/lpil/mix-test.watch/issues/115">he
suggested</a> that I should keep
our projects separate. I did just that, releasing <code class="highlighter-rouge">mix test.interactive</code> v1.0 in
February, 2021.</p>

<h2 id="the-basics">The Basics</h2>

<p>When using <code class="highlighter-rouge">mix test.interactive</code>, you’ll run it from a command line, optionally
passing some arguments to it. It will stay running until you quit it (with the
<code class="highlighter-rouge">q</code> command, <code class="highlighter-rouge">Ctrl-D</code>, or the ever-popular <a href="https://randycoulman.com/blog/2023/12/19/republish-between-the-ctrl-cs/"><code class="highlighter-rouge">Ctrl-C
Ctrl-C</code></a>).</p>

<p>While running, it watches for changes to your source code and re-runs the tests
when it detects a change. So far, this is the same as <code class="highlighter-rouge">mix test.watch</code>.</p>

<p><code class="highlighter-rouge">mix test.interative</code> also allows you to enter commands that change what
arguments will be passed to <code class="highlighter-rouge">mix test</code>.</p>

<p>Internally, <code class="highlighter-rouge">mix test.interactive</code> keeps track of a number of settings which
are used to construct a command-line for <code class="highlighter-rouge">mix test</code>. These settings are updated
every time an interactive-mode command is entered.</p>

<h3 id="examples">Examples</h3>

<p>If my test suite is very fast, I’m usually fine with running all of my tests
whenever anything changes. This is the default mode of <code class="highlighter-rouge">mix test.interactive</code>.</p>

<p>If I want even faster feedback, I might only want to run stale tests; that is,
only tests affected by code/test changes made since the tests last passed. For
this, I can use the <code class="highlighter-rouge">s</code> command to run only the stale tests, which runs <code class="highlighter-rouge">mix
test --stale</code> under the hood.</p>

<p>In a larger application, I might only want to run tests matching a filename
pattern. For example, if I’m working in my application’s <code class="highlighter-rouge">Accounts</code> context, I
can use the <code class="highlighter-rouge">p accounts</code> command to run only those tests whose filenames contain
the substring (pattern) <code class="highlighter-rouge">accounts</code>.</p>

<p>Perhaps I’ve just made a fundamental change to my application that caused a
number of tests to fail. I’d like to keep re-running the failed tests until I
can get them all passing again. For that, I can use the <code class="highlighter-rouge">f</code> command, which runs
<code class="highlighter-rouge">mix test --failed</code> under the hood.</p>

<p>I can switch back to running all of the tests again with the <code class="highlighter-rouge">a</code> command.</p>

<p>Maybe I want to run a single test at a time, but change which test I’m focused
on at any moment. I could add <code class="highlighter-rouge">@tag :focus</code> above the test I’m interested in and
then use the <code class="highlighter-rouge">o focus</code> command, which will run <code class="highlighter-rouge">mix test --only focus</code>. I can
then move the <code class="highlighter-rouge">@tag :focus</code> line to a different test to run that test instead.</p>

<p>If I’m making a number of changes and don’t want to run the tests while making
them, I can turn watch mode off with the <code class="highlighter-rouge">w</code> command, make the changes, and then
press <code class="highlighter-rouge">Enter</code> or turn watch mode back on (<code class="highlighter-rouge">w</code> command again) to run the tests.</p>

<h2 id="current-status">Current Status</h2>

<p>As I mentioned, I released the first version of <code class="highlighter-rouge">mix test.interactive</code> in
February of 2021 and I’ve been enhancing it off and on since then. I use it
on every Elixir project I work on. That doesn’t mean it’s perfect, but at
this point, it’s got all of the features I can think to add to it.</p>

<p>It can manage the following <code class="highlighter-rouge">mix test</code> options via interactive-mode commands:</p>

<ul>
  <li><code class="highlighter-rouge">--failed</code> (<code class="highlighter-rouge">f</code> command)</li>
  <li><code class="highlighter-rouge">--exclude &lt;tag&gt;</code> (<code class="highlighter-rouge">x</code> command)</li>
  <li><code class="highlighter-rouge">--include &lt;tag&gt;</code> (<code class="highlighter-rouge">i</code> command)</li>
  <li><code class="highlighter-rouge">--max-failures &lt;count&gt;</code> (<code class="highlighter-rouge">m</code> command)</li>
  <li><code class="highlighter-rouge">--only &lt;tag&gt;</code> (<code class="highlighter-rouge">o</code> command)</li>
  <li><code class="highlighter-rouge">--repeat-until-failure &lt;count&gt;</code> (<code class="highlighter-rouge">r</code> command) (Elixir 1.17.0 and later)</li>
  <li><code class="highlighter-rouge">--seed &lt;seed&gt;</code> (<code class="highlighter-rouge">d</code> command)</li>
  <li><code class="highlighter-rouge">--stale</code> (<code class="highlighter-rouge">s</code> command)</li>
  <li><code class="highlighter-rouge">--trace</code> (<code class="highlighter-rouge">t</code> command)</li>
  <li><code class="highlighter-rouge">&lt;filename&gt; or &lt;filename:line_no&gt;</code> arguments (<code class="highlighter-rouge">p</code> command)</li>
</ul>

<p>I’m happy to consider additional feature requests or bug reports.</p>

<h2 id="wish-list">Wish List</h2>

<p>There are two things I’d love to change in <code class="highlighter-rouge">mix test.interactive</code>, but haven’t
been able to figure out how yet.</p>

<h3 id="immediate-response">Immediate Response</h3>

<p>Jest works by immediately processing keystrokes, so there is no need to press
<code class="highlighter-rouge">Enter</code> after specifying a command.</p>

<p>As near as I can tell, Elixir (and, under the hood, Erlang) do not support
immediate input mode out of the box (the equivalent of the C <code class="highlighter-rouge">getc</code>/<code class="highlighter-rouge">getchar</code>
functions).</p>

<p>One suggestion I saw was to use an Elixir wrapper of the <code class="highlighter-rouge">ncurses</code> library, but
I’m reluctant to add such a dependency because I’m not sure how well it would
work on all platforms, including Windows.</p>

<p>If anyone knows how to do this, I’d love some pointers!</p>

<h3 id="tab-completion-for-p-command">Tab-completion for <code class="highlighter-rouge">p</code> Command</h3>

<p>I’d love to allow tab-completion of arguments to the <code class="highlighter-rouge">p</code> command.</p>

<p>From the documentation, I see that Erlang’s <code class="highlighter-rouge">:io</code> module has an <code class="highlighter-rouge">expand_fun</code>
option that can be set that is supposed to be active when calling
<code class="highlighter-rouge">:io.get_line</code>, but I’ve unable to make it work in <code class="highlighter-rouge">mix test.interactive</code>.</p>

<p>Again, any pointers on how to accomplish this would be most welcome!</p>

<h2 id="wrapping-up">Wrapping Up</h2>

<p>If you think the <code class="highlighter-rouge">mix test.interactive</code> approach would work for you, I’d love it
if you give this tool a try. It doesn’t interfere with anyone else’s workflow,
so it is safe to add to any project for those that want to use it, while staying
out of the way of anyone that doesn’t. Check it out on
<a href="https://hex.pm/packages/mix_test_interactive">hex.pm</a>!</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Starting at Mechanical Orchard</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2024/01/02/starting-at-mechanical-orchard/"/>
    
    <id>/blog/2024/01/02/starting-at-mechanical-orchard</id>
    <published>2024-01-02T07:30:22-08:00</published>
    <updated>2024-01-02T07:30:22-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>Today I start my new job as a Lead Software Engineer at <a href="https://www.mechanical-orchard.com/">Mechanical
Orchard</a>.</p>

<p>As I <a href="https://randycoulman.com/blog/2023/12/04/back-on-the-market/">posted last month</a>, <a href="https://sequin.io">Sequin</a> decided to transition
to 100% in-person based in San Francisco. I’m not able to make that move, so I
started looking for a new position and <a href="https://randycoulman.com/blog/2023/12/14/the-search-is-over/">found it very quickly</a>.</p>

<p>Mechanical Orchard works with large organizations to help modernize their older
mainframe applications by replicating them into the cloud. I expect to work
on some really interesting problems in domains I haven’t seen before, so I’ll
get to learn a ton!</p>

<p>I’m looking forward to getting to know my new co-workers and seeing what we can
build together.</p>

<p>Once again, I really appreciate all of you who reached out with opportunities
and encouragement. I had a number of interesting positions to consider, and
that’s largely thanks to your suggestions.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Republish: GenServer.reply: Don't Call Us, We'll Call You</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2023/12/27/republish-genserver-reply-dont-call-us-well-call-you/"/>
    
    <id>/blog/2023/12/27/republish-genserver-reply-dont-call-us-well-call-you</id>
    <published>2023-12-27T08:47:58-08:00</published>
    <updated>2023-12-27T08:47:58-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>Let’s look at how we can use <code class="highlighter-rouge">:noreply</code> and <code class="highlighter-rouge">GenServer.reply</code> to allow a
GenServer to continue working even while its <code class="highlighter-rouge">call</code>ers wait for the result of
long-running operations.</p>

<p><em>I originally published this article on the <a href="https://blog.sequin.io/genserver-reply-dont-call-us-well-call-you/">Sequin blog</a>.
Republishing here with permission.</em></p>

<p>GenServers are one of the core abstractions provided by the OTP library that both Erlang and Elixir share. A GenServer (generic server) is a separate process that maintains state and provides a way to run code asynchronously.</p>

<p>This article assumes some familiarity with GenServers and how to implement them. If you don’t have that background knowledge, start with the <a href="https://elixir-lang.org/getting-started/mix-otp/genserver.html">GenServer guide</a> and <a href="https://hexdocs.pm/elixir/GenServer.html">documentation</a>.</p>

<p>Conceptually, a GenServer process has a “mailbox” – a queue of messages that it needs to process. It processes one message fully before moving on to the next. If the handling of a message does something that takes a long time, the GenServer will not process any further messages until the long operation completes.</p>

<p>Every introductory tutorial about GenServers talks about the two main ways of interacting with a GenServer: <code class="highlighter-rouge">call</code> and <code class="highlighter-rouge">cast</code>. Briefly: <code class="highlighter-rouge">call</code> is used to send a message to a GenServer and wait for its response before moving on. <code class="highlighter-rouge">cast</code> is used to send a message to a GenServer without waiting for a reply.</p>

<p>One way to think about this is that, with <code class="highlighter-rouge">call</code>, both the caller and the GenServer are “blocked” while the message is being handled. The caller waits for the reply, and the GenServer is busy handing the call and not processing any other messages. With <code class="highlighter-rouge">cast</code>, only the GenServer is blocked. The caller continues on, while the GenServer stays busy handling the cast and not processing any other messages.</p>

<p>This might be OK if the GenServer is a “worker” that doesn’t need to respond to additional messages while it’s doing its job. But if the GenServer needs to handle messages from multiple clients, we don’t want it to become unresponsive while the work is happening. If it does, the GenServer can become a bottleneck in the system and cause significant performance problems.</p>

<p>In that case, we want the caller to wait for a reply from the GenServer, but we want the GenServer to be able to process additional messages while a long operation is running. For example, perhaps the GenServer manages a cache of values that take time to compute. If a request comes in for a value that’s not in the cache, the caller should wait for the computation to finish, but other callers should still be able to request already-cached values without having to wait for the unrelated computation to finish.</p>

<p>GenServer has a built-in mechanism to support this pattern. We can return a <code class="highlighter-rouge"><span class="p">{</span><span class="err">:noreply,</span><span class="w"> </span><span class="err">...</span><span class="p">}</span></code> tuple from its <code class="highlighter-rouge">handle_call</code> callback and then later use <code class="highlighter-rouge">GenServer.reply</code> to reply to the caller.</p>

<p>Let’s look at an example to see how this works.</p>

<h2 id="common-usage-with-reply">Common usage with :reply</h2>

<p>We’ll start with a simple GenServer that uses <code class="highlighter-rouge">Process.sleep</code> to simulate a slow operation.</p>

<div class="language-elixir highlighter-rouge"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">ReplyExample</span><span class="o">.</span><span class="no">Server</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">GenServer</span>

  <span class="nv">@timeout</span> <span class="ss">:timer</span><span class="o">.</span><span class="n">seconds</span><span class="p">(</span><span class="m">30</span><span class="p">)</span>

  <span class="k">def</span> <span class="n">start_link</span><span class="p">(</span><span class="n">opts</span> <span class="p">\\</span> <span class="p">[])</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">start_link</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="n">opts</span><span class="p">,</span> <span class="ss">name:</span> <span class="bp">__MODULE__</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">do_the_thing</span><span class="p">(</span><span class="n">pid</span> <span class="p">\\</span> <span class="bp">__MODULE__</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="p">{</span><span class="ss">:do_the_thing</span><span class="p">,</span> <span class="n">n</span><span class="p">},</span> <span class="nv">@timeout</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="nv">@impl</span> <span class="no">GenServer</span>
  <span class="k">def</span> <span class="n">init</span><span class="p">(</span><span class="n">_opts</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="p">%{}}</span>
  <span class="k">end</span>

  <span class="nv">@impl</span> <span class="no">GenServer</span>
  <span class="k">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:do_the_thing</span><span class="p">,</span> <span class="n">n</span><span class="p">},</span> <span class="n">_from</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">log</span><span class="p">(</span><span class="sd">"</span><span class="s2">Sleeping for 2 seconds..."</span><span class="p">)</span>
    <span class="no">Process</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="m">2000</span><span class="p">)</span>

    <span class="p">{</span><span class="ss">:reply</span><span class="p">,</span> <span class="n">n</span> <span class="o">*</span> <span class="m">1000</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="k">defp</span> <span class="n">log</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">now</span> <span class="o">=</span> <span class="no">DateTime</span><span class="o">.</span><span class="n">utc_now</span><span class="p">()</span> <span class="o">|&gt;</span> <span class="no">DateTime</span><span class="o">.</span><span class="n">truncate</span><span class="p">(</span><span class="ss">:second</span><span class="p">)</span>
    <span class="no">IO</span><span class="o">.</span><span class="n">puts</span><span class="p">(</span><span class="sd">"</span><span class="si">#{</span><span class="n">now</span><span class="si">}</span><span class="s2">: </span><span class="si">#{</span><span class="n">message</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">test</span> <span class="k">do</span>
    <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">pid</span><span class="p">}</span> <span class="o">=</span> <span class="n">start_link</span><span class="p">()</span>

    <span class="k">try</span> <span class="k">do</span>
      <span class="m">1</span><span class="o">..</span><span class="m">5</span>
      <span class="o">|&gt;</span> <span class="no">Enum</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="k">fn</span> <span class="n">n</span> <span class="o">-&gt;</span> <span class="no">Task</span><span class="o">.</span><span class="n">async</span><span class="p">(</span><span class="k">fn</span> <span class="o">-&gt;</span> <span class="n">do_the_thing</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">end</span><span class="p">)</span> <span class="k">end</span><span class="p">)</span>
      <span class="o">|&gt;</span> <span class="no">Task</span><span class="o">.</span><span class="n">await_many</span><span class="p">(</span><span class="nv">@timeout</span><span class="p">)</span>
      <span class="o">|&gt;</span> <span class="n">inspect</span><span class="p">()</span>
      <span class="o">|&gt;</span> <span class="n">log</span><span class="p">()</span>
    <span class="k">after</span>
      <span class="no">GenServer</span><span class="o">.</span><span class="n">stop</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre>
</div>

<p>This is a pretty simple GenServer. It has a single function, <code class="highlighter-rouge">do_the_thing</code>. When invoked, the caller will wait for a response which will come after a two second delay.</p>

<p>In IEx, I can use the <code class="highlighter-rouge">test</code> function to start up five tasks, each calling <code class="highlighter-rouge">do_the_thing</code>, and then wait for all of them to complete.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>iex(7)&gt; ReplyExample.Server.test()
2023-07-28 16:36:26Z: Sleeping for 2 seconds...
2023-07-28 16:36:28Z: Sleeping for 2 seconds...
2023-07-28 16:36:30Z: Sleeping for 2 seconds...
2023-07-28 16:36:32Z: Sleeping for 2 seconds...
2023-07-28 16:36:34Z: Sleeping for 2 seconds...
2023-07-28 16:36:36Z: [1000, 2000, 3000, 4000, 5000]
:ok
</code></pre>
</div>

<p>Notice the timestamps. Each request is processed only after the previous one has completed. In order for this to complete successfully, I’ve had to explicitly add a long enough timeout to both the <code class="highlighter-rouge">GenServer.call</code> and the <code class="highlighter-rouge">Task.await_many</code> calls. Otherwise, one or more of the <code class="highlighter-rouge">GenServer.call</code>s would have timed out after the default five seconds.</p>

<p>With this approach, you can imagine a busy GenServer becoming a bottleneck in the system with numerous processes queued up waiting for their turn.</p>

<h2 id="using-noreply-and-genserverreply">Using :noreply and GenServer.reply</h2>

<p>Let’s refactor this code to move the long-running operation into a separate task. We can then use <code class="highlighter-rouge">:noreply</code> and <code class="highlighter-rouge">GenServer.reply</code> to allow the GenServer to continue processing other messages in the mean time.</p>

<div class="language-elixir highlighter-rouge"><pre class="highlight"><code><span class="k">defmodule</span> <span class="no">ReplyExample</span><span class="o">.</span><span class="no">Server</span> <span class="k">do</span>
  <span class="kn">use</span> <span class="no">GenServer</span>

  <span class="k">def</span> <span class="n">start_link</span><span class="p">(</span><span class="n">opts</span> <span class="p">\\</span> <span class="p">[])</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">start_link</span><span class="p">(</span><span class="bp">__MODULE__</span><span class="p">,</span> <span class="n">opts</span><span class="p">,</span> <span class="ss">name:</span> <span class="bp">__MODULE__</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">do_the_thing</span><span class="p">(</span><span class="n">pid</span> <span class="p">\\</span> <span class="bp">__MODULE__</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="k">do</span>
    <span class="no">GenServer</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="p">{</span><span class="ss">:do_the_thing</span><span class="p">,</span> <span class="n">n</span><span class="p">})</span>
  <span class="k">end</span>

  <span class="nv">@impl</span> <span class="no">GenServer</span>
  <span class="k">def</span> <span class="n">init</span><span class="p">(</span><span class="n">_opts</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="p">%{}}</span>
  <span class="k">end</span>

  <span class="nv">@impl</span> <span class="no">GenServer</span>
  <span class="k">def</span> <span class="n">handle_call</span><span class="p">({</span><span class="ss">:do_the_thing</span><span class="p">,</span> <span class="n">n</span><span class="p">},</span> <span class="n">from</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="no">Task</span><span class="o">.</span><span class="n">async</span><span class="p">(</span><span class="k">fn</span> <span class="o">-&gt;</span>
      <span class="n">log</span><span class="p">(</span><span class="sd">"</span><span class="s2">Sleeping for 2 seconds..."</span><span class="p">)</span>
      <span class="no">Process</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="m">2000</span><span class="p">)</span>

      <span class="no">GenServer</span><span class="o">.</span><span class="n">reply</span><span class="p">(</span><span class="n">from</span><span class="p">,</span> <span class="n">n</span> <span class="o">*</span> <span class="m">1000</span><span class="p">)</span>
    <span class="k">end</span><span class="p">)</span>

    <span class="p">{</span><span class="ss">:noreply</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="nv">@impl</span> <span class="no">GenServer</span>
  <span class="k">def</span> <span class="n">handle_info</span><span class="p">(</span><span class="n">_msg</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
    <span class="p">{</span><span class="ss">:noreply</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span>
  <span class="k">end</span>

  <span class="k">defp</span> <span class="n">log</span><span class="p">(</span><span class="n">message</span><span class="p">)</span> <span class="k">do</span>
    <span class="n">now</span> <span class="o">=</span> <span class="no">DateTime</span><span class="o">.</span><span class="n">utc_now</span><span class="p">()</span> <span class="o">|&gt;</span> <span class="no">DateTime</span><span class="o">.</span><span class="n">truncate</span><span class="p">(</span><span class="ss">:second</span><span class="p">)</span>
    <span class="no">IO</span><span class="o">.</span><span class="n">puts</span><span class="p">(</span><span class="sd">"</span><span class="si">#{</span><span class="n">now</span><span class="si">}</span><span class="s2">: </span><span class="si">#{</span><span class="n">message</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="n">test</span> <span class="k">do</span>
    <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">pid</span><span class="p">}</span> <span class="o">=</span> <span class="n">start_link</span><span class="p">()</span>

    <span class="k">try</span> <span class="k">do</span>
      <span class="m">1</span><span class="o">..</span><span class="m">5</span>
      <span class="o">|&gt;</span> <span class="no">Enum</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="k">fn</span> <span class="n">n</span> <span class="o">-&gt;</span> <span class="no">Task</span><span class="o">.</span><span class="n">async</span><span class="p">(</span><span class="k">fn</span> <span class="o">-&gt;</span> <span class="n">do_the_thing</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">end</span><span class="p">)</span> <span class="k">end</span><span class="p">)</span>
      <span class="o">|&gt;</span> <span class="no">Task</span><span class="o">.</span><span class="n">await_many</span><span class="p">()</span>
      <span class="o">|&gt;</span> <span class="n">inspect</span><span class="p">()</span>
      <span class="o">|&gt;</span> <span class="n">log</span><span class="p">()</span>
    <span class="k">after</span>
      <span class="no">GenServer</span><span class="o">.</span><span class="n">stop</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre>
</div>

<p>The significant changes from the previous version are in the <code class="highlighter-rouge">handle_call</code> callback, plus the addition of a <code class="highlighter-rouge">handle_info</code> callback <sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup>.</p>

<p>In <code class="highlighter-rouge">handle_call</code>, the code is almost identical, but has been moved into an anonymous function that is passed to <code class="highlighter-rouge">Task.async</code>. There are other ways to do this, but <code class="highlighter-rouge">Task.async</code> is a great fit for this situation <sup id="fnref:2"><a href="#fn:2" class="footnote">2</a></sup>.</p>

<p>After spawning the task, <code class="highlighter-rouge">handle_call</code> immediately returns <code class="highlighter-rouge"><span class="p">{</span><span class="err">:noreply,</span><span class="w"> </span><span class="err">state</span><span class="p">}</span></code>. That allows the GenServer to move on to the next message in its mailbox while the caller stays blocked waiting for the reply.</p>

<p>At the end of the task, rather than returning a result, the anonymous function calls <code class="highlighter-rouge">GenServer.reply</code>, passing the address of the original caller (the <code class="highlighter-rouge">from</code> parameter) and the actual reply. <code class="highlighter-rouge">GenServer.reply</code> is what returns the result to the caller, unblocking it.</p>

<p>If you’ve written <code class="highlighter-rouge">handle_call</code> callbacks before, you have probably always ignored the <code class="highlighter-rouge">from</code> parameter because it’s normally not used. But in this case, <code class="highlighter-rouge">from</code> becomes very useful because we can use it to reply to the correct caller.</p>

<p>With these changes, we can again test our GenServer and see the results:</p>
<div class="highlighter-rouge"><pre class="highlight"><code>iex(4)&gt; ReplyExample.Server.test()
2023-07-28 16:42:30Z: Sleeping for 2 seconds...
2023-07-28 16:42:30Z: Sleeping for 2 seconds...
2023-07-28 16:42:30Z: Sleeping for 2 seconds...
2023-07-28 16:42:30Z: Sleeping for 2 seconds...
2023-07-28 16:42:30Z: Sleeping for 2 seconds...
2023-07-28 16:42:32Z: [1000, 2000, 3000, 4000, 5000]
:ok
</code></pre>
</div>

<p>Notice the timestamps again. This time, all of the <code class="highlighter-rouge">Sleeping for...</code> messages happen within the same second and the final response comes in after 2 seconds. This shows that the GenServer keeps processing messages even though all of the callers are blocked waiting for their replies! And the overall test runs much faster because we’ve been able to run the long operations concurrently.</p>

<p>Because the GenServer stays unblocked, we no longer need to add the long timeouts. Here, I’ve eliminated them entirely, falling back to the default of five seconds.</p>

<h2 id="wrapping-up">Wrapping Up</h2>

<p><code class="highlighter-rouge">:noreply</code> and <code class="highlighter-rouge">GenServer.reply</code> give you a way to keep a GenServer from becoming a bottleneck in your system even when callers need to wait for the result of a slow operation. Taking advantage of these tools requires only a relatively simple change to your code.</p>
<div class="footnotes">
  <ol>
    <li id="fn:1">
      <p>When using <code class="highlighter-rouge">Task.async</code>, the processes are linked and the Task will send messages back to the GenServer. In order to handle those (and do nothing in this case), I’ve added the <code class="highlighter-rouge">handle_info</code> callback which is where those messages are handled. See the <a href="https://hexdocs.pm/elixir/Task.html#await/2-compatibility-with-otp-behaviours">Task docs</a> for more information. <a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>The <a href="https://hexdocs.pm/elixir/GenServer.html#c:handle_call/3">GenServer docs</a> contain some very useful information about managing the lifecycle of the Task to keep the caller from blocking indefinitely. To keep things simple, I haven’t included any explicit code here to implement that. <a href="#fnref:2" class="reversefootnote">&#8617;</a></p>
    </li>
  </ol>
</div>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Republish: Between the Ctrl-C's</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2023/12/19/republish-between-the-ctrl-cs/"/>
    
    <id>/blog/2023/12/19/republish-between-the-ctrl-cs</id>
    <published>2023-12-19T07:11:18-08:00</published>
    <updated>2023-12-19T07:11:18-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>This article is about a regularly overlooked, but helpful feature in Elixir: the
BREAK menu. We even explore the lesser-known commands and give suggestions for
when to use them.</p>

<p><em>I originally published this article on the <a href="https://blog.sequin.io/between-the-ctrl-cs/">Sequin blog</a>.
Republishing here with permission.</em></p>

<p>One of Elixir’s best features is its REPL, IEx (interactive Elixir.) The <code class="highlighter-rouge">iex</code>
command spawns a shell that allows you to run Elixir code interactively.</p>

<p>To exit IEx, you normally press Ctrl-C twice. If you’ve done this before, you
may have noticed an interesting menu pop up between the Ctrl-Cs:</p>

<div class="highlighter-rouge"><pre class="highlight"><code>BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
</code></pre>
</div>

<p>What’s that about? What do all of those options do?</p>

<p>This menu is known as <a href="https://hexdocs.pm/iex/IEx.html#module-the-break-menu">the BREAK
menu</a> and it allows you
to interact with the running Elixir session in various ways.</p>

<p>The BREAK menu is part of the Erlang Virtual Machine (commonly known as the
BEAM), so these options are also available when running Erlang applications and
shells.</p>

<p>The BREAK menu is available when:</p>
<ul>
  <li>Running <code class="highlighter-rouge">iex</code></li>
  <li>Running an application locally (e.g. <code class="highlighter-rouge">mix phx.server</code> or <code class="highlighter-rouge">iex -S mix</code>)</li>
  <li>Connecting IEx to a remote application (e.g. <code class="highlighter-rouge">iex --sname local --remsh
app@host</code>)</li>
</ul>

<p>In the latter case, all of the menu options in the BREAK menu apply only to your
local IEx session and not to the remote application. In some cases this is a
good thing, as you probably don’t want to accidentally shut down the running
application.</p>

<p>Here’s a quick summary of these commands (and some additional undocumented
commands). We’ll look at each of these in more detail in the following sections.</p>

<table>
  <thead>
    <tr>
      <th>Command</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>(a)bort</td>
      <td>Close the current shell</td>
    </tr>
    <tr>
      <td>(A)bort with dump</td>
      <td>Close the current shell AND create a BEAM crash dump file</td>
    </tr>
    <tr>
      <td>(c)ontinue</td>
      <td>Return to the running application or IEx shell</td>
    </tr>
    <tr>
      <td>(q)uit</td>
      <td>Close the current shell</td>
    </tr>
    <tr>
      <td>(v)ersion</td>
      <td>Print the current BEAM version</td>
    </tr>
    <tr>
      <td>(k)ill</td>
      <td>Interactively kill one or more running processes</td>
    </tr>
    <tr>
      <td>(D)b-tables</td>
      <td>List ETS tables</td>
    </tr>
    <tr>
      <td>(d)istribution</td>
      <td>List nodes for a distributed application</td>
    </tr>
    <tr>
      <td>(i)nfo</td>
      <td>Print memory and allocator information</td>
    </tr>
    <tr>
      <td>(l)oaded</td>
      <td>List loaded modules</td>
    </tr>
    <tr>
      <td>p(o)rt info</td>
      <td>List open ports</td>
    </tr>
    <tr>
      <td>(p)roc info</td>
      <td>List running processes and open ports</td>
    </tr>
  </tbody>
</table>

<blockquote>
  <p>If you want to see how these are implemented, you can look at <a href="https://github.com/erlang/otp/blob/master/erts/emulator/beam/break.c">the C source
code</a> in
the BEAM.</p>
</blockquote>

<h2 id="simple-commands">Simple Commands</h2>

<p>A number of the BREAK menu options are simple commands for interacting with the
running shell.</p>

<h3 id="abort">(a)bort</h3>

<p>The <code class="highlighter-rouge">a</code> command does the same thing that hitting the second <code class="highlighter-rouge">Ctrl-C</code> does: it
closes the current shell.</p>

<p>If you’re running IEx normally, it will close the session and any application
running in it.</p>

<p>If you’re running your application directly (e.g. <code class="highlighter-rouge">mix phx.server</code>), it will
shut down your application.</p>

<p>If you’re in a remote IEx session connected to a running application, it only
closes your IEx session, but leaves the remote application alone.</p>

<h3 id="abort-with-dump">(A)bort with dump</h3>

<p>This is the same as <code class="highlighter-rouge">(a)bort</code>, but also produces a BEAM crash dump file
(<code class="highlighter-rouge">erl_crash.dump</code>).</p>

<p>Looking through long pages of information in an interactive shell on a remote
system can often be quite difficult. In that case, producing a crash dump file
that you can examine on your local workstation might make things easier.</p>

<p>See <a href="https://www.erlang.org/doc/apps/erts/crash_dump.html">the Erlang
documentation</a> for more
information on interpreting and working with crash dump files.</p>

<h3 id="continue">(c)ontinue</h3>

<p>Exits the BREAK menu and returns to your application or shell session.</p>

<p>This is the command to remember when you hit <code class="highlighter-rouge">Ctrl-C</code> by accident or change your
mind.</p>

<h3 id="quit">(q)uit</h3>

<p>The <code class="highlighter-rouge">q</code> command is not listed in the BREAK menu, but is supported. It is exactly
the same as the <code class="highlighter-rouge">a</code> command.</p>

<h3 id="version">(v)ersion</h3>

<p>Prints the current BEAM version.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)&gt;
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
v
Erlang (BEAM) emulator version 12.3.2.6
</code></pre>
</div>

<p>This shows you the current Erlang Runtime System (ERTS) version and not the OTP
version.</p>

<h2 id="informational-options">Informational Options</h2>

<p>A number of the options in the BREAK menu will provide information about the
running Erlang VM.</p>

<p>In general, it’s easier to see this information by running either
<a href="https://www.erlang.org/doc/apps/observer/observer_ug.html">Observer</a> or
<a href="https://hexdocs.pm/observer_cli/">observer_cli</a>. That’s what <a href="https://blog.sequin.io/how-we-used-elixirs-observer-to-hunt-down-bottlenecks/">we normally
use</a>.
But if you don’t have those tools available, the BREAK menu is always available.</p>

<p>As I mentioned above, these commands all print information about your local IEx
session even when you’ve opened a remote shell to a running application.</p>

<p>If you’re in a normal IEx session or are running your application locally,
that’s perfect.</p>

<p>But for a remote shell to a running application, you’re probably more interested
in seeing this information for that application instead. There doesn’t seem to
be a way to make the BREAK menu display information for the remote application,
so you’ll have to rely on using Observer or observer_cli instead.</p>

<p>Let’s look at the commands that are available.</p>

<h3 id="db-tables">(D)b-tables</h3>

<p>Prints a list of <a href="https://www.erlang.org/doc/man/ets.html">ETS</a> tables along
with some information about each one.</p>

<p>This can help you find a particular table, see how it’s been configured, and see
how big it is.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)&gt;
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
D
=ets:&lt;0.42.0&gt;
Slot: 4710072768
Table: logger
Name: logger
Buckets: 256
Chain Length Avg: 0.011719
Chain Length Max: 1
Chain Length Min: 0
Chain Length Std Dev: 0.107617
Chain Length Expected Std Dev: 0.108042
Fixed: false
9: [{{'$handler_config$','Elixir.Logger'},#{config=&gt;#{counter=&gt;{atomics,#Ref&lt;0.2287420997.2752643074.39926&gt;},sasl=&gt;false,thresholds=&gt;{20,500},translators=&gt;[{'Elixir.Logger.Translator',translate}],truncate=&gt;8096,utc_log=&gt;false},filter_default=&gt;log,filters=&gt;[],formatter=&gt;{logger_formatter,#{}},id=&gt;'Elixir.Logger',level=&gt;all,module=&gt;'Elixir.Logger.Handler'}}]
84: [{'$primary_config$',#{filter_default=&gt;log,filters=&gt;[{process_level,{fun 'Elixir.Logger.Filter':process_level/2,[]}}],handlers=&gt;['Elixir.Logger'],level=&gt;debug,metadata=&gt;#{}}}]
116: [{'$proxy_config$',#{burst_limit_enable=&gt;false,burst_limit_max_count=&gt;500,burst_limit_window_time=&gt;1000,drop_mode_qlen=&gt;1000,flush_qlen=&gt;5000,overload_kill_enable=&gt;false,overload_kill_mem_size=&gt;3000000,overload_kill_qlen=&gt;20000,overload_kill_restart_after=&gt;5000,sync_mode_qlen=&gt;500}}]
Objects: 3
Words: 7709
Type: set
Protection: protected
Compressed: false
Write Concurrency: true
Read Concurrency: true

...
</code></pre>
</div>

<h3 id="distribution">(d)istribution</h3>

<p>Prints information about the current node and other nodes it is connected to.</p>

<p>This command shows you information about all of the nodes in your distributed
Elixir/Erlang application, which can be helpful when trying to debug connection
problems.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)&gt;
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
d
=node:'nonode@nohost'
=no_distribution
</code></pre>
</div>

<h3 id="info">(i)nfo</h3>

<p>Prints information about memory usage and allocation.</p>

<p>This command produces a large volume of information about memory usage and can
be helpful in figuring out where a memory leak might be helpful.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)&gt;
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
i
=memory
total: 34928033
processes: 5723312
processes_used: 5723312
system: 29204721
atom: 336049
atom_used: 331018
binary: 25520
code: 7495815
ets: 537960
=hash_table:atom_tab
size: 8192
used: 6389
objs: 12508
depth: 9
=index_table:atom_tab
size: 13312
limit: 1048576
entries: 12509
=hash_table:module_code
size: 128
used: 103
objs: 174
depth: 5
=index_table:module_code
size: 1024
limit: 65536
entries: 174

...
</code></pre>
</div>

<h3 id="loaded">(l)oaded</h3>

<p>Prints a list of loaded modules and their size.</p>

<p>This can be handy for checking that all of the code is available that you
thought should be there.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)&gt;
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
l
Current code: 7737441
Old code: 0
erts_code_purger 13536
erl_init 2520
init 63188
prim_buffer 4984
prim_eval 1352
prim_inet 111589
prim_file 41674
zlib 20584
socket_registry 22408
prim_socket 51960
prim_net 10840
prim_zip 24120
erl_prim_loader 56864
erlang 97012
erts_internal 22920
erl_tracer 1680
erts_literal_area_collector 4928
erts_dirty_process_signal_handler 2352
atomics 3464
counters 4176
persistent_term 1456

...
</code></pre>
</div>

<h3 id="port-info">p(o)rt info</h3>

<p>This is not listed in the BREAK menu, but does appear in the source code. It
prints a list of open ports (identical to what’s included at the end of the <code class="highlighter-rouge">p</code>
command’s output).</p>

<p>According to the <a href="https://www.erlang.org/doc/reference_manual/ports.html">Erlang
documentation</a>, ports
provide the basic mechanism for communication with the external world, from
Erlang’s point of view. An open port will represent a connection from the Erlang
VM to another process running in the host operating system.</p>

<p>Listing open ports can allow you to see what other processes your application is
talking to.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)&gt;
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
o
=port:#Port&lt;0.0&gt;
State: CONNECTED
Slot: 0
Connected: &lt;0.0.0&gt;
Port controls forker process: forker
Input: 0
Output: 0
Queue: 0
=port:#Port&lt;0.2&gt;
State: CONNECTED|BINARY_IO
Slot: 16
Connected: &lt;0.62.0&gt;
Links: &lt;0.62.0&gt;
Port is UNIX fd not opened by emulator: 2/2
Input: 0
Output: 0
Queue: 0
=port:#Port&lt;0.4&gt;
State: CONNECTED|SOFT_EOF
Slot: 32
Connected: &lt;0.64.0&gt;
Links: &lt;0.64.0&gt;
Port controls linked-in driver: tty_sl -c -e
Input: 4
Output: 235
Queue: 0
</code></pre>
</div>

<h3 id="proc-info">(p)roc info</h3>

<p>Prints a list of running processes along with a list of open ports.</p>

<p>Processes are a fundamental building blog of Elixir applications, so seeing what
processes are running can give you a lot of insight into what’s going on.</p>

<p>Most Elixir/Erlang applications run a large number of processes, so this list
will be quite long.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
p
...

=proc:&lt;0.1.0&gt;
State: Waiting
Name: erts_code_purger
Spawned as: erts_code_purger:start/0
Current call: erlang:hibernate/3
Spawned by: &lt;0.0.0&gt;
Message queue length: 0
Number of heap fragments: 0
Heap fragment data: 0
Reductions: 9
Stack+heap: 4
OldHeap: 0
Heap unused: 4
OldHeap unused: 0
BinVHeap: 0
OldBinVHeap: 0
BinVHeap unused: 46422
OldBinVHeap unused: 46422
Memory: 800
Stack dump:
Program counter: 0x00000001059a6008 (unknown function)
arity = 3
   erts_code_purger
   wait_for_request
   []

0x0000000118970220 Return addr 0x00000001059a6088 (&lt;terminate process normally&gt;)
Internal State: ACT_PRIO_HIGH | USR_PRIO_HIGH | PRQ_PRIO_HIGH | OFF_HEAP_MSGQ
=proc:&lt;0.2.0&gt;
State: Waiting
Spawned as: erts_literal_area_collector:start/0
Current call: erlang:hibernate/3
Spawned by: &lt;0.0.0&gt;
Message queue length: 0
Number of heap fragments: 0
Heap fragment data: 0
Reductions: 8
Stack+heap: 4
OldHeap: 0
Heap unused: 4
OldHeap unused: 0
BinVHeap: 0
OldBinVHeap: 0
BinVHeap unused: 46422
OldBinVHeap unused: 46422
Memory: 800
Stack dump:
Program counter: 0x00000001059a6008 (unknown function)
arity = 3
   erts_literal_area_collector
   start
   []

0x0000000107c3a3b8 Return addr 0x00000001059a6088 (&lt;terminate process normally&gt;)
Internal State: ACT_PRIO_HIGH | USR_PRIO_HIGH | PRQ_PRIO_HIGH | OFF_HEAP_MSGQ

...
</code></pre>
</div>

<h2 id="interactive-command">Interactive Command</h2>

<p>One of the commands is an interactive command, entering a new mode with
sub-commands.</p>

<h3 id="kill">(k)ill</h3>

<p>Prints information about one of the running processes in the system, then
prompts for what to do with that process:</p>

<ul>
  <li><code class="highlighter-rouge">(k)ill</code>: Kill the process, then display the next process</li>
  <li><code class="highlighter-rouge">(n)ext</code>: Move to the next process without killing the current one</li>
  <li><code class="highlighter-rouge">(r)eturn</code>: Exit the sub-menu and return to the BREAK menu</li>
</ul>

<p>When using the <code class="highlighter-rouge">p</code> command to list processes (described above), the list can be
quite long and hard to navigate.</p>

<p>This command will show you only a single process at a time, allowing you to
decide what to do with it.</p>

<p>If the process is running under a supervisor, killing it will cause the
supervisor to respond according to its restart policy, often be recreating the
process.</p>

<div class="highlighter-rouge"><pre class="highlight"><code>Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)&gt;
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
k


Process Information

--------------------------------------------------
=proc:&lt;0.108.0&gt;
State: Waiting
Spawned as: erlang:apply/2
Spawned by: &lt;0.78.0&gt;
Message queue length: 0
Number of heap fragments: 0
Heap fragment data: 0
Link list: [{to,&lt;0.66.0&gt;,#Ref&lt;0.2287420997.2752512002.40054&gt;}]
Reductions: 4190
Stack+heap: 233
OldHeap: 0
Heap unused: 207
OldHeap unused: 0
BinVHeap: 1
OldBinVHeap: 0
BinVHeap unused: 46421
OldBinVHeap unused: 46422
Memory: 2696
Stack dump:
Program counter: 0x0000000105dac3e8 (io:execute_request/3 + 376)
arity = 0
y(0)     #Ref&lt;0.2287420997.2752512002.40054&gt;
y(1)     error
y(2)     {false,{get_line,unicode,&lt;&lt;"iex(1)&gt; "&gt;&gt;}}
y(3)     &lt;0.66.0&gt;

0x0000000107d82470 Return addr 0x0000000105e20998 ('Elixir.IEx.Server':io_get/4 + 136)
y(0)     &lt;0.108.0&gt;
y(1)     &lt;0.78.0&gt;

0x0000000107d82488 Return addr 0x00000001059a6088 (&lt;terminate process normally&gt;)
Internal State: ACT_PRIO_NORMAL | USR_PRIO_NORMAL | PRQ_PRIO_NORMAL
(k)ill (n)ext (r)eturn:
</code></pre>
</div>

<h2 id="wrapping-up">Wrapping Up</h2>

<p>I wasn’t able to find a place where this information was documented, so I hope
this gives you some insight into more of the power tools available in the BEAM.</p>

<p>When you’re running your application in an environment that doesn’t have access
to more powerful tools like Observer or observer_cli, the BREAK menu can help
you get to the bottom of a problem.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">The Search Is Over</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2023/12/14/the-search-is-over/"/>
    
    <id>/blog/2023/12/14/the-search-is-over</id>
    <published>2023-12-14T11:24:05-08:00</published>
    <updated>2023-12-14T11:24:05-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>I’m happy to announce that my search for a new position is over!</p>

<p>This morning, I accepted an offer for a new position. I’ll start first of the
new year and will share more details at that time.</p>

<p>I had so many people reach out with really good and interesting opportunities. I
wasn’t sure what to expect in the current tech job market, and I was pleasantly
surprised by the choices I was presented with.</p>

<p>So thank you all for your referrals and suggestions! I really appreciate that
you were willing to share those opportunities with me.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Playing Dumb</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2023/12/12/playing-dumb/"/>
    
    <id>/blog/2023/12/12/playing-dumb</id>
    <published>2023-12-12T07:39:10-08:00</published>
    <updated>2023-12-12T07:39:10-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>Write cleaner, more reusable code by forgetting what you know.</p>

<p><em>I wrote the first draft of this post while I was still at Sequin, and it uses
examples from their domain. Publishing here with permission.</em></p>

<p>When implementing a new feature in a codebase, we usually have the whole problem
loaded into our brains, and we’re intimately familiar with how all of the
relevant pieces work and how they fit together. This is good, as it helps us get
things done quickly.</p>

<p>But if we’re not careful, we can use this deep knowledge to accidentally embed
implicit assumptions into the code we’re writing. When we come back to it later,
we find it harder to understand, more difficult to reuse in a slightly different
context, and more susceptible to needing to be refactored the next time we’re in
the area.</p>

<p>One of the ways I try to avoid this mess is to <em>play dumb</em>. That is, I try to
take off my <em>omniscient creator of all the things</em> hat put myself in the shoes
of the code I’m writing. I’ll ask some questions from that perspective:</p>
<ul>
  <li>What is my job?</li>
  <li>What should I know?</li>
  <li>What do I have no business knowing?</li>
</ul>

<p>This technique applies at many levels: subsystems, individual services,
modules/classes, and functions/methods.</p>

<p>Sandi Metz says it very well in her article, <a href="https://www.sandimetz.com/blog/2018/21/what-does-oo-afford">What Does OO
Afford?</a></p>

<blockquote>
  <p>“OO asks you to blithely trust others to correctly do their bit. It wants you
to strive for ignorance to protect yourself from the consequences of distant
changes to other objects.”</p>
</blockquote>

<p>Let’s look at some examples. The first two are both in Elixir which is a
functional language, so I’ll be talking about modules and functions below. But
the same principles apply in an object-oriented language where we work with
classes, objects, and methods.</p>

<h2 id="module-level">Module Level</h2>

<p>In the Sequin codebase, a <code class="highlighter-rouge">Job</code> contains the state needed to replicate a
collection of objects from an upstream API to a customer’s database (e.g.
HubSpot contacts). Every time a job runs, it fetches a page of objects and
writes them to the database. We then update the job with information needed to
fetch the next page as well some other metadata.</p>

<p>We have two general kinds of jobs for each collection: <code class="highlighter-rouge">backfill</code> and <code class="highlighter-rouge">delta</code>.
Backfill jobs are responsible for fetching historical data, and delta jobs are
responsible for keeping up with the latest changes made upstream. When a
customer starts replicating a new collection, we start with a <code class="highlighter-rouge">backfill</code> job.
When it is done, we then kick off a <code class="highlighter-rouge">delta</code> job.</p>

<p>We keep the latest version of each job in memory for speed, but we also need to
persist the jobs so that we don’t have to start over after a system restart. For
this, we have a <code class="highlighter-rouge">JobStore</code>.</p>

<p>We were recently writing some new code related to job execution and we wrote
something like this function:</p>

<div class="language-elixir highlighter-rouge"><pre class="highlight"><code><span class="k">defp</span> <span class="n">note_job_completed</span><span class="p">(%</span><span class="no">State</span><span class="p">{}</span> <span class="o">=</span> <span class="n">state</span><span class="p">,</span> <span class="n">table_id</span><span class="p">,</span> <span class="n">row_count</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">job</span> <span class="o">=</span>
    <span class="n">state</span>
    <span class="o">|&gt;</span> <span class="n">get_job!</span><span class="p">(</span><span class="n">table_id</span><span class="p">)</span>
    <span class="o">|&gt;</span> <span class="no">Jobs</span><span class="o">.</span><span class="n">note_job_completed!</span><span class="p">(</span><span class="n">state</span><span class="o">.</span><span class="n">resource_id</span><span class="p">,</span> <span class="n">row_count</span><span class="p">,</span> <span class="no">nil</span><span class="p">)</span>

  <span class="k">if</span> <span class="n">job</span><span class="o">.</span><span class="n">kind</span> <span class="o">==</span> <span class="ss">:backfill</span> <span class="k">do</span>
    <span class="no">JobStore</span><span class="o">.</span><span class="n">replace_job</span><span class="p">(</span><span class="n">state</span><span class="o">.</span><span class="n">resource_id</span><span class="p">,</span> <span class="n">job</span><span class="p">,</span> <span class="p">[</span><span class="no">Map</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">job</span><span class="p">,</span> <span class="ss">:kind</span><span class="p">,</span> <span class="ss">:delta</span><span class="p">)])</span>
  <span class="k">else</span>
    <span class="no">JobStore</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">state</span><span class="o">.</span><span class="n">resource_id</span><span class="p">,</span> <span class="n">job</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="k">defp</span> <span class="n">get_job!</span><span class="p">(%</span><span class="no">State</span><span class="p">{}</span> <span class="o">=</span> <span class="n">state</span><span class="p">,</span> <span class="n">table_id</span><span class="p">)</span> <span class="k">do</span>
  <span class="c1"># Omitted; uses `JobStore.load()` to load all of the jobs for</span>
  <span class="c1"># `state.resource_id` and then finds the one for the collection</span>
  <span class="c1"># represented by table_id.</span>
<span class="k">end</span>
</code></pre>
</div>

<p>This code makes some critical assumptions about how the JobStore is implemented.
If we ever chose to change our implementation, this code would break in
interesting and confusing ways.</p>

<p>This seemed perfectly reasonable when we first wrote it. But because <strong>you</strong>
don’t know the implementation of the JobStore, you probably noticed some
problems right away. Our intimate knowledge of the implementation of the
JobStore kept us from seeing these problems at first.</p>

<p>Here are some of the assumptions this code makes:</p>

<ul>
  <li>The JobStore derives a key for each job and stores the job under that key.</li>
  <li>Calling <code class="highlighter-rouge">Job.note_job_completed!/3</code> doesn’t change the job’s key, so when we
call <code class="highlighter-rouge">JobStore.replace_job</code> with the updated job, the JobStore can still find
the job in order to replace it.</li>
  <li>Calling <code class="highlighter-rouge">JobStore.add/2</code> will actually replace any existing job that has the
same key rather than adding a second copy of the job.</li>
</ul>

<p>Once we recognized that we were making these assumptions, we immediately
refactored the code. To do that, we put ourselves in the shoes of this code and
answered the questions from above:</p>

<ul>
  <li><strong>What is my job?</strong> To update a job after it completes and persist the updated
version back into the <code class="highlighter-rouge">JobStore</code> in place of the previous version.</li>
  <li><strong>What should I know?</strong> There is a <code class="highlighter-rouge">JobStore</code>, and it exposes some public
functions for interacting with it.</li>
  <li><strong>What do I have no business knowing?</strong> How and where the <code class="highlighter-rouge">JobStore</code> stores
jobs; what mechanisms it uses to find stored jobs; what parts of the Job are
relevant to how jobs are stored.</li>
</ul>

<p>Given those answers, we were able to temporarily forget what we know about the
internals of the JobStore (aka play dumb) and make this code much cleaner and
safer:</p>

<div class="language-elixir highlighter-rouge"><pre class="highlight"><code><span class="k">defp</span> <span class="n">note_job_completed</span><span class="p">(%</span><span class="no">State</span><span class="p">{}</span> <span class="o">=</span> <span class="n">state</span><span class="p">,</span> <span class="n">job</span><span class="p">,</span> <span class="n">row_count</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">next_job</span> <span class="o">=</span>
    <span class="n">job</span>
    <span class="o">|&gt;</span> <span class="no">SyncJobs</span><span class="o">.</span><span class="n">note_job_completed!</span><span class="p">(</span><span class="n">state</span><span class="o">.</span><span class="n">resource_id</span><span class="p">,</span> <span class="n">row_count</span><span class="p">,</span>  <span class="no">nil</span><span class="p">)</span>
    <span class="o">|&gt;</span> <span class="no">Map</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="ss">:kind</span><span class="p">,</span> <span class="ss">:delta</span><span class="p">)</span>

  <span class="no">JobStore</span><span class="o">.</span><span class="n">replace_job</span><span class="p">(</span><span class="n">state</span><span class="o">.</span><span class="n">resource_id</span><span class="p">,</span> <span class="n">job</span><span class="p">,</span> <span class="p">[</span><span class="n">next_job</span><span class="p">])</span>
<span class="k">end</span>

<span class="c1"># get_job! as before</span>
</code></pre>
</div>

<p>Here are the relevant changes:</p>
<ul>
  <li>We now save the next version of the job into a new variable, <code class="highlighter-rouge">next_job</code>.</li>
  <li>We no longer call <code class="highlighter-rouge">add_job</code> at all; we always call <code class="highlighter-rouge">replace_job</code>.</li>
  <li>We call <code class="highlighter-rouge">replace_job</code> with the job we originally loaded from the store (<code class="highlighter-rouge">job</code>)
and replace it with the updated job, <code class="highlighter-rouge">next_job</code>.</li>
</ul>

<p>This will continue to work even if we make significant changes to the underlying
implementation of the JobStore.</p>

<h2 id="function-level">Function Level</h2>

<p>When the shape of the data changes upstream (for example, a new custom property
is added to a HubSpot contact), Sequin has to react to those changes by updating
the structure of the database we’re replicating to. We call these changes
“migrations”, as do many ORM libraries.</p>

<p>Sequin <a href="https://blog.sequin.io/launch-week-1-wrap-up/">recently released</a> an
improvement that allows a replication to continue running while attempting to
perform the migration. If the migration fails, it is scheduled to be retried
later.</p>

<p>The new code that runs when a replication (sync)process starts up looked
something like this:</p>

<div class="language-elixir highlighter-rouge"><pre class="highlight"><code><span class="k">defp</span> <span class="n">initialize_sync</span><span class="p">(</span><span class="n">state</span><span class="p">)</span> <span class="k">do</span>
  <span class="p">{</span><span class="n">state</span><span class="p">,</span> <span class="n">jobs</span><span class="p">}</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">run_pending_migrations</span><span class="p">(</span><span class="n">state</span><span class="p">)</span> <span class="k">do</span>
      <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span> <span class="o">-&gt;</span>
        <span class="c1"># Do migration follow-up work</span>
        <span class="c1"># Create any new jobs required by the migrations</span>
        <span class="p">{</span><span class="n">state</span><span class="p">,</span> <span class="n">jobs</span><span class="p">}</span>
      <span class="n">_error</span> <span class="o">-&gt;</span>
        <span class="no">Process</span><span class="o">.</span><span class="n">send_after</span><span class="p">(</span><span class="n">self</span><span class="p">(),</span> <span class="ss">:restart_sync</span><span class="p">,</span> <span class="nv">@migration_retry_interval</span><span class="p">)</span>
        <span class="n">jobs</span> <span class="o">=</span> <span class="n">load_jobs!</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
        <span class="p">{</span><span class="n">state</span><span class="p">,</span> <span class="n">jobs</span><span class="p">}</span>
    <span class="k">end</span>

  <span class="c1"># Start running `jobs` in order continue replicating data</span>
<span class="k">end</span>

<span class="k">def</span> <span class="n">handle_info</span><span class="p">(</span><span class="ss">:restart_sync</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">stop_pipeline</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="ss">:migration_failed</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
</div>

<p>Again, there were some implicit assumptions built into this code because we knew
too much when writing it:</p>
<ul>
  <li>We know that we’re going to retry running migrations by stopping the
replication pipeline and allowing it to restart, where it will try running
migrations again.</li>
  <li>We know that this is the only place we’re sending the <code class="highlighter-rouge">:restart_sync</code> message,
so we assume that the reason for stopping the pipeline is <code class="highlighter-rouge">:migration_failed</code>.</li>
</ul>

<p>These assumptions may not always be true. We might move migrations completely
away from the replication process and run them out-of-band. We might find other
reasons to stop and restart the sync pipeline. Any of those changes would cause
us to have to do more refactoring than if we had played dumb while writing this
code.</p>

<p>Once we realized that we were making these assumptions, we again asked ourselves
the questions, this time from two perspectives:</p>

<p>From the perspective of <code class="highlighter-rouge">initialize_sync</code>:</p>
<ul>
  <li><strong>What is my job?</strong> Schedule a retry of failed migrations.</li>
  <li><strong>What should I know?</strong> I can send a message to myself after the retry
interval to trigger the retry.</li>
  <li><strong>What do I have no business knowing?</strong> How the retry is performed, in
particular that it will be performed by restarting the entire replication
process.</li>
</ul>

<p>From the perspective of the <code class="highlighter-rouge">handle_info</code> callback:</p>
<ul>
  <li><strong>What is my job?</strong> Retry running migrations after a failure.</li>
  <li><strong>What should I know?</strong> That we currently re-run migrations by stopping and
restarting the replication pipeline.</li>
  <li><strong>What do I have no business knowing?</strong> Who is sending me the message to retry
migrations and why they’re sending it.</li>
</ul>

<p>Given this set of answers, we might refactor to something like this:</p>

<div class="language-elixir highlighter-rouge"><pre class="highlight"><code><span class="k">defp</span> <span class="n">initialize_sync</span><span class="p">(</span><span class="n">state</span><span class="p">)</span> <span class="k">do</span>
  <span class="p">{</span><span class="n">state</span><span class="p">,</span> <span class="n">jobs</span><span class="p">}</span> <span class="o">=</span>
    <span class="k">case</span> <span class="n">run_pending_migrations</span><span class="p">(</span><span class="n">state</span><span class="p">)</span> <span class="k">do</span>
      <span class="p">{</span><span class="ss">:ok</span><span class="p">,</span> <span class="n">state</span><span class="p">}</span> <span class="o">-&gt;</span>
        <span class="c1"># Do migration follow-up work</span>
        <span class="c1"># Create any new jobs required by the migrations</span>
        <span class="p">{</span><span class="n">state</span><span class="p">,</span> <span class="n">jobs</span><span class="p">}</span>
      <span class="n">_error</span> <span class="o">-&gt;</span>
        <span class="no">Process</span><span class="o">.</span><span class="n">send_after</span><span class="p">(</span><span class="n">self</span><span class="p">(),</span> <span class="ss">:migration_failed</span><span class="p">,</span> <span class="nv">@migration_retry_interval</span><span class="p">)</span>
        <span class="n">jobs</span> <span class="o">=</span> <span class="n">load_jobs!</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
        <span class="p">{</span><span class="n">state</span><span class="p">,</span> <span class="n">jobs</span><span class="p">}</span>
    <span class="k">end</span>

  <span class="c1"># Start running `jobs` in order continue replicating data</span>
<span class="k">end</span>

<span class="k">def</span> <span class="n">handle_info</span><span class="p">(</span><span class="ss">:migration_failed</span><span class="p">,</span> <span class="n">state</span><span class="p">)</span> <span class="k">do</span>
  <span class="n">stop_pipeline</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="ss">:migration_failed</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
</div>

<p>All we did is change the the message being sent from <code class="highlighter-rouge">:restart_sync</code> to
<code class="highlighter-rouge">:migration_failed</code>, but with this change, we’re cleanly separating “what
happened” (migrations failed) from “what do we do about it” (restart the
pipeline to retry).</p>

<h2 id="system-level">System Level</h2>

<p>I don’t have permission to use the code for this example, but several years ago
I was reviewing a pull request where a permission check was removed from part of
the code. The authors’ comment was, “We removed the permission check because any
user can change the topology, so there’s no need for the permission check.”</p>

<p>The original authors were removing what they saw as dead code. If permission
checking was rare in the codebase, that would likely have been a good decision.</p>

<p>However, given that the application consistently checked permissions on various
operations, they were inappropriately using their knowledge that this operation
isn’t currently restricted, making it harder to change that decision in the
future.</p>

<p>By asking the questions, they might have come to a different decision:</p>

<p><strong>What is my job?</strong> Change the topology
<strong>What should I know?</strong> We often restrict who can perform potentially dangerous
operations; we have a standard mechanism for checking these permissions.
<strong>What do I have no business knowing?</strong> Whether or not this particular operation
is restricted.</p>

<p>Keeping the permission check in place made the code more resilient to future
changes to permissions.</p>

<h2 id="wrapping-up">Wrapping Up</h2>

<p>I’ve found the technique of playing dumb to be extremely valuable in writing
code that is clean and easy to work with. It helps reduce inappropriate coupling
and allows code to be more easily reused without first refactoring it.</p>

<p>Note that I’m not advocating doing extra work. Rather, I’m advocating doing the
same amount of work in a better way. We’re still writing the same code, but
we’re writing it in different places or using better names.</p>

<p>It’s hard to stop and remind myself that I know too much when I’m writing code.
I try to make it a habit to put myself in the position of the code I’m writing
and ask those questions:</p>

<ul>
  <li>What’s my job?</li>
  <li>What should I know?</li>
  <li>What do I have no business knowing?</li>
</ul>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Onboarding Milestones: Am I There Yet?</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2023/12/07/onboarding-milestones-am-i-there-yet/"/>
    
    <id>/blog/2023/12/07/onboarding-milestones-am-i-there-yet</id>
    <published>2023-12-07T07:46:00-08:00</published>
    <updated>2023-12-07T07:46:00-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>When you start a new job, it often feels like you’ve jumped into the deep end
of the pool and you need to find a way to just stay afloat. Eventually, the
panic subsides and you’re keeping your head above the water. Then you learn to
start swimming and are able to move confidently within your new surroundings.
How can you tell which stage you’re in?</p>

<p>Every new job starts with a process of “onboarding” into that role, whether
formal or informal. How do you know when you’re fully onboarded? When do you
feel like you have a good handle on things?</p>

<p>When I started at <a href="https://sequin.io">Sequin</a>, one of the first things I did was
write down a list of Onboarding Milestones that I could use to gauge my
progress. These milestones gave me a roadmap of where I needed to dig deeper.
They gave me a sense of accomplishment to see how far I’d come since I started.
They formed the basis of my 30/60/90-day and then quarterly goals.</p>

<p>My initial list was very focused on learning the codebase and its architecture.
Here it is:</p>

<ul>
  <li>[x] Can confidently review a non-trivial PR</li>
  <li>[x] Can ship customer-facing code to production</li>
  <li>[x] Can implement and test a non-trivial feature end-to-end</li>
  <li>[x] Can safely refactor a non-trivial part of the codebase</li>
  <li>[x] Can successfully complete a single day of on-call with no help</li>
  <li>[ ] Can successfully complete a full week of on-call with no help</li>
  <li>[x] Can safely make a small deployment change (e.g. adding a new env var)</li>
  <li>[ ] Can safely make a larger infrastructure change (e.g. CI, CD, deployment)</li>
  <li>[x] Can definitively answer questions about how something works from another
team member</li>
  <li>[ ] <del>Can update the CHANGELOG</del> (We decided to make announcements elsewhere,
so no longer relevant)</li>
  <li>[x] Can write a big picture/visionary memo about product direction</li>
  <li>[x] Can triage/debug a production issue with no help</li>
  <li>[x] Can recognize when seemingly innocent issues are representative of a
larger issue</li>
</ul>

<p>Over time, I add and remove milestones from the list. I might come to realize
that there’s something important that I don’t know much about, so I’ll add
milestones to tell me when I’ve learned about it. Something might change that
means that a milestone is no longer relevant, so I’ll drop it.</p>

<p>As you can see, I hit most of these milestones in my time at Sequin, but I
still had a couple to go.</p>

<p>On one of my on-call weeks, I handled everything on my own until the last
half-day of my shift, when a really weird new issue arose that I couldn’t figure
out. I asked for help, and the milestone remained incomplete. But that’s OK. I
was much more capable at customer support than when I started and I even
contributed substantial improvements to the support process. This outstanding
milestone helped me to focus on learning what I still needed to learn in order
to eventually complete it.</p>

<p>Upon reflection, I’d add more items that are less technically focused. Sequin is
a very small startup where we all needed to wear a lot of hats. This list
has nothing about some of these hats. Some examples of what I’d add:</p>
<ul>
  <li>More cross-functional items related to marketing, customer calls/discovery
sessions, sales, etc.</li>
  <li>Writing documentation</li>
  <li>Writing blog posts</li>
  <li>Other outside communication</li>
  <li>Leading projects</li>
  <li>Using our own software for something useful (“dog-fooding”)</li>
</ul>

<p>You don’t need to change companies to get value from Onboarding Milestones. Use
them any time you get promoted or take on new responsibilities.</p>

<p>I will definitely employ Onboarding Milestones again when I <a href="https://randycoulman.com/blog/2023/12/04/back-on-the-market/">start my next
role</a>. I’ve found them extremely valuable.</p>

<p>Your list of Onboarding Milestones is going to be very different from mine.
Here are some things to think about as you start to brainstorm:</p>

<ul>
  <li>What kinds of things are you expected to accomplish in your role?</li>
  <li>What does success look like for your role?</li>
  <li>How senior is your role? The milestone list for someone new to this career
will look very different than the one for a senior person with many years of
experience.</li>
  <li>What do you value?</li>
  <li>What can you control and/or influence? What factors are outside of your
control?</li>
</ul>

<p>Here’s a partial list of categories to consider as you develop your Onboarding
Milestones:</p>

<ul>
  <li>Customer interaction</li>
  <li>Representing your company to the outside world</li>
  <li>Customer support</li>
  <li>Troubleshooting/debugging/incidents</li>
  <li>Peer interaction</li>
  <li>Mentoring/being mentored</li>
  <li>Contributions to code/documentation/PR reviews</li>
  <li>Comfort in the codebase: where to find stuff; where the tech debt lives; etc.</li>
  <li>Subject matter expertise</li>
  <li>Able to onboard someone else (aka onboarding buddy)</li>
  <li><a href="https://www.snopes.com/fact-check/know-where-man/">Knowing which screw to
turn</a></li>
  <li>Leaving the honeymoon phase: starting to see technical/process/leadership
issues</li>
</ul>

<p>What categories would you add to this list?</p>

<p>Learning is a continuous process. “Onboarded” is not a binary on/off state. You
might complete your company’s formal onboarding process, but that has nothing to
do with whether you’re really onboarded.</p>

<p>Onboarding is like the sunrise: the darkness slowly gives way to light, but
you’re never really sure when that happened. There might be some “aha” moments,
like when the sun first peeks over the horizon, but expect this to be a
continuous process. You can use your Onboarding Milestones to help you measure
your progress.</p>

<p><em>Thanks to Bucky, Gene, and Jeff for brainstorming the milestone categories with
me, to Drew for the sunrise metaphor, and to Anthony for his thorough review of
an earlier draft of this post.</em></p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Back on the Market</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2023/12/04/back-on-the-market/"/>
    
    <id>/blog/2023/12/04/back-on-the-market</id>
    <published>2023-12-04T08:43:14-08:00</published>
    <updated>2023-12-04T08:43:14-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>After a really enjoyable year at <a href="https://sequin.io">Sequin</a>, I’m once again looking
for a new opportunity.</p>

<p>Sequin recently decided that they need to transition from 100% remote to 100% in-person
based in San Francisco. That’s just not a move I can make at this time.</p>

<p>While I’m disappointed to no longer be working there, I’m really grateful for
the time I had, and the great team I got to work with. We built some cool stuff,
and I was able to be involved in more facets of the business than I ever have
before. All in all, it was was a wonderful learning experience.</p>

<p>Last year when I was in a similar position, I posted a list of what I was looking
for. Sequin ticked most of those boxes. I find that my priorities remain
largely the
same, so I’ll reproduce that list here with an addition and some minor edits:</p>

<ul>
  <li>
    <p>I do my best work when I’m making life better for other people. That can
involve building systems that help people do their jobs more effectively,
refactoring to make a codebase easier to work in, mentoring and teaching
others, or bridging gaps to resolve conflicts between teams and individuals.
Work like this is my “happy place”.</p>
  </li>
  <li>
    <p>I want to stay on the technical side. I don’t necessarily need to have my
hands on the code all day every day, but I still enjoy programming. I’m not
interested in moving into management.</p>
  </li>
  <li>
    <p>I’d prefer to have a technical leadership role. I believe everyone can lead
from wherever they are (and I do that), but I’ve also found that having the
title matters sometimes.</p>
  </li>
  <li>
    <p>I’d love to work somewhere that is all-in on Elixir and the
BEAM (Erlang virtual machine), or is moving that direction. While I’m open to
other technology stacks, I’ve been really enjoying working in Elixir and would
love to be able to continue to take advantage of what it offers.</p>
  </li>
  <li>
    <p>I’m not focused on any single industry or business domain, but I want to work
on things that are designed to serve people and not enslave them.</p>
  </li>
  <li>
    <p>I prefer to work remotely. I’m open to some light travel for in-person
meetings/work.</p>
  </li>
</ul>

<p>If you know of any opportunities that match these criteria, please <a href="https://randycoulman.com/contact/">get in
touch</a>. You can find more details about my work on <a href="https://www.linkedin.com/in/randycoulman/">my LinkedIn
profile</a>.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Don't Call Us, We'll Call You</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2023/08/01/dont-call-us-well-call-you/"/>
    
    <id>/blog/2023/08/01/dont-call-us-well-call-you</id>
    <published>2023-08-01T13:32:43-07:00</published>
    <updated>2023-08-01T13:32:43-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>In Elixir, how can you keep a GenServer from blocking its clients while
performing a long operation?</p>

<p>The answer is <code class="highlighter-rouge">:noreply</code> and <code class="highlighter-rouge">GenServer.reply</code>. See my <a href="https://blog.sequin.io/genserver-reply-dont-call-us-well-call-you/">latest post on the
Sequin blog</a>
for more details and an example. I have also <a href="https://randycoulman.com/blog/2023/12/27/republish-genserver-reply-dont-call-us-well-call-you/">republished
here on my own blog</a>.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Between the Ctrl-C's</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2023/03/27/between-the-ctrl-cs/"/>
    
    <id>/blog/2023/03/27/between-the-ctrl-cs</id>
    <published>2023-03-27T13:57:36-07:00</published>
    <updated>2023-03-27T13:57:36-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>In Elixir, we often use <code class="highlighter-rouge">Ctrl-C Ctrl-C</code> to exit the IEx interactive shell or to
stop a running application. But did you ever notice the menu that pops up after
the first <code class="highlighter-rouge">Ctrl-C</code>? I was curious about that menu and what it can do, so I dug
in.</p>

<p>The result of my exploration is now up on <a href="https://blog.sequin.io/between-the-ctrl-cs/">the Sequin
blog</a> and has been <a href="https://randycoulman.com/blog/2023/12/19/republish-between-the-ctrl-cs/">republished
here on my own blog</a>. Check it
out!</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Starting at Sequin</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2022/12/07/starting-at-sequin/"/>
    
    <id>/blog/2022/12/07/starting-at-sequin</id>
    <published>2022-12-07T08:11:06-08:00</published>
    <updated>2022-12-07T08:11:06-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>This week, I am starting a new job as a Software Engineer at
<a href="https://sequin.io">Sequin</a>.</p>

<p>As I <a href="https://randycoulman.com/blog/2022/11/14/looking-for-whats-next/">posted last month</a>, I was laid
off from <a href="https://influxdata.com">InfluxData</a> and was looking for my next
opportunity. I’m happy to say that I found it at Sequin!</p>

<p>Sequin is a small startup that allows integrating external APIs with your
database. I’ll be working mostly in Elixir (as I wanted) and I’m really excited
about the tools we’re going to build and the people we’ll be able to serve.</p>

<p>I can’t wait to get started and to see what we can accomplish in the
coming months and years!</p>

<p>I am beyond grateful to many of you who contacted me with potential
opportunities, said nice things to and about me, encouraged me, and served as
references. Because of you, I had a lot of great options to consider. Words
can’t express how much I appreciate you!</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Recompiling ElixirLS</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2022/11/29/recompiling-elixirls/"/>
    
    <id>/blog/2022/11/29/recompiling-elixirls</id>
    <published>2022-11-29T11:28:02-08:00</published>
    <updated>2022-11-29T11:28:02-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>If you’re using the <a href="https://github.com/elixir-lsp/vscode-elixir-ls">ElixirLS</a>
extension in VSCode and your project uses a newer version of Elixir and/or
Erlang/OTP than what the extension uses, you may not be getting all of the
features that ElixirLS provides.</p>

<p>As <a href="https://dragoshmocrii.com/fix-vscode-elixirls-intellisense-for-code-imported-with-use/">Dragosh
Mocrii</a>
discovered, IntelliSense (aka ElixirSense) and the “jump to definition” features
won’t work for functions and macros imported with <code class="highlighter-rouge">use</code>.</p>

<p>As of this writing, I’m using Erlang 25.1.2 and Elixir 1.14.2, but <a href="https://github.com/elixir-lsp/vscode-elixir-ls/blob/master/.github/workflows/release.yml#L20-L21">ElixirLS
seems to be
using</a>
Erlang 22.x and Elixir 1.12.x.</p>

<p>The solution is to recompile ElixirLS with the versions of Elixir and Erlang
that your project uses.</p>

<p>Dragosh gives a set of instructions in his blog post. You can also refer to the
<a href="https://github.com/elixir-lsp/vscode-elixir-ls#installation">vscode-elixir-ls
README</a>.</p>

<p>I’ve distilled these two sources into a set of instructions that works well for
me (at least on MacOS) and posted them to <a href="https://gist.github.com/randycoulman/e554a46e31c2c064820d4137c21b3b14">a
Gist</a>,
which I’ve also included below to save you a click.</p>

<div class="language-shell highlighter-rouge"><pre class="highlight"><code><span class="c"># First time only</span>
git clone --recursive git@github.com:elixir-lsp/vscode-elixir-ls.git
<span class="nb">cd </span>vscode-elixir-lsp

<span class="c"># Second and subsequent times</span>
<span class="nb">cd </span>vscode-elixir-lsp
git pull <span class="o">&amp;&amp;</span> git submodule update --recursive

<span class="c"># Always</span>
npm install
<span class="nb">cd </span>elixir-ls
asdf <span class="nb">local </span>erlang <span class="o">{</span>desired version<span class="o">}</span>
asdf <span class="nb">local </span>elixir <span class="o">{</span>desired version<span class="o">}</span>
asdf install <span class="c"># should do nothing, but just to be safe</span>
<span class="nb">cd</span> ..
rm <span class="k">*</span>.vsix
npx vsce package
code --install-extension <span class="k">*</span>.vsix --force
</code></pre>
</div>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Looking for What's Next</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2022/11/14/looking-for-whats-next/"/>
    
    <id>/blog/2022/11/14/looking-for-whats-next</id>
    <published>2022-11-14T07:13:14-08:00</published>
    <updated>2022-11-14T07:13:14-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>Last week, <a href="https://www.influxdata.com/">InfluxData</a> laid off 27% of their
staff, including me. As a result, I’m now looking for my next opportunity.</p>

<p>I really enjoyed my three years there. I got to work with great people, I
learned a ton, and was able to do a lot of work that I’m proud of.</p>

<p>I now find myself looking for what’s next.</p>

<p>I’m open to a lot of possibilities, but here are the things I’m prioritizing:</p>

<ul>
  <li>
    <p>I do my best work when I’m making life better for other people. That can
involve building systems that help people do their jobs more effectively,
refactoring to make a codebase easier to work in, mentoring and teaching
others, or bridging gaps to resolve conflicts between teams and individuals.
Work like this is my “happy place”.</p>
  </li>
  <li>
    <p>I want to stay on the technical side. I don’t necessarily need to have my
hands on the code all day every day, but I still enjoy programming. I’m not
interested in moving into management.</p>
  </li>
  <li>
    <p>I’d prefer to have a technical leadership role. I believe everyone can lead
from wherever they are (and I do that), but I’ve also found that having the
title matters sometimes.</p>
  </li>
  <li>
    <p>I’d love to work somewhere that is all-in on Elixir and the
BEAM (Erlang virtual machine), or is moving that direction. While I’m open to
other technology stacks, I’ve been really enjoying working in Elixir and would
love to be able to take more advantage of what it offers than I’ve been able
to so far.</p>
  </li>
  <li>
    <p>I’m not focused on any single industry or business domain, but I want to work
on things that are designed to serve people and not enslave them.</p>
  </li>
</ul>

<p>If you know of any opportunities that match these criteria, please <a href="https://randycoulman.com/contact/">get in
touch</a>. You can find more details about my work on <a href="https://www.linkedin.com/in/randycoulman/">my LinkedIn
profile</a>.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Elixir Mix Podcast</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2021/10/11/elixir-mix-podcast/"/>
    
    <id>/blog/2021/10/11/elixir-mix-podcast</id>
    <published>2021-10-11T08:35:20-07:00</published>
    <updated>2021-10-11T08:35:20-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>I was recently on the <a href="https://elixirmix.com/">Elixir Mix podcast</a>, talking about some of the Elixir open source projects I’ve worked on recently.</p>

<p>Check out <a href="https://elixirmix.com/elixir-configcat-sdk-and-mix-test-in-emx-147">Episode 147</a>!</p>

<p>The main topic we discussed was the <a href="https://randycoulman.com/blog/2021/05/07/configcat-sdk-for-elixir/">Elixir ConfigCat SDK</a> I worked on last year.</p>

<p>We also talked about <a href="https://hex.pm/packages/mix_test_interactive">mix_test_interactive</a>, a tool I released earlier this year. <code class="highlighter-rouge">mix_test_interactive</code> is adapted from Louis Pilfold’s wonderful <a href="https://hex.pm/packages/mix_test_watch">mix_test_watch</a>, but adds an interactive element that allows you to control which tests you want to run.</p>

<p>We had a fun side discussion on the use of emoji in log messages and for git commits. I mentioned <a href="https://gitmoji.dev/">gitmoji</a>, which provides a catalog of emoji to use for various kinds of code changes.</p>

<p>I enjoyed my time on the podcast. Thanks so much to the hosts for inviting me!</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">ConfigCat SDK for Elixir</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2021/05/07/configcat-sdk-for-elixir/"/>
    
    <id>/blog/2021/05/07/configcat-sdk-for-elixir</id>
    <published>2021-05-07T08:23:19-07:00</published>
    <updated>2021-05-07T08:23:19-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>My team and I at <a href="https://www.influxdata.com/">InfluxData</a> recently worked with <a href="https://github.com/igorescobar">Igor Escobar</a> of <a href="https://www.joindrover.com/">Drover</a> and the team at <a href="https://configcat.com/">ConfigCat</a> to develop an Elixir SDK for ConfigCat’s feature flagging and configuration management service.</p>

<p>I wrote a blog post for InfluxData that was <a href="https://thenewstack.io/elixir-sdk-for-configcat/">just published on The New Stack</a>.</p>

<p>The SDK itself is on <a href="https://hex.pm/packages/configcat">hex.pm</a>.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Taking the Next Step</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2019/12/04/taking-the-next-step/"/>
    
    <id>/blog/2019/12/04/taking-the-next-step</id>
    <published>2019-12-04T07:31:59-08:00</published>
    <updated>2019-12-04T07:31:59-08:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>With mixed emotions, I’ve decided to leave <a href="https://codingzeal.com">Zeal</a> after
more than five years and join the e-commerce team at
<a href="https://influxdata.com">InfluxData</a>.</p>

<h2 id="zeal">Zeal</h2>

<p>I’ve loved working at Zeal.  The people are great, the projects are interesting,
and I’ve learned a ton.  <a href="https://www.codingzeal.com/hiring">They’re hiring</a> and
I wouldn’t hesitate to recommend working there if it seems like a good fit for
you.</p>

<p>As I transitioned from the industrial automation world to the web world, I
intentionally chose to work for a consulting company.  I felt that it would
provide the opportunity to experience many different projects, teams, and
environments and give me the breadth to get a sense of which parts of web
development I enjoyed most.</p>

<p>Zeal delivered on that goal in a big way.  I worked on a dozen client projects
and shipped production code in at least eight different languages during that
time, several of which I didn’t really know when I started there.</p>

<h2 id="growth">Growth</h2>

<p>Last year, I heard an <a href="https://www.entreleadership.com/blog/podcasts/whitney-johnson">interview with Whitney Johnson on the EntreLeadership
podcast</a> where
she talked about the idea of “S-curves” as it relates to personal growth and
learning.</p>

<p>The basic idea is that when you’re first learning something, you don’t know much;
you’re at the bottom of the “S”.  As you learn, you start moving up the curve
of the “S”.  This is where you grow the most.  As you reach the top of the “S”,
it’s time to use what you’ve learned to help bring others along the curve as
well.  But if you stay there too long, you start getting bored because there’s
not as much learning happening any more. Once you reach that point, you need to
start looking for the next “S” curve to move to so you can keep growing and
challenging yourself.</p>

<p>This metaphor describes my last five years really well.  At Zeal, I came in
knowing something about web development, but not a lot.  I went through a period
of rapid learning and growth as I climbed the “S” curve.  And now I feel like
I’ve been near the top of the “S” for the last year or so.  I’ve decided to make a
move so that I can jump to the bottom of the next “S”.</p>

<h2 id="next">Next?</h2>

<p>As I thought about what I wanted to do next, I had a few guiding thoughts:</p>

<ul>
  <li>
    <p>I want to stay technical.  While I enjoy working with people, I’m not
currently interested in moving into the people-management side of things.</p>
  </li>
  <li>
    <p>I want to be able to get above the day-to-day process of developing features
sometimes. My most fulfilling work has been when I’ve been able to work on the
bigger picture: system architecture, design and structure of the codebase, and
integrating the various pieces of a complex system together.</p>
  </li>
  <li>
    <p>I really enjoy teaching and mentoring, especially as it relates to technical
skills.</p>
  </li>
  <li>
    <p>I want the opportunity to continue growing and to expand the impact I’m able
to have on a team and a company.</p>
  </li>
  <li>
    <p>I want to get back to working at a product company again, but this time in the
web world.  I like the feedback cycle that results from living in the same
codebase for a long time.  I get to see the payoff from the investments I make
in code quality.  I also get to learn from the mistakes I make and shortcuts I
take.</p>
  </li>
</ul>

<h2 id="influxdata">InfluxData</h2>

<p>Enter <a href="https://influxdata.com">InfluxData</a>.</p>

<p>Believe it or not, I heard about the opportunity when I received a random e-mail
from a recruiter on LinkedIn about it.  After looking things over, it seemed
interesting enough to pursue, so I responded.</p>

<p>Through the interview process, I met my manager and future teammates and became
more and more excited about the opportunity and the people.</p>

<p>It’s a growing company (<a href="https://www.influxdata.com/careers/">and also hiring!</a>)
with lots of interesting challenges to address and opportunity for growth on a
technical career path.</p>

<p>It looks like it’s going to tick all of the boxes I listed above and I can’t
wait to get started!</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Comparing Floats in Tests</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2018/06/19/comparing-floats-in-tests/"/>
    
    <id>/blog/2018/06/19/comparing-floats-in-tests</id>
    <published>2018-06-19T06:12:00-07:00</published>
    <updated>2018-06-19T06:12:00-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>Because many <a href="http://floating-point-gui.de/errors/comparison/">floating point numbers can’t be represented exactly</a> in a computer, most testing frameworks provide a way of checking that a floating point result is “close enough” to the expected value.  In a recent Python project, I learned that <a href="https://pytest.org/">pytest</a> has a solution to this problem that I’d never seen before.</p>

<p>When first working with floating point numbers, many programmers are surprised when two numbers that should be equal are not.  For example, in binary, 0.1 + 0.2 does not exactly equal 0.3 because 0.1 does not have a finite represenation in the binary floating point representation that our computers use.  This is similar to how 1/3 does not have a finite representation in decimal.</p>

<p>The solution most people come up with is to check whether the absolute difference between the expected and actual values is small enough.  If you know that the numbers you’ll be working with are in a certain range, this can be fine.  But if you’re working with either very large or very small numbers, this may not work the way you’d expect.</p>

<p>A solution to this problem is to compare the relative difference between the two numbers.  This is a bit trickier, though, as you have to worry about what happens when the numbers are close to 0.</p>

<p>Because of these complexities, most unit testing frameworks provide a way of checking that a floating point result is close enough to the expected value.</p>

<p>Here are some examples:</p>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">Ruby Minitest assertions</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="n">assert_in_delta</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="o">.</span><span class="mi">1</span> <span class="o">+</span> <span class="mi">0</span><span class="o">.</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="o">.</span><span class="mo">0005</span><span class="p">)</span>
</div></div><div data-line="2" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="n">assert_in_epsilon</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="o">.</span><span class="mi">1</span> <span class="o">+</span> <span class="mi">0</span><span class="o">.</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="o">.</span><span class="mo">0001</span><span class="p">)</span>  <span class="c1"># relative difference</span>
</div></div></pre></div></figure>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">Ruby RSpec</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="n">expect</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">1</span> <span class="o">+</span> <span class="mi">0</span><span class="o">.</span><span class="mi">2</span><span class="p">).</span><span class="nf">to</span> <span class="n">be_within</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mo">0005</span><span class="p">).</span><span class="nf">of</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mi">3</span><span class="p">)</span>
</div></div></pre></div></figure>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">Java JUnit</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="n">assertEquals</span><span class="o">(</span><span class="mf">0.3</span><span class="o">,</span> <span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span><span class="o">,</span> <span class="mf">0.0005</span><span class="o">)</span>
</div></div></pre></div></figure>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">JavaScript Mocha + Chai</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nx">expect</span><span class="p">(</span><span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">be</span><span class="p">.</span><span class="nx">closeTo</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mf">0.0005</span><span class="p">)</span>
</div></div></pre></div></figure>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">JavaScript Jest</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nx">expect</span><span class="p">(</span><span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span><span class="p">).</span><span class="nx">toBeCloseTo</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>  <span class="c1">// number of digits, not absolute value</span>
</div></div></pre></div></figure>

<p>Hopefully you get the idea.  This is pretty much what I expect to find when I encounter a new testing framework.</p>

<p>However, I recently worked on a Python project where I used <a href="https://pytest.org/">pytest</a> as the test framework.</p>

<p>pytest uses Python’s built-in <code class="highlighter-rouge">assert</code> statement in its tests and is able to produce very nice failure messages from that.  However, <code class="highlighter-rouge">assert</code> by itself doesn’t provide any niceties for comparing floating point numbers.</p>

<p>To solve this problem, pytest includes an <code class="highlighter-rouge">approx</code> function that creates an object that knows how to compare itself to a floating point value appropriately.</p>

<p>Here are some examples of how to use it:</p>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">Python pytest with approx</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="k">assert</span> <span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span> <span class="o">==</span> <span class="n">approx</span><span class="p">(</span><span class="mf">0.3</span><span class="p">)</span>
</div></div><div data-line="2" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="3" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="k">assert</span> <span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span> <span class="o">==</span> <span class="n">approx</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="n">rel</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">)</span>
</div></div><div data-line="4" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="5" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="k">assert</span> <span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span> <span class="o">==</span> <span class="n">approx</span><span class="p">(</span><span class="mf">0.3</span><span class="p">,</span> <span class="nb">abs</span><span class="o">=</span><span class="mf">1e-3</span><span class="p">)</span>
</div></div></pre></div></figure>

<p>As you can hopefully see, <code class="highlighter-rouge">approx</code> provides a lot of flexibility with a very simple API.  If you provide a <code class="highlighter-rouge">rel</code> value, it does relative comparison (the default).  If you instead provide an <code class="highlighter-rouge">abs</code> value, it does absolute comparison.  It can even handle comparing arrays or dictionaries containing numbers.</p>

<p>After so many years of using different testing frameworks in different languages, I was genuinely surprised to run into such a different approach to the problem.  I think this is a really nice, effective solution and it’s got me thinking about how it might be applied to other languages and testing frameworks.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Solving Circular Dependencies in Modular Redux</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2018/06/12/solving-circular-dependencies-in-modular-redux/"/>
    
    <id>/blog/2018/06/12/solving-circular-dependencies-in-modular-redux</id>
    <published>2018-06-12T06:16:15-07:00</published>
    <updated>2018-06-12T06:16:15-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>Some time ago, I wrote several posts about encapsulating the Redux state tree using reducers and selectors, the asymmetry between reducers and selectors, and the problems that arise when attempting to resolve that asymmetry in a modular-structured Redux application.  Thanks to a <a href="http://nicolasgallagher.com/redux-modules-and-code-splitting/">wonderful blog post by Nicholas Gallagher</a>, I now have a better solution to the problems.</p>

<h2 id="background">Background</h2>

<p>As a recap, here are my original posts:</p>

<ul>
  <li><a href="https://randycoulman.com/blog/2016/09/13/encapsulating-the-redux-state-tree/">Encapsulating the Redux State Tree</a></li>
  <li><a href="https://randycoulman.com/blog/2016/09/20/redux-reducer-selector-asymmetry/">Redux Reducer/Selector Asymmetry</a></li>
  <li><a href="https://randycoulman.com/blog/2016/09/27/modular-reducers-and-selectors/">Modular Reducers and Selectors</a></li>
</ul>

<h2 id="where-did-we-leave-off">Where Did We Leave Off?</h2>

<p>To summarize the earlier posts very briefly, we’ve defined selectors within our Redux modules that work on the module’s local section of the state tree.  We use these selectors in each module’s reducer and its tests.</p>

<p>We also need versions of these selectors that work on the global state tree.  We’ll use these in containers and thunk action creators both within the module, and potentially in other modules.</p>

<p>In order to get from a local selector to a global selector, we need to know how to get from the root of the state tree to the module’s local section of the tree.  The main app reducer knows how to do that.  So the main part of the app could be the one to apply that knowledge to create globalized selectors.  However, since we need access to those globalized selectors within the module, we end up with a circular dependency:</p>

<p><img class="center" src="https://randycoulman.com/images/redux_circular_dependency.png" alt="'Circular Dependency'" title="Circular Dependency" /></p>

<p>In <a href="https://randycoulman.com/blog/2016/09/27/modular-reducers-and-selectors/">Modular Reducers and Selectors</a>, we talked about the “textbook” ways of solving the cyclic dependency problem:</p>

<ul>
  <li>
    <p>Apply the <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">Dependency Inversion Principle</a> by extracting something within the module that both the app and the rest of the module depend on; or</p>
  </li>
  <li>
    <p>Create a new module that both the app and the module depend on.</p>
  </li>
</ul>

<p>We looked at <a href="http://jaysoo.ca/2016/02/28/organizing-redux-application/">Jack Hsu’s approach</a>, which is to define a constant within the module.  This constant is used to globalize the selectors and is also used by the main app reducer to specify where in the state tree the module’s reducer is mounted.  This a form of the <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">Dependency Inversion Principle</a> approach.</p>

<p>We also looked at living with a bit of duplication.  The app reducer specifies where to mount the module’s reducer in the state tree, and we duplicate that knowledge within the module in order to globalize the selectors.  Up until now, that’s been my approach, though I still like Jack’s idea as well.</p>

<h2 id="code-splitting">Code-Splitting</h2>

<p>In all of this discussion about modular Redux applications, I didn’t understand one of the biggest advantages of a modular Redux architecture: code-splitting.  In a large application, you often want to load only the parts of your code that are needed for a particular section of the application.  A good modular structure can make it much easier to define the boundaries of the split.</p>

<p>But how do you code-split a Redux application when there is a single store?</p>

<p>This is where Nicholas Gallagher comes in.  His post, <a href="http://nicolasgallagher.com/redux-modules-and-code-splitting/">Redux modules and code-splitting</a>, tackles this question and comes up with a really nice approach involving a reducer registry.</p>

<p>As a side-effect, this reducer registry is an elegant solution to the circular dependency problem.  It takes Jack’s idea of extracting a constant within the module and combines it with the “create a new module that both the app and the module depend on” approach.</p>

<h2 id="what-does-it-look-like">What Does It Look Like?</h2>

<p>I won’t repeat all of Nicholas’ code here, but the basic idea is that there is no more top-level app reducer that pulls in all of the module reducers.  Instead, there is a <code class="highlighter-rouge">ReducerRegistry</code> in a separate module.</p>

<p>In the main part of the application, we create the Redux store by combining all of the reducers that the <code class="highlighter-rouge">ReducerRegistry</code> knows about.</p>

<p>Each module in turn registers itself with the <code class="highlighter-rouge">ReducerRegistry</code> using its own <code class="highlighter-rouge">moduleName</code> constant.  As a side benefit, this same <code class="highlighter-rouge">moduleName</code> constant can be used in other places, such as when <a href="https://github.com/CodingZeal/zeal-redux-utils#createactiontypes">creating action type constants for the module</a>.</p>

<p>The dependency structure ends up looking like this:</p>

<p><img class="center" src="https://randycoulman.com/images/fixed_circular_dependency.png" alt="'No More Circular Dependency'" title="No More Circular Dependency" /></p>

<p>I tested this approach in a sample application to see what it would look like.  It worked great and I’m happy with how it turned out.</p>

<p>I did run into one little gotcha that’s worth noting.</p>

<p>Before, I’d export my module reducer from the module’s <code class="highlighter-rouge">index.js</code> file so that it can be imported into the main app reducer:</p>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">Exporting the Reducer</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="nx">reducer</span> <span class="nx">from</span> <span class="s2">"./reducer"</span><span class="p">;</span>
</div></div><div data-line="2" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="3" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">export</span> <span class="nx">reducer</span><span class="p">;</span>
</div></div></pre></div></figure>

<p>There’s now no need to export the reducer, but we do need to import it somewhere so that our module bundler (e.g. Webpack) knows about it and includes it in the appropriate bundle.</p>

<p>There are a couple of ways to do this.</p>

<p>The reducer can register itself with the <code class="highlighter-rouge">ReducerRegistry</code>:</p>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">modules/todos/reducer.js</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="p">&#x7b;</span> <span class="nx">combineReducers</span> <span class="p">&#x7d;</span> <span class="nx">from</span> <span class="s2">"redux"</span><span class="p">;</span>
</div></div><div data-line="2" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="p">&#x7b;</span> <span class="nx">createReducer</span> <span class="p">&#x7d;</span> <span class="nx">from</span> <span class="s2">"zeal-redux-utils"</span><span class="p">;</span>
</div></div><div data-line="3" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="4" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="nx">reducerRegistry</span> <span class="nx">from</span> <span class="s2">"modules/reducerRegistry"</span><span class="p">;</span>
</div></div><div data-line="5" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="6" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="nx">moduleName</span> <span class="nx">from</span> <span class="s2">"./constants/moduleName"</span><span class="p">;</span>
</div></div><div data-line="7" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="8" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">const</span> <span class="nx">reducer</span> <span class="o">=</span> <span class="nx">createReducer</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">&#x7b;</span>
</div></div><div data-line="9" class="code-highlight-row numbered"><div class="code-highlight-line">  <span class="c1">// ...action handlers go here...</span>
</div></div><div data-line="10" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="p">&#x7d;);</span>
</div></div><div data-line="11" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="12" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nx">reducerRegistry</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">moduleName</span><span class="p">,</span> <span class="nx">reducer</span><span class="p">);</span>
</div></div><div data-line="13" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="14" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">export</span> <span class="k">default</span> <span class="nx">reducer</span><span class="p">;</span>
</div></div></pre></div></figure>

<p>Then, the module’s <code class="highlighter-rouge">index.js</code> file can import the reducer without re-exporting it:</p>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">modules/todos/index.js</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="s2">"./reducer"</span><span class="p">;</span>
</div></div></pre></div></figure>

<p>Another option is to move the registration of the reducer into the module’s <code class="highlighter-rouge">index.js</code> file:</p>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">modules/todos/reducer.js</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="p">&#x7b;</span> <span class="nx">combineReducers</span> <span class="p">&#x7d;</span> <span class="nx">from</span> <span class="s2">"redux"</span><span class="p">;</span>
</div></div><div data-line="2" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="p">&#x7b;</span> <span class="nx">createReducer</span> <span class="p">&#x7d;</span> <span class="nx">from</span> <span class="s2">"zeal-redux-utils"</span><span class="p">;</span>
</div></div><div data-line="3" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="4" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">export</span> <span class="k">default</span> <span class="nx">createReducer</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">&#x7b;</span>
</div></div><div data-line="5" class="code-highlight-row numbered"><div class="code-highlight-line">  <span class="c1">// ...action handlers go here...</span>
</div></div><div data-line="6" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="p">&#x7d;);</span>
</div></div></pre></div></figure>

<figure class="code-highlight-figure"><figcaption class="code-highlight-caption"><span class="code-highlight-caption-title">modules/todos/index.js</span></figcaption><div class="code-highlight"><pre class="code-highlight-pre"><div data-line="1" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="nx">reducerRegistry</span> <span class="nx">from</span> <span class="s2">"modules/reducerRegistry"</span><span class="p">;</span>
</div></div><div data-line="2" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="3" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="nx">moduleName</span> <span class="nx">from</span> <span class="s2">"./constants/moduleName"</span><span class="p">;</span>
</div></div><div data-line="4" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="kr">import</span> <span class="nx">reducer</span> <span class="nx">from</span> <span class="s2">"./reducer"</span><span class="p">;</span>
</div></div><div data-line="5" class="code-highlight-row numbered"><div class="code-highlight-line"> </div></div><div data-line="6" class="code-highlight-row numbered"><div class="code-highlight-line"><span class="nx">reducerRegistry</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="nx">moduleName</span><span class="p">,</span> <span class="nx">reducer</span><span class="p">);</span>
</div></div></pre></div></figure>

<p>Either way works, but I lean toward the latter approach because it allows the reducer to stand on its own and only code outside of itself determines how to hook it into the main application reducer.</p>

<p>Note that I’ve used <code class="highlighter-rouge">createReducer</code> from <a href="https://github.com/CodingZeal/zeal-redux-utils#createreducer">zeal-redux-utils</a> here, but that’s an implementation detail.  You can define your reducers however you want.</p>



]]>
    </content>
  </entry>

  <entry>
    <title type="html">Introspection and DoubleAgents</title>
    
    <link rel="alternate" type="text/html" href="https://randycoulman.com/blog/2018/06/05/introspection-and-doubleagents/"/>
    
    <id>/blog/2018/06/05/introspection-and-doubleagents</id>
    <published>2018-06-05T05:38:23-07:00</published>
    <updated>2018-06-05T05:38:23-07:00</updated>
    <author>
      <name>Randy Coulman</name>
      <uri>https://randycoulman.com/</uri>
    </author>
    <content type="html" xml:base="https://randycoulman.com/" >
<![CDATA[

<p>I recently added support for several introspection methods to the <a href="https://randycoulman.com/blog/2013/04/30/double-agents-a-test-double-library-for-visualworks-smalltalk/">DoubleAgents</a> test double library for VisualWorks Smalltalk.</p>

<p>While there are often better solutions, Smalltalk provides several methods for introspecting the class of an object or the inheritance hierarchy of a class.  These methods include <code class="highlighter-rouge">#isKindOf:</code> and <code class="highlighter-rouge">#isMemberOf:</code> for instances and <code class="highlighter-rouge">#includesBehavior:</code>, <code class="highlighter-rouge">#inheritsFrom:</code>, and <code class="highlighter-rouge">#isDirectSubclassOf:</code> for classes.</p>

<p>Up until now, the DoubleAgents library didn’t do anything special with these methods.  That would have been OK, but because of some internal implementation details it didn’t even allow mocking or stubbing <code class="highlighter-rouge">#isKindOf:</code> and <code class="highlighter-rouge">#isMemberOf:</code> at all.</p>

<p>I ran into a situation where it made sense to use <code class="highlighter-rouge">isKindOf:</code>. I wanted to be able to test the code using DoubleAgents, but found I was unable to.</p>

<p>I decided to make some changes to DoubleAgents to support these methods.</p>

<p>DoubleAgents has two kinds of test doubles:</p>

<ul>
  <li>
    <p>Standalone doubles completely replace a collaborator.</p>
  </li>
  <li>
    <p>In-place doubles (also known as partial doubles) are “normal” objects that have one or more methods replaced by a mock or a stub for a given test.  In-place doubles can be instance-side doubles, class-side doubles, or “any instance” doubles.</p>
  </li>
</ul>

<p>With the latest changes to DoubleAgents:</p>

<ul>
  <li>
    <p>All in-place doubles now respond properly to <code class="highlighter-rouge">#isKindOf:</code> and <code class="highlighter-rouge">#isMemberOf:</code> by default.  Since they are partial doubles, they should act like the original object or class they are doubling unless told to do otherwise by mocking or stubbing a method.</p>
  </li>
  <li>
    <p>In-place class doubles also respond properly to <code class="highlighter-rouge">#includesBehavior:</code>, <code class="highlighter-rouge">#inheritsFrom:</code>, and <code class="highlighter-rouge">#isDirectSubclassOf:</code>.</p>
  </li>
  <li>
    <p>Standalone doubles DO NOT pretend to be <code class="highlighter-rouge">#isKindOf:</code> or <code class="highlighter-rouge">#isMemberOf:</code> the class they are doubling.  Standalone doubles only respond to messages that are explicitly mocked or stubbed.</p>
  </li>
  <li>
    <p>It is now possible for any kind of double (in-place or standalone) to stub or mock these introspection messages.  Previously, it was not possible to mock or stub <code class="highlighter-rouge">#isKindOf:</code> and <code class="highlighter-rouge">#isMemberOf:</code>.</p>
  </li>
</ul>

<p>I have published these changes as version 22 in the <a href="http://www.cincomsmalltalk.com/CincomSmalltalkWiki/Public+Store+Repository">Cincom Public Store Repository</a> and put a snapshot of the current version on <a href="https://github.com/randycoulman/DoubleAgents">GitHub</a>.</p>

<p>The latest version has also been included as a contributed package in the about-to-be-released <a href="http://www.cincomsmalltalk.com/main/products/visualworks/">VisualWorks Smalltalk 8.3.1</a>.</p>



]]>
    </content>
  </entry>

</feed>
