<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="111893" data-post-id="111893">
  <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="19248">
<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>Sure: DirWalker uses Stream.resource internally. But it has a broader API than just streams, and so it uses a GenServer to provide that.</p>
</blockquote>
</aside>
<p>Glancing at the code of DirWalker, I see no reasons for it to be a GenServer. It could just as well be a plain functional module and still be able to keep state, perform read-aheads, and provide streaming. I didn’t thoroughly read the code, but I don’t see any current API concern which would justify using a separate process. If I was writing something like this, I’d make it a plain functional module.</p>
<p>I feel a similar way about your <a href="https://pragdave.me/blog/2019/01/10/where-does-state-live.html" rel="noopener nofollow ugc">last post about state</a>. You seem to argue that using a separate process for the game separates concerns and improves encapsulation. That’s certainly true, but I think that in your example you can get those same benefits by using plain functional abstractions (i.e. functions and modules). For a detailed discussion on this you can check out my <a href="https://www.theerlangelist.com/article/spawn_or_not" rel="noopener nofollow ugc">To spawn, or not to spawn?</a> post.</p>
<p>The gist of that long post is that I believe that design concerns, such as encapsulation, separation of concerns, or the shape of the API, do not play any weight in deciding whether something should run in a separate process or not. The reasons for spawning another process are IMO almost (if not completely) mechanical. I reach for a process if I want runtime benefits, such as concurrency and/or fault-tolerance. If I don’t get any of these benefits, then I stick with plain functions/modules.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="111893" data-batch-url="/posts/batch_likers">
                        16
                      </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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-111893" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111893"
                     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 #21"></div>
  </section>
</div>
    <div class="postbit" id="111899" data-post-id="111899">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="JEG2" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/JEG2/120/936_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  JEG2
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Designing Elixir Systems with OTP</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Wow.  Thanks for the lesson!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="111899" 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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-111899" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111899"
                     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 #22"></div>
  </section>
</div>
    <div class="postbit" id="111916" data-post-id="111916">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ericmj" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ericmj/120/25920_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ericmj
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Elixir Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="OvermindDL1" data-post="21" data-topic="19248">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>I.E. reductions are reduced based on the mailbox size of the receiver process.</p>
</blockquote>
</aside>
<p>This is no longer true since OTP 21, because it wasn’t a good enough backpressure mechanism.</p>
<aside class="quote no-group" data-username="OvermindDL1" data-post="21" data-topic="19248">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/overminddl1/48/2677_2.png" class="avatar"> OvermindDL1:</div>
<blockquote>
<p>Also, as a side note, using <code>call</code> instead of <code>cast</code> is not backpressure, it is forcing a queue size of 1 instead of N between those two processes, which only helps when one process is sending a lot of messages to another, not when a lot of processes are sending a message to one (which it can hurt).</p>
</blockquote>
</aside>
<p>It is one form of backpressure, it is arguably not enough in some circumstances though.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="111916" data-batch-url="/posts/batch_likers">
                        7
                      </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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-111916" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111916"
                     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 #23"></div>
  </section>
</div>
    <div class="postbit" id="111919" data-post-id="111919">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-Elixir-Core-Team" data-username="ericmj" data-post="24" data-topic="19248">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ericmj/48/25920_2.png" class="avatar"> ericmj:</div>
<blockquote>
<p>This is no longer true since OTP 21, because it wasn’t a good enough backpressure mechanism.</p>
</blockquote>
</aside>
<p>Ah hah, I thought I recalled reading somewhere about a major change about it, thanks!  <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 group-Elixir-Core-Team" data-username="ericmj" data-post="24" data-topic="19248">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ericmj/48/25920_2.png" class="avatar"> ericmj:</div>
<blockquote>
<p>It is one form of backpressure, it is arguably not enough in some circumstances though.</p>
</blockquote>
</aside>
<p>Yep, there are many many forms for many many different situations, that’s why I like that ferd link I just found, it has a lot of good information there.  <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="111919" 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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-111919" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111919"
                     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 #24"></div>
  </section>
</div>
    <div class="postbit" id="111931" data-post-id="111931">
  <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="JEG2" data-post="20" data-topic="19248">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jeg2/48/936_2.png" class="avatar"> JEG2:</div>
<blockquote>
<p>Yeah, I tend to favor <code>call</code> for the reasons you outlined.</p>
</blockquote>
</aside>
<p>I did the same. Then, as part of my anti-cargoculting ethic, I tried switching over to making stuff async.</p>
<p>I found it more difficult at first, because I’ve spend a lifetime writing procedures. But once I got some simple patterns into my head, I find it’s actually quite fun.</p>
<p>My current mental model for programming is based to some extent on the idea that 10 years from now we’ll all be working on IoT stuff. In that environment it’s all one-way, transient, pubsub-y and so on. By practicing doing stuff async now, I’m hoping to start building the reflexes that’ll let me think about that future.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="111931" 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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-111931" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111931"
                     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 #25"></div>
  </section>
</div>
    <div class="postbit" id="111934" data-post-id="111934">
  <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="22" data-topic="19248">
