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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>The problem I encounter everywhere is that the VOs are Ecto schema structs which, wherever they’re used, couples all the storage-agnostic logic to the database structure.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="381614" 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/value-object-and-primitive-obsession-code-smell/39529/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-381614" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381614"
                     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="381621" data-post-id="381621">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="yordisprieto" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/yordisprieto/120/20915_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  yordisprieto
                    <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>As far as I can tell, Ecto.Schema and Ecto.Changeset isn’t about database per se. I understand what you are saying, and definitely people should be careful. While also, it doesn’t hold water. The Ecto.Changeset is about validation, and Ecto.Schema is about structs, mappings, and Ecto.Type is about a shared interface around marshalling, unmarshalling.</p>
<p>Ecto.Repo, and Ecto.Query; maybe, it would be more about actual DB.</p>
<p>Being said, <img src="https://forum.elixirforum.com/images/emoji/apple/man_shrugging.png?v=15" title=":man_shrugging:" class="emoji" alt=":man_shrugging:" 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="381621" 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/value-object-and-primitive-obsession-code-smell/39529/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-381621" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381621"
                     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="381632" data-post-id="381632">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="Oddman" data-post="10" data-topic="39529">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/oddman/48/39728_2.png" class="avatar"> Oddman:</div>
<blockquote>
<p>The point is to ensure that you have valid data and structures at all times.</p>
</blockquote>
</aside>
<p><a href="https://acko.net/blog/i-is-for-intent/" rel="noopener nofollow ugc">Free yourself of this mentality before it’s too late</a>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="381632" 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/value-object-and-primitive-obsession-code-smell/39529/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-381632" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381632"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="381635" data-post-id="381635">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="yordisprieto" data-post="13" data-topic="39529">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/yordisprieto/48/20915_2.png" class="avatar"> yordisprieto:</div>
<blockquote>
<p>Ecto.Schema and Ecto.Changeset isn’t about database per se.</p>
</blockquote>
</aside>
<p>They aren’t, and you can have separate schemas and changesets for your forms!  In small apps I never feel this is worth it, but we do this at work with more gnarly forms.</p>
<aside class="quote no-group" data-username="yordisprieto" data-post="13" data-topic="39529">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/yordisprieto/48/20915_2.png" class="avatar"> yordisprieto:</div>
<blockquote>
<p>The Ecto.Changeset is about validation</p>
</blockquote>
</aside>
<p>Gotta call this one out as Changesets are not just about validation but also about, ahem, changes.  Sure they go hand-in-hand, but so many Phoenix apps do a lot of parameter manipulation in the controller/LiveView layer before passing them to a changeset.  I know it’s in many other apps evident by the number of people who ask how you deal with maps that may have string or atom keys… you don’t!  You use the changeset API!</p>
<p>K, rant over.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="381635" 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/value-object-and-primitive-obsession-code-smell/39529/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-381635" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381635"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="381656" data-post-id="381656">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Please elaborate - I don’t see why? How do you otherwise ensure you get the appropriate structures/values whenever you depend on them?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="381656" 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/value-object-and-primitive-obsession-code-smell/39529/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-381656" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381656"
                     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="381658" data-post-id="381658">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>My reply was a link to a very detailed answer to your question. But, briefly, you ensure they are appropriate as you consume them.</p>
<p>The transition state between two valid states is often itself an <em>invalid</em> state. If you approach this with the mentality that the state must be valid “at all times”, whatever straitjacket of a data structure you cook up to achieve this will necessarily be incapable of representing transitions. And then it is <em>you</em> who will be cooked, I’m afraid.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="381658" 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/value-object-and-primitive-obsession-code-smell/39529/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-381658" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381658"
                     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="381710" data-post-id="381710">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>My experience has proven otherwise, for over a decade. If I understand you correctly, you’re saying that if I accept an argument, I then validate that argument in every function that expects it? Why would you do that, when you can do that in one place, and one place only, using the value object pattern?</p>
<p>I also read the article, it’s front-end focused. To that point, I largely agree with the author, and it was a good read. However, we’re not talking about frontend, here - we’re talking about value objects on the backend. Perhaps I’m missing something, but let’s take the ID argument above - how would you handle that without a value object implementation in elixir?</p>
<p>IMHO, expecting a particular struct/value type solves the problem almost entirely. At the very least, when dealing with IDs from Ecto, you’ll never end up passing the wrong id to a function, say a relationship that expects that value.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="381710" 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/value-object-and-primitive-obsession-code-smell/39529/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-381710" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381710"
                     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="381723" data-post-id="381723">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I never spoke against this “value object pattern”. I only suggested that you free yourself of the mentality that data must be “valid” at all times, because that mentality will hold you back. Especially if you’re writing <em>games</em>, which are like frontend on steroids.</p>
