<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://mycodingtales.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://mycodingtales.com/" rel="alternate" type="text/html" /><updated>2026-06-18T16:42:52-03:00</updated><id>https://mycodingtales.com/feed.xml</id><title type="html">mycodingtales</title><subtitle>All about my coding tales. Some times they don&apos;t involve coding at all!</subtitle><author><name>Luiz Felipe G. Pereira</name></author><entry><title type="html">The Human AI Interface</title><link href="https://mycodingtales.com/the-human-ai-interface/" rel="alternate" type="text/html" title="The Human AI Interface" /><published>2026-06-18T08:00:00-03:00</published><updated>2026-06-18T08:00:00-03:00</updated><id>https://mycodingtales.com/the-human-ai-interface</id><content type="html" xml:base="https://mycodingtales.com/the-human-ai-interface/"><![CDATA[<p>Recently I’ve noticed a weird set of phrases that I had never read before, getting popular. The first one was “defense in-depth”. I’ve been working in web development for 15+ years so that wasn’t a common term for me. I thought: that’s a concise way of putting it. I’ll add it to my dictionary!</p>

<p>Eventually when arguing with an AI against some defensive programming it was doing (check X is not nil, even though it’s impossible to be nil due to the context), it valiantly defended its decision mentioning it was “defense in-depth”. That immediately tickled my spidey senses. Was my colleague merely repeating the slop machine’s output as his own? But I ended up dismissing it as a mere coincidence.</p>

<p>Then the same happened with more terms like “belts and suspenders solution” and “load-bearing changes” that eventually also got spewed by the AI. This particular colleague dove in head first in the AI hype train and, after seeing several of their gigantic pull requests with comments about “belts and suspenders”, I knew these were not really their words anymore.</p>

<p>It’s not that the these terms are new or wrong. They are merely not commonly used inside my sphere. But now when using these tools we’re, intentionally or not, conforming to it. Were they using a better word to describe something or copying what the AI said? I don’t know anymore. Not really.</p>

<p>Later they argued that a problem was unsolvable because the AI couldn’t do it. But even smart people seem to forget the fact that AI is not only incomplete, but also very easily falls into bad answers. One of the most common phrases I see on the AI output now is “that’s the real culprit”. Only to then repeat a variation of this phrase five minutes later after you correct it. Ah, now that’s the smoking gun!</p>

<p>But this is not really about my colleague. It’s now spread everywhere and I don’t know how to feel about this. I want to hate it but it does also enable so many good things for me. I can code much more than before, even though I don’t understand or learn as much. But I’m still using it as a tool and it’s clear that many fully depend on it. They delegate everything they can and really don’t want to… think.</p>

<p>Instead of the future where the AI extends us, we’re heading into a different version where the meat bag is the middleman but the content is all AI. Fuck that. I don’t care about what the AI has to say, I care about what you, fellow human being, has to say.</p>

<p>At what point do we become the tool for AI?</p>]]></content><author><name>Luiz Felipe G. Pereira</name></author><category term="ai" /><category term="tech" /><summary type="html"><![CDATA[Recently I’ve noticed a weird set of phrases that I had never read before, getting popular. The first one was “defense in-depth”. I’ve been working in web development for 15+ years so that wasn’t a common term for me. I thought: that’s a concise way of putting it. I’ll add it to my dictionary!]]></summary></entry><entry><title type="html">We need to talk about interactors</title><link href="https://mycodingtales.com/we-need-to-talk-about-interactors/" rel="alternate" type="text/html" title="We need to talk about interactors" /><published>2023-05-26T08:00:00-03:00</published><updated>2023-05-26T08:00:00-03:00</updated><id>https://mycodingtales.com/we-need-to-talk-about-interactors</id><content type="html" xml:base="https://mycodingtales.com/we-need-to-talk-about-interactors/"><![CDATA[<p>I’ve noticed a bit of a trend within the Ruby community in recent years that worries me: every other codebase is now attempting to use interactors. That’s not inherently bad, but as we’ll discuss in this article, it has some unforeseen consequences. Luckily I haven’t seen much of this bleed into libraries but, on application code, it has been surprisingly common. Interestingly enough the first time I saw it my reaction was not negative at all: it looked like a very clean way to organize procedures (or commands) keeping things relatively interchangeable.</p>

<p>After months of extensive usage and delving deeper into the codebases, I have noticed several inherent flaws within the usage of this pattern that cannot be overlooked. Moreover, I have observed the formation of bad habits among developers who rely on this pattern. In this article we’re going to be diving into the issues that stem from it and why you should be careful when using it.</p>

<h1 id="what-are-interactors-anyways">What are interactors anyways?</h1>

<p>Most interactor gems say they are an implementation of the command pattern and a way to encapsulate what your application does. As <a href="https://en.wikipedia.org/wiki/Command_pattern">wikipedia</a> tells us, it’s a design pattern to encapsulate how to perform an action.</p>

<p>But the real origin is more likely from Uncle Bob’s Clean Architecture, where he calls them <strong>Use Case Interactors</strong>. These are classes that encapsulate a use-case with pure data structures. These classes are responsible for taking these data structures, performing the use-case and returning another data structure. There’s a <a href="https://www.youtube.com/watch?v=asLUTiJJqdE">pretty good lecture</a> available online where he goes over some of it.</p>

<p>In Ruby they have emerged as an alternative to <em>Service Objects</em>, which took over the Rails world for a while (<code class="language-plaintext highlighter-rouge">app/services</code> anyone?), inspired by Services from <a href="https://en.wikipedia.org/wiki/Domain-driven_design">Domain Driven Design</a>. These classes encapsulate business logic that does not belong in typical models. They are somewhat similar but not quite the same.</p>

<p>To summarize: an interactor encapsulates a single use-case from your application with pure data structures decoupling that logic from the delivery mechanisms. Whether you use a CLI or an HTTP API to create a user, it doesn’t matter for the use-case.</p>