<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 feel a similar way about your <a href="https://pragdave.me/blog/2019/01/10/where-does-state-live.html" rel="noopener nofollow ugc">last post about state </a>. You seem to argue that using a separate process for the game separates concerns and improves encapsulation. That’s certainly true, but I think that in your example you can get those same benefits by using plain functional abstractions (i.e. functions and modules).</p>
</blockquote>
</aside>
<p>In agree 100% about that particular example.</p>
<p>The problem with examples is coming up with something that demonstrates the stuff you want to demonstrate without also having tons of extra code. In this case, I wanted to demo the actual library.</p>
<aside class="quote no-group" data-username="sasajuric" data-post="22" data-topic="19248">
<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>The gist of that long post is that I believe that design concerns, such as encapsulation, separation of concerns, or the shape of the API, do not play any weight in deciding whether something should run in a separate process or not.</p>
</blockquote>
</aside>
<p>Couldn’t agree more. And in a case such as Task.async_stream, where the state is all effectively opaque to the outside world, it’s definitely a good idea.</p>
<p>But… the other side of the coin is that when a module lets someone else handle its state, it’s actually exposing its implementation to the outside world. Now you can always say “I’m passing you my state, but your code should treat it as an opaque type.” But my experience is that folks aways want to open the kimono.</p>
<p>A great example of this is the way the phoenix_ecto populates FormData from an ecto ChangeSet:</p>
<p>Here’s the code in phoenix_ecto/html:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">    def to_form(changeset, opts) do
      %{params: params, data: data} = changeset
      ...
</code></pre>
<p>Here we’re initializing fields in one module from fields in the state of an entirely different module: one that’s not even in the same top-level application. We’re coupling to the type of data (must be a map), the names of fields in that map, and the total internal structure of those fields. Make an internal change in ecto, and you could easily break phoenix_ecto.</p>
<p>Now that particular thing isn’t going to happen: it’s a small and very clever team working on both.</p>
<p>But, in the general case, I’d much, much rather see a guarantee of information hiding over the trivial cost of spawning another process.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="111934" 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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-111934" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111934"
                     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 #26"></div>
  </section>
</div>
    <div class="postbit" id="111946" data-post-id="111946">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="JEG2" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/JEG2/120/936_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  JEG2
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Author of Designing Elixir Systems with OTP</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group quote-modified" data-username="pragdave" data-post="27" data-topic="19248">
<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 trivial cost of spawning another process.</p>
</blockquote>
</aside>
<p>The CPU cost is very low, but I personally find the cognitive load added to the developers to be significant.  It goes from “you need to understand X” to “you need to understand a concurrent X,” doesn’t it?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="111946" 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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-111946" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111946"
                     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 #27"></div>
  </section>
</div>
    <div class="postbit" id="111949" data-post-id="111949">
  <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">
								<p>Only if it’s concurrent <img src="https://forum.elixirforum.com/images/emoji/apple/grinning_face.png?v=15" title=":grinning_face:" class="emoji" alt=":grinning_face:" loading="lazy" width="20" height="20"></p>
<p>A two_way function acts identically to a regular function call, but with added state.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="111949" 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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-111949" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111949"
                     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 #28"></div>
  </section>
</div>
    <div class="postbit" id="111958" data-post-id="111958">
  <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="27" data-topic="19248">
