<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="127398" data-post-id="127398">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Fl4m3Ph03n1x" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Fl4m3Ph03n1x/120/11709_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Fl4m3Ph03n1x
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hello <a class="mention" href="/u/mark_lemberg" rel="nofollow">@mark_lemberg</a> and welcome !</p>
<p>Could you elaborate on why you agree with Dave and how you would apply his opinion to the piece of code I provide in the question?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127398" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-127398" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127398"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="127491" data-post-id="127491">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dimitarvp" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/120/38664_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dimitarvp
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I think looking for universal rules would not ever work and is a distraction in general. I’ll post one of mine though since it proved itself as a time saver many times.</p>
<p>I draw the line at how complex would a file be for me to parse by eyeballing. For most simple(-ish) GenServers I leave everything in one file. This gives me the peace of mind that I can easily find whatever I need for functionality XYZ in file <code>xyz.ex</code>.</p>
<p>It is only when a module and its responsibilities grow big that I’d look into splitting it into multiple files. And even then I’d analyse probable feature envy and refactor into several new modules. Very rarely have I split a singular module into several files (interface / implementation / runtime artifacts).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127491" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-127491" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127491"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="127506" data-post-id="127506">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="peerreynders" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/peerreynders/120/5826_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  peerreynders
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Another goal of <a href="https://pragdave.me/blog/2017/07/13/decoupling-interface-and-implementation-in-elixir.html" rel="noopener nofollow ugc">the article</a> seemed to be <a href="https://www.win.tue.nl/~wstomv/edu/2ip30/references/criteria_for_modularization.pdf" rel="noopener nofollow ugc">encapsulation</a> of data inside the process.</p>
<p>In objects the advantage of encapsulation is two-fold:</p>
<ul>
<li>only the object’s methods can mutate the internal data</li>
<li>client objects couple with the interface (API), not the structure of the internal data.</li>
</ul>
<p>In Elixir values are immutable so mutating a data structure is not an issue (though a name can be rebound). However if clients have to access the data structure directly they become coupled.</p>
<p><em>When</em> it is desirable to treat the data structure as <em>opaque</em> then all access needs to go through module functions to decouple the caller from the internal structure. While this type of “encapsulation” isn’t enforced, it is often good enough.</p>
<p>So in the article it was surprising to me that the API was <a href="https://pragdave.me/blog/2017/07/13/decoupling-interface-and-implementation-in-elixir.html#bring-on-the-server" rel="noopener nofollow ugc">modified</a> for the server version when in fact all that was needed was to go from:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">@type names() :: map()

@spec new() :: names()
@spec lookup(n, k) :: {:ok, v} | :error when n: names(), k: term(), v: term()
@spec store(n, k, v) :: n when n: names(), k: term(), v: term()
</code></pre>
<p>to</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">@type names() :: pid()

@spec new() :: names()
@spec lookup(n, k) :: {:ok, v} | :error when n: names(), k: term(), v: term()
@spec store(n, k, v) :: n when n: names(), k: term(), v: term()
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127506" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-127506" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127506"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="127628" data-post-id="127628">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="pragdave" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/120/1042_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  pragdave
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Programming Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="Fl4m3Ph03n1x" data-post="1" data-topic="22193">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/fl4m3ph03n1x/48/11709_2.png" class="avatar"> Fl4m3Ph03n1x:</div>
<blockquote>
<p>It’s a fairly small file with 53 lines, but it has a couple of things that bother me:</p>
</blockquote>
</aside>
<p>I wouldn’t particularly argue against the code you have. I’m not sure I’d have the interface module unless I knew there’d be more implementations, and I’d do the types a little differently.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  @type via_tuple_without_value   :: {:via, module, {module, {module, any}}}
  @type via_tuple_with_value(val) :: {:via, module, {module, {module, any}, val}}
  @type via_tuple                 :: via_tuple_without_value | via_tuple_with_value(any)

  @spec via_tuple(tuple)      :: via_tuple_without_value
  @spec via_tuple(tuple, any) :: via_tuple_with_value(any)