<p>We could represent an user registration use-case with an interactor like this:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">UserRegistration</span>
  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="nb">name</span><span class="p">:,</span> <span class="n">email</span><span class="p">:)</span>
    <span class="c1"># ...</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">call</span>
    <span class="no">User</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="ss">name: </span><span class="vi">@name</span><span class="p">,</span> <span class="ss">email: </span><span class="vi">@email</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Then controllers, rake tasks, CLIs or any other delivery mechanisms can use this interactor to register a user. The responsibility of the delivery mechanism is to translate their inputs into the data structures used by the interactors and then translate the results back. As an example, a controller could use this.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">UsersController</span>
  <span class="k">def</span> <span class="nf">create</span>
    <span class="n">user</span> <span class="o">=</span> <span class="no">UserRegistration</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">user_params</span><span class="p">)</span>
    <span class="n">head</span><span class="p">(</span><span class="n">user</span><span class="p">.</span><span class="nf">valid?</span> <span class="p">?</span> <span class="ss">:ok</span> <span class="p">:</span> <span class="ss">:bad_request</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>The interactor pattern is a great abstraction that makes it easy to decouple business logic from other concerns, promoting the consistent re-use of your use-cases.</p>

<h1 id="where-interactors-go-wrong">Where interactors go wrong</h1>

<p>Given the interactor pattern is a useful one even if you’re not trying to strictly follow the Clean Architecture philosophy, what exactly is the problem here? We’re now going to dive into the concrete problems of using interactors without proper care.</p>

<h2 id="a-specific-interpretation-of-interactors">A specific interpretation of interactors</h2>

<p>We have some examples of gems implementing this pattern. To cite a few we have: <a href="https://github.com/collectiveidea/interactor">interactor</a>, <a href="https://github.com/aaronmallen/activeinteractor">active interactor</a> and <a href="https://github.com/AaronLasseigne/active_interaction">active interaction</a>.</p>

<p>Aside from adding confusion with the renaming of the concept to interaction, one of the advantages often cited by these gems is the fact that they use an unified interface: the mighty <code class="language-plaintext highlighter-rouge">call</code> method. No more guessing if your <code class="language-plaintext highlighter-rouge">AuthenticationService</code> responds to <code class="language-plaintext highlighter-rouge">call</code>, <code class="language-plaintext highlighter-rouge">perform</code> or <code class="language-plaintext highlighter-rouge">run</code>!</p>

<p>Another feature that’s often included into it is the concept of a result. Whenever you call <code class="language-plaintext highlighter-rouge">call</code> (ha) you receive a result back telling you if the operation was successful or not. This is pretty handy when chaining things together and for the typical boilerplate that props up in Rails controllers.</p>

<p>Here’s a simple interactor using the <a href="https://github.com/collectiveidea/interactor">interactor</a> gem and the accompanying controller:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">CreatePost</span>
  <span class="kp">include</span> <span class="no">Interactor</span>

  <span class="k">def</span> <span class="nf">call</span>
    <span class="n">post</span> <span class="o">=</span> <span class="no">Post</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="nf">attributes</span><span class="p">)</span>
    <span class="n">post</span><span class="p">.</span><span class="nf">save</span> <span class="p">?</span> <span class="n">post</span> <span class="p">:</span> <span class="n">context</span><span class="p">.</span><span class="nf">fail!</span><span class="p">(</span><span class="ss">error: </span><span class="s2">"Could not create post"</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="k">class</span> <span class="nc">PostsController</span>
  <span class="k">def</span> <span class="nf">create</span>
    <span class="n">result</span> <span class="o">=</span> <span class="no">CreatePost</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">post_params</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">result</span><span class="p">.</span><span class="nf">success?</span>
      <span class="n">render</span> <span class="ss">:show</span>
    <span class="k">else</span>
      <span class="n">flash</span><span class="p">[</span><span class="ss">:error</span><span class="p">]</span> <span class="o">=</span> <span class="n">result</span><span class="p">.</span><span class="nf">error</span>
      <span class="n">redirect_back_or_to</span> <span class="n">posts_path</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>This example already shows basic error handling with results. Some of them include <code class="language-plaintext highlighter-rouge">ActiveSupport::Errors</code> somewhere (typically in the result or the interaction itself), allowing you to return user-readable errors directly to your views. These libraries also assume interactors have a single interface and have some form of telling the caller if the result was successful or not.</p>

<p>Here we have the first issue: nowhere in the Clean Architecture’s definition of interactors it’s stated that they must share a single interface. In fact, each use-case may have completely different interfaces. Some might have results, some might not. Some might return objects, others simple primitives. They accept and return different data structures suited for each use-case.</p>

<p>Unfortunately for (what I imagine was) convenience or ease of use, implementations settled on using this single interface for all interactors. Given this is the first real contact developers have with this pattern, it’s already established as a rule even though it’s a library specific decision.</p>

<p>Above all the abstraction of interactors, as the name states if we used the full name, is to wrap a use-case. In other words, this should wrap the <strong>outer shell</strong> of your application. Interactors should not be used for the implementation details of said use-cases. They should use application-independent entities and other classes with application business logic to perform whatever the use-case states and return a result, if there’s a need for one.</p>

<p>Based on the current implementations, we’re led down a path that narrows the original interactors idea in a very specific way. Perhaps if we kept the original use-case interactors name, most of the issues I’m going to expose here wouldn’t exist, but here we are.</p>

<h2 id="everything-is-an-interactor">Everything is an interactor</h2>

<p>Even though they were meant to represent use-cases, I’ve found that invariably they start to be used for internal details of other interactors.</p>

<p>After all, they have a simple enough interface which leads to focused classes that are more likely to follow the <a href="https://en.wikipedia.org/wiki/Single-responsibility_principle">Single Responsibility Principle</a>. The simple interface also makes them easy to be called in chains. Some libraries even provide classes to facilitate that.</p>

<p>But the biggest reason of all is the “hack” that they enable for one of the most commonly known problems of development: naming. Naming interactors is extremely easy compared to naming abstractions. They represent actions, which means they become verbs. Naming everything as a verb almost completely removes the need to think about any abstractions. Let’s take a look at an example.</p>

<p>Say we want to register a user, send him a welcome email then assign him a role. If we write everything as interactors. We have <code class="language-plaintext highlighter-rouge">ValidateUser</code> followed by <code class="language-plaintext highlighter-rouge">CreateUser</code>, <code class="language-plaintext highlighter-rouge">SendWelcomeEmail</code> and finally <code class="language-plaintext highlighter-rouge">AssignRoleToUser</code>. All of these wrapped around a bigger interactor called <code class="language-plaintext highlighter-rouge">RegisterUser</code> which calls these interactors in sequence.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">RegisterUser</span>
  <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">user_params</span><span class="p">:)</span>
    <span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">user_params</span><span class="p">)</span>
    <span class="no">ValidateUser</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="ss">user: </span><span class="n">user</span><span class="p">)</span>
    <span class="no">CreateUser</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="ss">user: </span><span class="n">user</span><span class="p">)</span>
    <span class="no">SendWelcomeEmail</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="ss">user: </span><span class="n">user</span><span class="p">)</span>
    <span class="no">AssignRoleToUser</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="ss">user: </span><span class="n">user</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>It’s easy to see how it makes things easier. Since the interface is extremely generic, naming is no longer a concern, our classes are small and have a single responsibility, this code looks clean.</p>