<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>We’re coupling to the type of data (must be a map), the names of fields in that map, and the total internal structure of those fields.</p>
</blockquote>
</aside>
<p>The changeset type is <a href="https://hexdocs.pm/ecto/Ecto.Changeset.html#t:t/1" rel="noopener nofollow ugc">publicly documented</a>, and so the data structure is part of the API. Changing the structure breaks the API, so it’s not an internal change.</p>
<p>Using struct matching would made this a bit more obvious:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">%Ecto.Changeset{params: params, data: data} = changeset
</code></pre>
<aside class="quote no-group" data-username="pragdave" data-post="27" data-topic="19248">
<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’d much, much rather see a guarantee of information hiding</p>
</blockquote>
</aside>
<p>You don’t get that even with GenServer. Peeking into the state and changing it is as easy as invoking <code>:sys.get_state</code> and <code>:sys.replace_state</code>.</p>
<aside class="quote no-group" data-username="pragdave" data-post="27" data-topic="19248">
<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>trivial cost of spawning another process</p>
</blockquote>
</aside>
<p>I don’t think that cost is trivial at all.</p>
<p>First, by moving from functions to processes, you’re changing the paradigm. All of the sudden, instead of <code>game = Game.something(game, ...)</code> we’re just writing <code>:ok = Game.something(game, ...)</code>. In other words we’re moving from immutable functional to side-effectful imperative.</p>
<p>This style now becomes similar to OO, except it has some extra issues. For example, it becomes easier to leak processes. If e.g. the game process traps exits, it won’t be immediately taken down when it’s parent terminates. If there’s some bug, the child might even linger on forever.</p>
<p>Another issue is that debugging becomes harder. If one process crashes, we’ll get cascading crashes (assuming no one in hierarchy is trapping exits), and that’s going to add a lot of log noise. If a crash happens in a “one-way” handler, the stack trace won’t be complete (i.e. you won’t be able to tell how did you arrive to that one-way handler). Tracing multiple processes is going to be harder than tracing a single one.</p>
<p>Going further, if an abstraction is process-based we can’t implement protocols for it. In a hierarchy of process-based entities, we can’t just invoke <code>Jason.encode</code> or <code>:erlang.term_to_binary</code> on the root element. Even ad-hoc debugging with <code>IO.inspect(game)</code> becomes unusable.</p>
<p>Yet another problem is passing the abstraction to other processes. If we pass data to another process, we make a copy, and two processes can safely work on the data concurrently. In contrast, when a pid is passed, it’s almost like pass-by-reference. So again we encounter a paradigmatic switch.</p>
<p>Moving to the performance realm, spawning a process and communicating with it is “cheap” (by some hand-wavy definition of cheap), but it’s still much more expensive than not using a process. In a tight loop where an abstraction is frequently accessed, the performance penalty might become really significant.</p>
<p>You might also experience weird timeouts here. Imagine you pass a million pieces of data to the abstraction in a one-way fashion (you seem to prefer that for mutations), and immediately after that invoke a getter. This might easily lead to a five-seconds timeout error.</p>
<p>Another problem is memory usage. A process overhead is about few kilobytes - an order of magnitude more compared to an empty map or a struct. So if we start creating a bunch of process based entities, and do this for every web request, the memory usage will skyrocket even in a moderately loaded system handling a few hundred or few thousand connected users.</p>
<p>This is further exacerbated by the fact that the data is copied across process boundaries. So in a two-way invocation of <code>Game.do_something(some_data)</code> we keep two copies of the data in memory, neither of which is garbage. Again, it’s usually not a problem, but overuse processes, multiply by the number of connected users, and you might find yourself in trouble.</p>
<p>Don’t get me wrong, I’m a huge fan of processes. Heck, the main focus of my book is on processes, and even in my aforementioned article I’ve used them extensively. Used judiciously, they can do wonders for our systems. But misused, they will bring a lot of harm with little to no good. I’m speaking from experience here, because I’ve spent my first few years of Erlang programming using processes for encapsulation (mostly influenced by my own OO heritage), and I’ve bumped into most of the issues mentioned above.</p>
<p>So tl;dr - no, I wouldn’t say that the cost of spawning a process is trivial <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="111958" data-batch-url="/posts/batch_likers">
                        20
                      </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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-111958" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111958"
                     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 #29"></div>
  </section>
</div>
    <div class="postbit" id="111960" data-post-id="111960">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="pragdave" data-post="27" data-topic="19248">
<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>Here we’re initializing fields in one module from fields in the state of an entirely different module: one that’s not even in the same top-level application. We’re coupling to the type of data (must be a map), the names of fields in that map, and the total internal structure of those fields. Make an internal change in ecto, and you could easily break phoenix_ecto.</p>
</blockquote>
</aside>
<p>Isn’t that how dependencies should work out? Have two applications, which want to work together, create an interface for how to work together (Phoenix.HTML.FormData / phoenix_html) and have a higher level application depending on both and implementing the interface (phoenix_ecto).</p>
<p>The type of a changeset is <a href="https://hexdocs.pm/ecto/3.0.6/Ecto.Changeset.html#t:t/0" rel="nofollow">documented</a> and therefore part of the public API, so I don’t really see a reason not to depend on it. Having accessors for those fields in Ecto.Changeset would have the benefit of ecto having more control over how data is extracted out of their struct and how they can refactor without breaking changes, but they seem to be certain that it won’t change (in a breaking fashion) in the future.</p>
<p>On the other hand MapSet is a map internally, but the community and the docs are very adamant in making sure that people do not depend on that implementation, especially as the implementation indeed was changed once already.</p>
<p>The benefit of having public types of data is that people can customize and add functionality running on the same datatype, while with opaque/hidden ones you’re limited by what the you get out of the box by the implementor. Like if you’re missing an accessor to a part of the data then you’re out of luck.</p>
<p>If one still pokes into opaque types it’s on their own to maintain that implementation detail. I don’t feel that artificially moving computation into processes for essentially making the data private would do us any good. See <a class="mention" href="/u/sasajuric" rel="nofollow">@sasajuric</a> for the reasons, which he added while I wrote this.</p>
<aside class="quote no-group" data-username="sasajuric" data-post="30" data-topic="19248">
<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>This style now becomes similar to OO, except it has some extra issues.</p>
</blockquote>
</aside>
<p>It feels like adding processes for data hiding, but introducing all the issues of distributed computation. Sure locally we don’t need to think to much about it as there’s no network involved, but it’s essentially that on the beam. The simplest example might even be timeouts. As soon as message passing is involved I need to be aware of how long a certain computation might take and how long I’d like to wait for it.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="111960" 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/pragdave-s-new-component-library-his-preferred-way-of-building-apps/19248/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-111960" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="111960"
                     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 #30"></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/19248/load_more?page=4">Load more posts (14 remaining)</a>
</div></template></turbo-stream>