</code></pre>
<p>If the main module has <em>just</em> the API, then adding the extra behaviour seems to obscure things to my eye,</p>
<p>To your point about splitting APIs, what you have here is exactly what I describe. The external Registry <em>is</em> the implementation (only without the useless name <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"> ) and this file <em>is</em> the API that delegates to it. Yes, it adds a little along the way, but not so much that it obscures its nature.</p>
<p>What I’m less keen on is the start_link/child_spec magic in here. As far as I can tell, the API code would still run fine if these two were moved into a separate module: in fact the API would run fine any time there is a Registry process called <code>Clint.ProcessRegistry</code> running. So I might do a little refactoring:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Clint.ProcessRegistry do

  @registry_name __MODULE__

  @type via_tuple_without_value   :: {:via, module, {module, {module, any}}}
  @type via_tuple_with_value(val) :: {:via, module, {module, {module, any}, val}}
  @type via_tuple                 :: via_tuple_without_value | via_tuple_with_value(any)

  @spec lookup(tuple) :: [{pid, any}]
  def lookup(key),
  do: Registry.lookup(@registry_name, key)


  @spec update_with_value(tuple, any) :: {any, any} | :error
  def update_with_value(key, new_value),
  do: Registry.update_value(@registry_name, key, fn _old_value -&gt; new_value end )


  @spec via_tuple(tuple) :: via_tuple_without_value
  def via_tuple(key),
  do: {:via, Registry, {@registry_name, key}}


  @spec via_tuple(tuple, any) :: via_tuple_with_value(any)
  def via_tuple(key, value),
  do: {:via, Registry, {@registry_name, key, value}}

  
  #############################################################################
  
  defmodule Server do
    
    @registry_name Clint.ProcessRegistry
    
    def start_link,
    do: Registry.start_link(keys: :unique, name: @registry_name)

    def child_spec(_) do
      Supervisor.child_spec(
        Registry,
        id: @registry_name,
        start: {__MODULE__, :start_link, []}
      )
    end
  end
end
</code></pre>
<p>I haven’t run this, so it might be total BS.</p>
<p>I’m not keen in the duplication of the registry name between the two modules, but I couldn’t quickly come up with an alternative which wasn’t even worse <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>The two things I prefer about this solution are:</p>
<ol>
<li>
<p>The API and the server stuff are separate, so there’s no need for a behaviour module, and</p>
</li>
<li>
<p>The use of <code>__MODULE__</code> is disambiguated: before it was used both as a process name and as the module passed to the supervisor, which made it harder for my few remaining neurons to work out what was going on.</p>
</li>
</ol>
<h3><a name="p-127628-but-1" class="anchor" href="#p-127628-but-1" aria-label="Heading link" rel="nofollow"></a>But…</h3>
<p>Honestly, what’s important here isn’t whether a particular structure is right or wrong. The most important thing is that we’re discussing it, and thinking about it.</p>
<p>Nicely done.</p>
<p>Dave</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127628" data-batch-url="/posts/batch_likers">
                        8
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-127628" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127628"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="127687" data-post-id="127687">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Fl4m3Ph03n1x" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Fl4m3Ph03n1x/120/11709_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Fl4m3Ph03n1x
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you so much for your criticism.</p>
<p>It is clear from your post I have a long way to learn about giving my opinions, you share yours in such a nice way that in comparison I look like Hitler when sharing mine <img src="https://forum.elixirforum.com/images/emoji/apple/smiley.png?v=15" title=":smiley:" class="emoji" alt=":smiley:" loading="lazy" width="20" height="20"></p>
<p>I quite like the idea of separating the Server from the API, but at the same time there is that pesky indirection argument people like to use against this methodology.</p>
<p>I can see the value in both, I just need to find the line between when it makes sense to use one model or the other.</p>
<p>Once again, thanks for your reply!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127687" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-127687" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127687"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="127711" data-post-id="127711">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="pragdave" data-post="15" data-topic="22193">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/48/1042_2.png" class="avatar"> pragdave:</div>
<blockquote>
<p>What I’m less keen on is the start_link/child_spec magic in here. As far as I can tell, the API code would still run fine if these two were moved into a separate module</p>
</blockquote>
</aside>
<p>IMO, starting required processes is the part of the API of an abstraction, just like constructor is the part of the API of a class, or <code>new</code> is the part of the API of some data abstraction (e.g. <code>Map</code>).</p>
<p>With the proposed code split, in order to use <code>Clint.ProcessRegistry</code>, I need to first start <code>Clint.ProcessRegistry.Server</code>. In my view this makes the usage and the subsequent reading experience more complicated. Having to start <code>Foo</code> in order to use <code>Foo</code> seems more intuitive to me.</p>
<p>Of course, there are some cases where it’s worth splitting the abstraction API, for example if the API becomes too large and covers a bunch of semi-related concerns. In such scenarios, I’d prefer to have the top-level module, e.g. <code>Foo</code> providing the childspec, and then have other API concerns exposed via “submodules”, such as <code>Foo.ApiConcern1</code>, <code>Foo.ApiConcern2</code>, … That way, if I want to use different aspects of <code>Foo</code>, I have to start <code>Foo</code>, which, again, seems more intuitive than having to start <code>Foo.Server</code>.</p>
<p>Either way, the exact approach I’d prefer is IMO highly dependent on the context. In this simple case, given the code size, I’d definitely keep the start API (i.e. the childspec) together with the rest of the API.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127711" data-batch-url="/posts/batch_likers">
                        5
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-127711" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127711"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="127747" data-post-id="127747">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="pragdave" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/120/1042_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  pragdave
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Programming Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="sasajuric" data-post="17" data-topic="22193">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/48/991_2.png" class="avatar"> sasajuric:</div>
<blockquote>
<p>IMO, starting required processes is the part of the API of an abstraction, just like constructor is the part of the API of a class, or <code>new</code> is the part of the API of some data abstraction (e.g. <code>Map</code> ).</p>
</blockquote>
</aside>
<p>Thanks for highlighting this, because I think it’s at the core of much of my thinking.</p>
<p>The Beam is a pretty unique environment, and it makes us think about many things differently. One major difference is in the way we have to think about process lifecycle <em>as well as</em> process functionality.</p>
<p>Take this particular example. We have a global registry with an API (<code>lookup</code>, <code>update</code>, and so on). In most other languages, that would be the end of it. But on the Beam the conventional way to have global state is to have a named process, and so we now have lifecycle code that starts this process.</p>
<p>But I suggest that this code (the <code>start_link</code> and <code>child_spec</code>) are <em>not</em> part of the API of the Registry. They are part of the lifecycle, the scaffolding needed to get the Registry working on the Beam. 99% of the time, it will only be invoked as a tuple passed as a child spec to some top-level supervisor. It never gets called by people using the module.</p>
<p>So that’s at the root of my concern. We mix traditional APIs and BEAM lifecycle management code into the same bucket of functions. And, as a result, I think we often conflate supervision with functionality. But the two are separate: the supervision tree is an expression of process lifecycle, and not process functionality.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127747" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-127747" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127747"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="127751" data-post-id="127751">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="pragdave" data-post="18" data-topic="22193">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/48/1042_2.png" class="avatar"> pragdave:</div>
<blockquote>
<p>But I suggest that this code (the <code>start_link</code> and <code>child_spec</code> ) are <em>not</em> part of the API of the Registry. They are part of the lifecycle, the scaffolding needed to get the Registry working on the Beam. 99% of the time, it will only be invoked as a tuple passed as a child spec to some top-level supervisor. It never gets called by people using the module.</p>
</blockquote>
</aside>
<p>I regard the fact that these funs are (usually) not called directly as a mechanical detail. To me they are still first and foremost a part of the same API, because these functions cover one aspect of how we use the abstraction. IMO starting a thing is a part of using the thing, and so it’s a part of the API of that thing.</p>
<p>Separating into two modules doesn’t change that - the <code>Registry</code> docs still need to instruct me to start <code>Registry.Server</code> before I can use <code>Registry</code> functions. So the API surface remains the same, except now it’s split across two modules. Now I need to read docs of both modules because they cross-reference themselves (e.g. docs for <code>Server</code> explain how some childspec/start_link option affects the behaviour of some function in the “API” module and vice-versa). I personally find this confusing.</p>
<p>I can agree that starting might be considered as a separate API concern, so splitting these two concerns might sometimes be valid, but IMO that’s not the case in this simple example. I feel that such split here brings more usage/reading distractions with little to no practical gain.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127751" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-127751" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127751"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="127756" data-post-id="127756">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="pragdave" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/120/1042_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  pragdave
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Programming Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="sasajuric" data-post="19" data-topic="22193">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/48/991_2.png" class="avatar"> sasajuric:</div>
<blockquote>
<p>I regard the fact that these funs are (usually) not called directly as a mechanical detail. To me they are still first and foremost a part of the same API, because these functions cover one aspect of how we use the abstraction. IMO starting a thing is a part of using the thing, and so it’s a part of the API of that thing.</p>
</blockquote>
</aside>
<p>If it’s a “mechanical detail” then I’d argue that it’s definitely something that isn’t important when reading. It’s just housekeeping noise.</p>
<p>That’s why I have the ability in the Component library to have globals started automatically.</p>
<p>But it’s all just style, and there’s nothing  but time and experience to judge which is preferable. And indeed, as you say, there’s no one right answer.</p>
<p>I push these points, though, because the community seems to be very happy to continue to write code as it has been written for the last 20 years, and that sets off little alarm bells in the agile part of my brain. Unless we try new ways of doing things (rather than just talking about them) we’ll never learn if the current way is indeed the best. I don’t want to debate. I want to code <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127756" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-127756" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127756"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="127761" data-post-id="127761">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="sasajuric" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sasajuric/120/991_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  sasajuric
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Elixir In Action</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="pragdave" data-post="20" data-topic="22193">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/48/1042_2.png" class="avatar"> pragdave:</div>
<blockquote>
<p>the community seems to be very happy to continue to write code as it has been written for the last 20 years</p>
</blockquote>
</aside>
<p>The style might not have changed much within BEAM languages (it actually has, but more on that later), but I feel that this style is mostly unknown to non-BEAM languages. Since in those languages people typically don’t have lightweight processes, they usually resort to running multiple OS processes to split runtime activities. So for example, to start an external process registry, we would have a registry as an external OS process (e.g. etcd). To start/stop it, we would use some CLI API, probably in combination with an external lifecycle manager, such as systemd. Then we’d use some internal API (e.g. REST, possibly wrapped with some library functions) to interact with the running component. Such approach is in my view close to what you seem to be suggesting.</p>
<p>After using that approach myself for many years, and then also using the “BEAM way” for quite some time too, I empirically came to conclusion that I prefer the latter. I find it simpler, and at the same time more powerful and flexible. YMMV of course <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>In addition, it’s worth remembering that <code>child_spec/1</code> thing is Elixir specific, and it’s in fact a fairly new addition to Elixir. FWIW, I think it’s one of the more interesting changes introduced by Elixir, because it makes things closer to the way I personally think about code. With <code>child_spec</code> &amp; support by Elixir <code>Supervisor</code>, a component/service can fully encapsulate the details of how its started, which makes things simpler for the user. Stick <code>Foo</code> or <code>{Foo, arg}</code> where you want it in the supervision tree, and you can now interact with <code>Foo</code> using the functions from the same module (or “submodules”). To me that seems very straightforward. Again, YMMV <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="pragdave" data-post="20" data-topic="22193">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/pragdave/48/1042_2.png" class="avatar"> pragdave:</div>
<blockquote>
<p>I don’t want to debate. I want to code</p>
</blockquote>
</aside>
<p>Well, you said earlier in this thread that it’s important that we’re discussing it, so here I am, discussing it <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="127761" data-batch-url="/posts/batch_likers">
                        4
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/how-would-pragdave-separate-this-code/22193/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-127761" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="127761"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #20"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/22193/load_more?page=3">Load more posts (6 remaining)</a>
</div></template></turbo-stream>