<p>This is similar to how we would implement this in a more functional style. The <code class="language-plaintext highlighter-rouge">RegisterUser</code> works like a higher order function composing other functions forwarding the initial parameters and the results of each function to the next one. So now instead of having interactors being used as a single wrapper on a use-case, they are used as wrappers for everything. A single interactor then calls N other interactors, that in turn call M other interactors and so on.</p>

<p>At this point I’d argue a conscious decision should have been made. Are you going to use a functional style of coding for all your business logic or do you want to use an object oriented approach?</p>

<p>This decision is, more often than not, made without intention. Which in turn leads the codebase down a path that requires a very different style of programming. If this <em>is</em> intentional, you will have to deal with the issues mentioned here using functional patterns knowing the trade-offs you are making. If that’s the case then congratulations! It’s a totally valid alternative and you’ve actively chosen to use it. However if this was not an intentional decision (and in my experience this is the most common scenario), it will inevitably lead to all of the issues we’ll discuss here.</p>

<p>Once this pattern of turning everything into an interactor takes hold, it will force you to mix and match OO and functional concepts every step of the way. It affects error handling, how you deal with duplication, abstractions, naming and more. While I’m not saying they can’t be mixed, it should be done with care and consideration.</p>

<h2 id="one-abstraction-to-rule-them-all">One abstraction to rule them all</h2>

<p>Interactors need some way of passing arguments to them. This varies depending on the implementation but generally speaking they receive a big hash as an argument. Some libraries create DSLs to describe that contract while others leave that as a Hash. Regardless of the implementation details, this defines how you call these classes.</p>

<p>Ruby’s hashes are extremely good and easy to use, which in turn leads them to be overused. It’s like a higher form of primitive obsession. Although hashes are not strictly primitives, for a dynamic language like Ruby, they might as well be.</p>

<p>The problem here is not limited to interactors but it’s definitely amplified by it. So let’s look at a few examples of how this hurts our code. Let’s use the <a href="https://github.com/AaronLasseigne/active_interaction">active interaction</a> gem this time, and look at our user registration again. I’m also going to make it a bit more complex to make the issue more apparent.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">RegisterUser</span> <span class="o">&lt;</span> <span class="no">ActiveInteraction</span><span class="o">::</span><span class="no">Base</span>
  <span class="n">string</span> <span class="ss">:name</span>
  <span class="n">string</span> <span class="ss">:email</span>
  <span class="n">string</span> <span class="ss">:ip</span>
  <span class="nb">hash</span> <span class="ss">:identity_provider</span><span class="p">,</span> <span class="ss">default: </span><span class="kp">nil</span>
  <span class="n">record</span> <span class="ss">:organization</span><span class="p">,</span> <span class="ss">default: </span><span class="kp">nil</span>
  <span class="n">boolean</span> <span class="ss">:send_welcome_email</span><span class="p">,</span> <span class="ss">default: </span><span class="kp">false</span>

  <span class="k">def</span> <span class="nf">execute</span>
    <span class="k">if</span> <span class="n">ip_blocked?</span>
      <span class="n">errors</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="ss">:ip</span><span class="p">,</span> <span class="s2">"IP is blocked"</span><span class="p">)</span> 
      <span class="k">return</span>
    <span class="k">end</span>

    <span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">name: </span><span class="nb">name</span><span class="p">,</span> <span class="ss">email: </span><span class="n">email</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">user</span><span class="p">.</span><span class="nf">save</span>
      <span class="n">user</span><span class="p">.</span><span class="nf">create_identity</span><span class="p">(</span><span class="n">identity_provider</span><span class="p">)</span> <span class="k">if</span> <span class="n">identity_provider</span>
      <span class="n">organization</span><span class="p">.</span><span class="nf">users</span> <span class="o">&lt;&lt;</span> <span class="n">user</span> <span class="k">if</span> <span class="n">organization</span>
      <span class="n">send_email</span> <span class="k">if</span> <span class="n">send_welcome_email</span>
    <span class="k">else</span>
      <span class="n">errors</span><span class="p">.</span><span class="nf">merge!</span><span class="p">(</span><span class="n">user</span><span class="p">.</span><span class="nf">errors</span><span class="p">)</span>
    <span class="k">end</span>
    <span class="n">user</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>In this scenario we have some logic to fail the registration if the IP is blocked, create an identity based on the given identity provider, an organization in which we have to add the user to and a flag to determine if we should send a welcome email afterwards. This is a common scenario on a web-application.</p>