<p>I think it would be easy to poke some holes in the value object idea (what if I hand you <code>%Id{id: "evil nonsense"}</code>), but I don’t want to do that because in the limit I think it would be an argument against type systems, and I don’t actually have a problem with type systems, so long as they are not accompanied by the aforementioned mentality.</p>
<p>If you have read and enjoyed the article then you understand the problem and my work is done, I have nothing else to add <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="381723" 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/value-object-and-primitive-obsession-code-smell/39529/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-381723" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381723"
                     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="381724" data-post-id="381724">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You didn’t yourself make the point, but the article you linked is fairly polemical. It calls out an entire class of BE devs en masse and accuses them not only of not being well-equipped to handle types of FE complexity, but also poorly designing their own systems by insisting so much on validation. I don’t think the article does a great job backing up that argument. This passage seems to be the most direct treatment, and it’s still fairly vague:</p>
<blockquote>
<p>The trigger vs memo problem also happens on the back-end, when you have derived collections. Each object of type A must have an associated type B, created on-demand for each A. What happens if you delete an A? Do you delete the B? Do you turn the B into a tombstone? What if the relationship is 1-to-N, do you need to garbage collect?</p>
<p>If you create invisible objects behind the scenes as a user edits, and you never tell them, expect to see a giant mess as a result. It’s crazy how often I’ve heard engineers suggest a user should only be allowed to create something, but then never delete it, as a “solution” to this problem. Everyday undo/redo precludes it. Don’t be ridiculous.</p>
</blockquote>
<p>Maybe I’m missing the real point here, but this doesn’t sound like an average BE type problem. If this standard parent-child type relation, then there are plenty of patterns that don’t involve forbidding deletes, baked into most DBs in fact (do cascading deletes count as “garbage collection”?). Maybe it’s caching, which, yes, we are aware can be quite complex. But then I’m not sure how it relates to the issue of “intent” at all, since the user is not involved at that point.</p>
<p>The closest BE issue that comes to mind would be robustness in API design. Of course we want to try preserve the user’s intent as much as possible and even when we end up running into problems it’s good to be able to preserve that intent in the system so we can provide good feedback. But at the end of the day I think modern FE is just really complex with tons of user input being rapidly provided and so obviously validation is less useful and the balance is going to be a lot different compared to a web API.</p>
<p>But then at the end of the article the author seems to imply that internal APIs (BE/FE splits) are themselves a bad, or at least obsolete idea so</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="381724" 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/value-object-and-primitive-obsession-code-smell/39529/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-381724" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381724"
                     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="381726" data-post-id="381726">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Fair point, but I’m also not arguing for “valid at all times”, as that’s impossible. However, I think that’s for the most part, pure semantics. I’m a subscriber to the DDD approach where the business domain cannot be ALLOWED to have an invalid state at any time. This is enforced by strong typing and/or validation where required. This massively reduces bugs, and so my point about IDs and value objects are approaches to enforcing that validity of state.</p>
<p>I think arguing against that doesn’t make much sense, but of course you will have invalid state when a use submits a form, for example, and you have to manage that, but that’s a separate concern. It seems to me to be a bit of a strawman, honestly, or at least somewhat disingenuous - because it’s obvious. You can’t enforce valid state from a user, that’s why we have validation in place to begin with.</p>
<p>Your point about the ID part, what you’re suggesting simply wouldn’t be possible. The value object pattern enforces that (for example), the ID must be an integer, or a ULID, or whatever it is that makes sense in your system. Of course, a developer could certainly just create an id object without an actual valid id value, but the question then needs to be asked - why? Why are you doing this? If it’s for testing purposes, okay - makes sense. But are you doing this in code you’re preparing for production? Bigger questions would need to be answereed there, likely one of maliciousness <img src="https://forum.elixirforum.com/images/emoji/apple/wink.png?v=15" title=":wink:" class="emoji" alt=":wink:" 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="381726" 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/value-object-and-primitive-obsession-code-smell/39529/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-381726" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="381726"
                     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/39529/load_more?page=3">Load more posts (10 remaining)</a>
</div></template></turbo-stream>