<p>There are some issues here but I’m gonna focus on the primitive obsession: we actually have multiple distinct concerns that are hidden inside of the arguments. Some of the arguments relate to the user, some to the origin of the registration and others to allow the caller to customize the behavior. However these are effectively hidden because we are using only primitives as inputs.</p>

<p>When using these interactor gems it’s common to use only raw primitives or <code class="language-plaintext highlighter-rouge">ActiveRecord</code> objects as inputs. It encourages primitive obsession because hashes can describe pretty much anything and so the input of interactors is rarely the POROs that should be used instead. Additionally, since we are using a DSL to describe this, we don’t have the usual parameter list issue that would be caught by a default RuboCop check.</p>

<p>The Clean Architecture interactors state that we have data structures as inputs and outputs of interactors but it does not necessarily mean they need to be primitives. But implementing these as hashes makes it easy to add as many parameters as you’d like without thinking about any other abstractions required.</p>

<p>If we were to separate the concerns appropriately, the IP blocking should not even be inside of the interactor since it’s a delivery method specific concern. You won’t care about IPs if you call this interaction from the CLI.</p>

<p>For the user related arguments like name, email, identity, organization, we have an user input object that’s missing. If we have a simpler use-case where you only need a name and email, following the <a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it">YAGNI</a> principle we could avoid the abstraction. But as you add more concerns attached to the user we’re registering, an object should encapsulate all that.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">UserInput</span> <span class="o">=</span> <span class="no">Struct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:email</span><span class="p">)</span>
</code></pre></div></div>

<p>Now, I’m pretty sure most of you will already be analyzing this example and rubbing their hands getting ready to point out flaws or alternative implementations that would be much better. But that’s not the point here: my point is about incentives.</p>

<p>This pattern will repeat itself for every single interactor. They will be copied, pasted and altered for new requirements because creating a new interactor is extremely easy, while thinking about the objects involved and abstractions is not.</p>

<p>New requirements can usually be described as new verbs or small changes to the existing ones. The interactor abstraction fits the bill for pretty much any concept. It’s a class that does something and returns something, after all! Almost anything can be framed as an action.</p>

<h2 id="incentives-matter">Incentives matter</h2>

<p>As I alluded to before, the issue here is with the incentives. Once you have interactors you will <strong>want</strong> to add more interactors for everything as it will be the default choice. We shift from thinking about objects and how they interact into a rote repetition of adding new commands and/or making them more configurable. Instead of having objects that represent the input, the operation, the user, the notification system, the validator and all else, we now think in terms of procedures/commands.</p>

<p>It is especially bad for juniors and new hires. Most of the time developers look at what has been done before and replicate it. You don’t go against the grain as the default option. If commands are used everywhere, developers are likely to follow suit and maintain the pattern.</p>

<p>We might even know that using an interactor is not the best choice for the given problem. But given that’s how it’s done everywhere else, even if you do bite the bullet and come up with a more OO approach, we need to sell that to the team. It’s a time consuming effort while the incentive is to simply cave in and repeat the pattern.</p>

<h2 id="roles-and-interfaces">Roles and interfaces</h2>

<p>Interface definition is really important when creating our abstractions. The interactor interface is very open and it obviously does not cover every use case, so you cannot effectively represent anything complex with it.</p>

<p>We can’t, for example, have a subscriber abstraction with interactors. If we define that interface as responding to <code class="language-plaintext highlighter-rouge">#subscribe(object)</code> and <code class="language-plaintext highlighter-rouge">#unsubscribe(object)</code> messages, the narrow definition of interactors can’t handle that. That’s somewhat expected since a subscriber is not really a command or a use-case.</p>

<p>Regardless, with interactors as the standard, you would certainly find <code class="language-plaintext highlighter-rouge">SubscribeToSomething</code> interactors, alongside another <code class="language-plaintext highlighter-rouge">UnsubscribeFromSomething</code> for unsubscribing. Once again, this is very much a functional approach.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">## Interactors</span>
<span class="k">class</span> <span class="nc">Subscribe</span>
  <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">object</span><span class="p">,</span> <span class="n">subscriber</span><span class="p">)</span>
    <span class="n">object</span><span class="p">.</span><span class="nf">subscribers</span> <span class="o">&lt;&lt;</span> <span class="n">subscriber</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="k">class</span> <span class="nc">Unsubscribe</span>
  <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">object</span><span class="p">,</span> <span class="n">subscriber</span><span class="p">)</span>
    <span class="n">object</span><span class="p">.</span><span class="nf">subscribers</span><span class="p">.</span><span class="nf">delete_if</span> <span class="p">{</span> <span class="n">_1</span> <span class="o">==</span> <span class="n">subscriber</span> <span class="p">}</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="c1">## OO</span>

<span class="k">class</span> <span class="nc">Thing</span>
  <span class="k">def</span> <span class="nf">subscribe</span><span class="p">(</span><span class="n">subscriber</span><span class="p">)</span>
    <span class="n">subscribers</span> <span class="o">&lt;&lt;</span> <span class="n">subscriber</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">unsubscribe</span><span class="p">(</span><span class="n">subscriber</span><span class="p">)</span>
    <span class="n">subscribers</span><span class="p">.</span><span class="nf">delete_if</span> <span class="p">{</span> <span class="n">_1</span> <span class="o">==</span> <span class="n">subscriber</span> <span class="p">}</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="c1"># Or with a module</span>

<span class="k">module</span> <span class="nn">EventEmitter</span>
  <span class="k">def</span> <span class="nf">subscribe</span><span class="p">(</span><span class="n">subscriber</span><span class="p">)</span>
    <span class="n">subscribers</span> <span class="o">&lt;&lt;</span> <span class="n">subscriber</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">unsubscribe</span><span class="p">(</span><span class="n">subscriber</span><span class="p">)</span>
    <span class="n">subscribers</span><span class="p">.</span><span class="nf">delete_if</span> <span class="p">{</span> <span class="n">_1</span> <span class="o">==</span> <span class="n">subscriber</span> <span class="p">}</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">subscribers</span>
    <span class="vi">@subscribers</span> <span class="o">||=</span> <span class="p">[]</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="k">class</span> <span class="nc">Thing</span>
  <span class="kp">include</span> <span class="no">EventEmitter</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Interactors don’t really have any state and act like mere functions. When using them we no longer think in terms of roles like a subscriber, event emitter, etc. We only think about actions. We lose interfaces and don’t gain any of the advantages that functional programming gives us, since we don’t adopt other concepts like: immutability, currying, higher-order functions and so many others.</p>

<p>With the original use-case interactors and an object oriented approach, we would use objects - including ones with complex interfaces - to accomplish what we need. If we want to turn everything into a function, then we must also use everything else that comes with functional programming too or we end up with a poor man’s functional nightmare.</p>

<p>The roles and interfaces that are so important for OO are completely lost with this approach. Many developers already struggle with basic modeling so this is disastrous. There’s a precedent in place to almost completely circumvent thinking about your models and domain. Simply add another action.</p>

<h3 id="duplication">Duplication</h3>

<p>Let’s take a look at another real world example related to interactors I’ve come across. The operation in question published a specific resource to different online platforms. My job was to refactor that code and it was pretty clear from the get-go what had happened - later confirmed by colleagues.</p>

<p>I’m sure many of you will have had the same experience: the system is built to integrate with one platform, then we want to add support for a new one. The code was similar but not quite the same and, since interactors were the standard, the usual was done: a new interactor was added. Later, when a third platform needed to be integrated, we ended up with three interactors and a switch case depending on the platform type.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">PublishThing</span>
  <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
    <span class="k">case</span> <span class="n">platform</span>
    <span class="k">when</span> <span class="no">FirstPlatform</span>
      <span class="no">PublishFirstPlatform</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
    <span class="k">when</span> <span class="no">SecondPlatform</span>
      <span class="no">PublishSecondPlatform</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
    <span class="k">when</span> <span class="no">ThirdPlatform</span>
      <span class="no">PublishThirdPlatform</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Upon analyzing this code, it became apparent that there were methods that were re-created multiple times with slight differences, entire workflows that were also re-created and, in reality, the overall procedure did not change significantly for each platform. The aftermath was a ton of duplication, bugs and slight differences between each implementation that made the code brittle and hard to maintain.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Platform</span>
  <span class="c1"># platform specific way of publishing</span>
  <span class="k">def</span> <span class="nf">publish</span><span class="p">(</span><span class="n">thing</span><span class="p">);</span> <span class="k">end</span>

  <span class="c1"># platform specific way of doing something after publishing</span>
  <span class="k">def</span> <span class="nf">after_publish</span><span class="p">(</span><span class="n">thing</span><span class="p">);</span> <span class="k">end</span>

  <span class="c1"># other platform shared attributes/methods</span>
<span class="k">end</span>

<span class="c1"># platform specific implementations</span>
<span class="k">class</span> <span class="nc">FirstPlatform</span> <span class="o">&lt;</span> <span class="no">Platform</span><span class="p">;</span> <span class="k">end</span>
<span class="k">class</span> <span class="nc">SecondPlatform</span> <span class="o">&lt;</span> <span class="no">Platform</span><span class="p">;</span> <span class="k">end</span>
<span class="k">class</span> <span class="nc">ThirdPlatform</span> <span class="o">&lt;</span> <span class="no">Platform</span><span class="p">;</span> <span class="k">end</span>

<span class="k">class</span> <span class="nc">PublishThing</span>
  <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">thing</span><span class="p">,</span> <span class="n">platform</span><span class="p">)</span>
    <span class="n">platform</span><span class="p">.</span><span class="nf">publish</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
    <span class="c1"># Shared publishing logic</span>
    <span class="n">platform</span><span class="p">.</span><span class="nf">after_publish</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>It was very clear to me how interactors shaped that code. Instead of having a single operation with different classes encapsulating the differences, we have three distinct operations that all respond to <code class="language-plaintext highlighter-rouge">#call</code>. Creating a new interactor and implementing everything there is easier than thinking about the abstractions needed to make the entire system following the open/closed principle. The reality is we only have one use-case: publish the thing.</p>

<p>While there is a threshold where duplication is accepted and even encouraged, once you exceed that point, reasoning about the system and its abstractions becomes crucial for a better codebase. But interactors steer you into the duplication path. Be it intentional or unintentional it ends up littering our code more often than not.</p>

<p>Most times duplication isn’t obvious at first and only apparent after multiple instances of the behavior show up. The right time to refactor something is not set in stone and creating abstractions early can be even worse depending on how much you know about the problem space.</p>

<p>Developers, much like all humans, take the easier route and add to that <code class="language-plaintext highlighter-rouge">case</code> statement without even considering potential duplications. This is, of course, not strictly an issue with interactors, but it’s most certainly accentuated by them. The default is to always add a new class that “does the deed” and add to the conditional.</p>

<p>In this particular case we had to understand where the platforms diverged and keep in mind that there is only one use-case. But since most of that code was copied over and edited, it was not obvious. Incentives that are amplified by interactors led to unintended duplication.</p>

<h2 id="results-and-error-handling">Results and error handling</h2>

<p>Another area that is usually affected by this pattern is error handling. It’s very common to have to distinguish between different failure types. For example, we may need to abort execution on a specific error and retry on another.</p>

<p>With interactors we then have to make some non-optimal choices. We can fail the interactor and add errors to it. But this then means the caller has to rely on strings or error types:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># on the interactor</span>
<span class="n">errors</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="ss">:base</span><span class="p">,</span> <span class="ss">:my_custom_error</span><span class="p">)</span> <span class="k">unless</span> <span class="n">valid?</span>
</code></pre></div></div>

<p>And then our caller has to check the result with something like:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">result</span> <span class="o">=</span> <span class="no">Interactor</span><span class="p">.</span><span class="nf">call</span>
<span class="k">if</span> <span class="n">result</span><span class="p">.</span><span class="nf">failed?</span>
  <span class="k">if</span> <span class="n">result</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">added?</span><span class="p">(</span><span class="ss">:base</span><span class="p">,</span> <span class="ss">:my_custom_error</span><span class="p">)</span>
    <span class="c1"># handle custom error</span>
  <span class="k">elsif</span> <span class="n">result</span><span class="p">.</span><span class="nf">errors</span><span class="p">.</span><span class="nf">added?</span><span class="p">(</span><span class="ss">:base</span><span class="p">,</span> <span class="ss">:another_custom_error</span><span class="p">)</span>
    <span class="c1"># handle another custom error</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Not ideal to say the least. We’re back to checking strings/symbols to control our flow. Another option is to use the return value for this:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">result</span> <span class="o">=</span> <span class="no">Interactor</span><span class="p">.</span><span class="nf">call</span>
<span class="k">if</span> <span class="n">result</span><span class="p">.</span><span class="nf">failed?</span>
  <span class="k">if</span> <span class="n">result</span><span class="p">.</span><span class="nf">error_type</span> <span class="o">==</span> <span class="ss">:my_custom_error</span>
    <span class="c1"># handle custom error</span>
  <span class="k">elsif</span> <span class="n">result</span><span class="p">.</span><span class="nf">error_type</span> <span class="o">==</span> <span class="ss">:another_custom_error</span>
    <span class="c1"># handle another custom error</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>Not ideal either. You have to add this value to the return object to identify the type of error that occurred.</p>

<p>Handling errors beyond basic boolean results forces you to use unconventional techniques to achieve a functionality that our language provides naturally: exceptions.</p>

<p>An exception allows you to create a specific type of error and stop the execution. It also includes contextual information about the error and you can customize it to your heart’s content. After all, it’s simply a PORO.</p>

<p>I know what you’re thinking: you should not use exceptions for control flow! I agree that there are cases where exceptions are not a great fit. The most typical example is input validation. But aside from that, almost every error should stop the execution of the program and be dealt with accordingly. An alternative can be found on languages like Go where pretty much every function call looks like this:</p>

<div class="language-go highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ok</span><span class="p">,</span> <span class="n">err</span> <span class="o">:=</span> <span class="n">doSomething</span><span class="p">()</span>
<span class="k">if</span> <span class="n">err</span> <span class="o">!=</span> <span class="no">nil</span> <span class="p">{</span>
  <span class="c">// deal with it</span>
<span class="p">}</span>
</code></pre></div></div>

<p>We can debate the trade-offs from these approaches but that’s a moot point: we are in Ruby, we have exceptions and diverging from it should not be done by default.</p>

<p>Using exceptions with interactors is not prohibited and we can have both use-cases. But interactors change the default behavior. As the caller you are now <strong>required</strong> to check the results as if every operation has a failure mode. Even if you use bang versions of <code class="language-plaintext highlighter-rouge">call</code>, which most gems give you, we’re now artificially creating an exception with a generic type that we cannot easily distinguish.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># using call!</span>
<span class="k">begin</span>
  <span class="no">Interactor</span><span class="p">.</span><span class="nf">call!</span>
<span class="k">rescue</span> <span class="no">InteractorFailure</span>
  <span class="c1"># What actually failed here?</span>
<span class="k">end</span>

<span class="c1"># traditional exceptions</span>
<span class="k">begin</span>
  <span class="n">object_or_class</span><span class="p">.</span><span class="nf">do_something</span>
<span class="k">rescue</span> <span class="no">SpecificError</span>
<span class="k">rescue</span> <span class="no">AnotherSpecificError</span>
<span class="k">rescue</span> <span class="no">GenericError</span>
<span class="k">end</span>
</code></pre></div></div>

<p>As another example of the consequences of this change, it becomes very common to encounter interactors called <code class="language-plaintext highlighter-rouge">ListSomething</code> in which there is no failure mode. You either get a list or we should have an exception. But we are then forced to check results or use the generic bang version of call obscuring the original exception.</p>

<p>If we interpret interactors as an implementation of the command pattern, then this is not a command, it’s a query! What do we gain from wrapping that?</p>

<p>Ruby isn’t like Go and we don’t have a compiler to tell us when we forgot to check for an error like Elm or Haskell. As a result many times interactors are called without the bang or explicit result checking, causing errors to go unchecked. This in turn results in exceptions down the call chain (usually whiny nil errors). It’s surprisingly common to see interactors being called without error checking and having errors being silently swallowed.</p>

<p>One could argue that’s an issue with dynamic languages (although most compiled languages don’t check for logical errors) but once again this is a moot point: we are in Ruby and that’s not the language’s default.</p>

<p>I cannot tell you how many times I’ve had to investigate exceptions like <code class="language-plaintext highlighter-rouge">InteractorException: X is invalid</code>. Upon a closer look, there are dozens of interactors that can raise the same error. And given the possibility of some interactors being called without the bang, masking the real origin of the error is common.</p>

<p>These issues with error handling are amplified for juniors. When do you return a false result and add a string error message? When do you raise an exception? When do you use the bang method? Is returning a <code class="language-plaintext highlighter-rouge">falsy</code> result the same as a runtime exception? Should you wrap all exceptions in your interactor to keep the interactor pattern? I’ve seen many senior developers using this incorrectly because interactors incentivize boolean operation results.</p>

<p>The answers to these questions are not clear and they will vary depending on various factors. When using interactors you are faced with this question constantly and I have yet to see a codebase that properly enforces these rules. The idea of returning a boolean result for every operation only adds confusion with little to no benefit when it comes to error handling.</p>

<p>Returning “NaN” for zero divisions as JavaScript does is not how we do it in Ruby. Our standard library will raise a <code class="language-plaintext highlighter-rouge">ZeroDivisionError</code> for a reason, even though that is a known failure use-case for a division. For some reason though, when it comes to interactors, we suddenly feel like it’s okay to handle errors with boolean values by default.</p>

<h3 id="do-you-really-need-an-interactor">Do you really need an interactor?</h3>

<p>This all leads to this question: do you really need an interactor? Let’s take a look at another example using the <a href="https://github.com/collectiveidea/interactor">interactor</a> gem:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">SendOnlineNotification</span>
  <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">user</span><span class="p">:)</span>
    <span class="no">WebSocket</span><span class="p">.</span><span class="nf">send_notification</span><span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="ss">:online</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>On this implementation, we assume the interactor does not have a failure state and any errors that happen will have to be exceptions. So if that’s the case then why is this an interactor at all? It adds no real value to us.</p>

<p>Alternatively we make this even worse:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">SendOnlineNotification</span>
  <span class="kp">include</span> <span class="no">Interactor</span>

  <span class="k">def</span> <span class="nf">call</span>
    <span class="no">WebSocket</span><span class="p">.</span><span class="nf">send_notification</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="nf">user</span><span class="p">,</span> <span class="ss">:online</span><span class="p">)</span>
  <span class="k">rescue</span>
    <span class="n">context</span><span class="p">.</span><span class="nf">fail!</span><span class="p">(</span><span class="ss">message: </span><span class="s1">'websocket.fail'</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>

<p>With this alternative we are now wrapping exceptions into a failure. As a consequence we are losing all of the context from the exception and replacing a meaningful error, stack trace and message with a cryptic <code class="language-plaintext highlighter-rouge">message</code> string (most gems translate the key with i18n). On other interactor gems you’d add <code class="language-plaintext highlighter-rouge">websocket.fail</code> to the interactor’s <code class="language-plaintext highlighter-rouge">errors</code> attribute but the point remains.</p>

<p>Regardless, it is now the responsibility of the caller to check for this failure while having no meaningful way of differentiating types of errors. We’ve effectively destroyed the entire purpose of exceptions in order to satisfy the boolean result nature of interactors.</p>

<p>There are cases where wrapping exceptions into boolean results make sense but those are, in my experience, the exception (pun intended) and not the rule.</p>

<p>The harsh reality is that we do not need to use the command pattern in the absolute majority of cases. The desire to pigeonhole all business logic into boolean outcomes makes error handling way more difficult than it should be and ends up causing a lot more harm than good.</p>

<h2 id="you-sure-look-like-a-nail">You sure look like a nail</h2>

<p>It does not matter how much we want to believe in theories, reality always hits you in the face. Interactors are very addictive to use. When you compare them to the classic MVC with service objects, it seems like you now have a place to put everything you never knew where to put before. Everything can be an interactor because everything does <em>something</em>! And everything returns a result too! On top of that now we can chain it all together with ease while keeping classes small. Finally, no more fussing with names!</p>

<p>On every codebase with interactors I’ve come across, they spread like wildfire. Once that happens problems like the ones we discussed arise and become common. I’ve seen interactors being used even to instantiate objects: <code class="language-plaintext highlighter-rouge">BuildSomeObject.call</code>. I guess why not, right?</p>

<p>Honestly, I’d love to say that this is a case of inexperienced and/or bad developers, but it’s not. No matter how experienced you are, when faced with deadlines or other factors that force us to compromise, we will take the easiest path and duplicate the behavior. That’s might be the right option sometimes, as Sandi Metz put it before, <em>the wrong abstraction is worse than duplication</em>. But once you introduce interactors, it’s almost inevitable that duplication becomes the default. Best case scenario we create those tech debt tickets: the ones we never work on because they’re not critical.</p>

<p>Navigating that maze of interactors with procedures calling procedures that call other sequential procedures becomes the norm. Domain objects are absent or rare, duplication is more common than before and yet we feel safe with every new interactor we add because it’s a small class with a simple interface that’s easy to name.</p>

<p>Interactors are a hammer and everything looks like a nail once you’re using it.</p>

<h2 id="if-its-so-bad-why-do-people-use-it">If it’s so bad, why do people use it?</h2>

<p>The first obvious reason would be to use the concept from Clean Architecture. The ideas behind it are solid and enticing for developers to implement, but we should always be careful of doing so in a void. This is a case where implementations took an idea and implemented it in a dangerous manner that ends up harming codebases more than helping them.</p>

<p>Another reason is because it somewhat forces developers to make small classes. I’ve lost count of how many times people said they improved their code with interactors because now we have smaller classes. But that’s a perfectly valid reason to create small classes, not for interactors! We trade so many language features, basic OO principles and add all of the drawbacks we’ve mentioned here for something we can achieve without it.</p>

<p>I’ve heard from others that using the single <code class="language-plaintext highlighter-rouge">#call</code> interface removes confusion on how to use each class. Well, I guess? But do we really gain anything from making every single object respond to the same generic interface? I’d argue it’s not worth the price.</p>

<p>There are way more reasons I haven’t heard of, so I’d love to learn about them if you have one.</p>

<h2 id="what-can-we-do-about-it">What can we do about it?</h2>

<p>If you need the command pattern, I’d suggest you simply write the code yourself. Honestly, creating an interface for commands and a class for results with POROs is extremely simple. If you do it yourself you can also take advantage of amazing Ruby features like types instead of hashes, positional/named arguments, exceptions and much more that is lost on these gems.</p>

<p>More importantly use it when you actually need a command pattern. Perhaps you need the ability to chain, rollback or store commands for later usage. That’s why the pattern was created in the first place so it’s a great tool for the job.</p>

<p>A dislike for the Service Objects pattern is one of the reasons the majority of the developers I’ve talked to turned to interactors in the first place. Services grew too large and developers don’t split those classes as much as they should. They don’t know what to call these concepts and/or where to put them, so interactors seem to solve that: <code class="language-plaintext highlighter-rouge">Verb.call</code> to the rescue. It’s so much easier to name classes as verbs and use the same interface everywhere but that comes at a cost.</p>

<p>If you really want to use interactors from Clean Architecture, then create those classes yourself and for the love of all that’s good only use them for use-cases! Define the interfaces for your use-case interactors yourself and create explicit contracts between your application and the delivery mechanisms. They should be the interface to your app and nothing more. Don’t use them for your internals. Rely as much as possible on your entities and POROs.</p>

<p>The main reason I wrote this article was to raise the flag that: <strong>interactors are not a silver bullet</strong>! It’s easy to forget this after they’ve been introduced to your codebase. Some might say this is obvious and, perhaps it should be. But if it really was, I wouldn’t feel like I had to write this after seeing the same problems happen on completely different codebases.</p>

<p>We don’t need these libraries to create good OO code. We can (and should) create more domain objects and strive to keep classes small at all times. There’s no substitute for good engineering and design. Sadly I can’t say “use <em>this</em> instead” because there is nothing that fits that bill. We’d all love to have an incredible hack that covers it all, but there isn’t one.</p>

<p>For me, coming back to those basic OOP examples like <code class="language-plaintext highlighter-rouge">Car -&gt; Engine -&gt; Piston -&gt; Fuel Injector</code> is something that always helps. It’s much harder with the abstract concepts we have to deal with, but it’s not impossible. Objects communicating through meaningful messages and classes representing these concepts are, for me, still the way to go.</p>

<p>Or if you do want to use functional programming, do so with all of its tools. Don’t cherry pick one piece without all of the other concepts and patterns needed for a good FP codebase.</p>

<p>So if there is only one thing you pick up from this article, let it be: if you want to promote good object oriented programming patterns in your codebase, be very careful with interactors.</p>

<p>It invariably comes down to taking the time to think through our solutions. Nothing can substitute that.</p>]]></content><author><name>Luiz Felipe G. Pereira</name></author><category term="code" /><summary type="html"><![CDATA[I’ve noticed a bit of a trend within the Ruby community in recent years that worries me: every other codebase is now attempting to use interactors. That’s not inherently bad, but as we’ll discuss in this article, it has some unforeseen consequences. Luckily I haven’t seen much of this bleed into libraries but, on application code, it has been surprisingly common. Interestingly enough the first time I saw it my reaction was not negative at all: it looked like a very clean way to organize procedures (or commands) keeping things relatively interchangeable.]]></summary></entry><entry><title type="html">Stop Pretending Your Company is Remote</title><link href="https://mycodingtales.com/stop-pretending-your-company-is-remote/" rel="alternate" type="text/html" title="Stop Pretending Your Company is Remote" /><published>2022-05-01T08:06:13-03:00</published><updated>2022-05-01T08:06:13-03:00</updated><id>https://mycodingtales.com/stop-pretending-your-company-is-remote</id><content type="html" xml:base="https://mycodingtales.com/stop-pretending-your-company-is-remote/"><![CDATA[<p>The pandemic made evident how much work can, and should, be different. The forced change to accommodate remote workflows also brought to light what I like to call “virtual offices”. Unlike truly remote friendly workplaces optimized for asynchronous communication, these aim to merely transport the office into a virtual space keeping the same unnecessary constraints of synchronous work intact, only replacing shoulder taps with Zoom calls. I’d love if we collectively agreed to start using a more appropriate name for these. They are office-less companies but they are not remote-friendly.</p>

<p>Signs of these environments are not hard to spot. Unplanned meetings appearing on your calendar all the time, managers and co-workers starting every message with “hello, how are you doing?” and waiting for a response, the common “can we do a quick call?” instead of writing down what you need, employees adjusting their work hours to join meetings at absurd times and the typical conveyor belt of pings on Slack. Even companies that were born remote, not forced into it, often slowly devolve into this fake remote state.</p>

<p>If what I wrote so far resonated with you, and especially if you can influence this, please stop this farce and start truly supporting remote work. Real remote work does not force employees to bend their work hours even when they many times say “it’s not a problem”. After all, what will they say other than that? There’s a huge power imbalance present. Even more so because many times these are the people that don’t have time zones neatly aligned with the company’s executives main hours.</p>

<p>A remote friendly company does not depend on employees’ self-defined work hours or presence indicators. It does not force you - directly or indirectly - to put statuses on yourself to say you are eating or will be right back. Do you need a poop emoji status if you have to use the restroom? What if it’s a long one? Most likely you’ll take your phone with you just in case you need to show you’re available!</p>

<p>Remote is about getting things done asynchronously. Is it perfect for every type of work? Of course not. But should we default to copying the inefficient processes of physical offices because you’re used to “talking it out”? No!</p>

<p>Stop pretending you’re a remote friendly company because you don’t force everyone to be on a physical office. Take real steps to make processes asynchronous. Train people, that are many times on their first remote jobs, to think and act differently. Be conscious of the power imbalances involved that can make us take the phone to the toilet not for HN or Reddit, but for Slack. Incentivize written communication and by all means use synchronous meetings when necessary, but don’t default to it.</p>

<p>Remove the shackles of synchronous work and replace it with trust. Give us the power to deliver the best work we can and finally see all the benefits of remote.</p>

<p><a href="https://news.ycombinator.com/item?id=31315971">HN discussion</a></p>]]></content><author><name>Luiz Felipe G. Pereira</name></author><category term="remote" /><summary type="html"><![CDATA[The pandemic made evident how much work can, and should, be different. The forced change to accommodate remote workflows also brought to light what I like to call “virtual offices”. Unlike truly remote friendly workplaces optimized for asynchronous communication, these aim to merely transport the office into a virtual space keeping the same unnecessary constraints of synchronous work intact, only replacing shoulder taps with Zoom calls. I’d love if we collectively agreed to start using a more appropriate name for these. They are office-less companies but they are not remote-friendly.]]></summary></entry></feed>