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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tkruthoff" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tkruthoff/120/3063_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tkruthoff
                  </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="15" data-topic="8623">
<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>Parallel (not umbrella) applications are trivial to create and manage, and have decoupling built in from the start.</p>
</blockquote>
</aside>
<p>Would parallel applications still run in the same BEAM, and if not, would you then create a client module and a server module, where by the client modules simply make :rpc calles to known servers?  And the client and server code live in the same application, but when you need to use only the client you do not “start” the server?</p>
<p>Thanks,</p>
<p>Troy</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="50215" 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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-50215" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50215"
                     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="50218" data-post-id="50218">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="AstonJ" data-post="1" data-topic="8623">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/astonj/48/15_2.png" class="avatar"> AstonJ:</div>
<blockquote>
<p>Do you agree? Is this how you build your Elixir/Phoenix apps? Can you think of pros/cons?</p>
</blockquote>
</aside>
<p>I agree with this. This is how I develop my apps which are a bit larger.  For smaller apps which are more web only I just put everything in one app (but of course still try to use the correct interfaces between my modules)</p>
<p>I tend to create an umbrella application with my application as one app and the phoenix web layer as another app.</p>
<p>I think it is great that Phoenix 1.3 is pushing towards this direction. For me it feels natural but I guess if you are used to Rails or Django which doesn’t usually have as clean interfaces perhaps it may look odd. I really like erlang’s -export directive as you really need to think on what functions you are exporting and it also gives a quick overview when you just open the files. Technically it is the same with def/defp but quickly look at a module to see what the interface is.</p>
<p>The cons to this approach I think is the same as the pros and cons of strong type systems (haskell, ocaml, rust). You need to think about your problem and problem domain in advance to get the right abstraction. This takes more time up front but saves you lots of time later. With dynamic languages you can get visible results much quicker but may end up with messy code that gets harder to refactor later.</p>
<p>I feel contexts are in the same problem domain as this. If you think first and get your contexts sorted out you wont be the first one out of the box but you will win the race</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="50218" 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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-50218" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50218"
                     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="50226" data-post-id="50226">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="19" data-topic="8623">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>But since I have already phrased those concerns elsewhere, I won’t rehash them here.</p>
</blockquote>
</aside>
<p>Could you provide a link? I remember reading about it or watching a video about it somewhere but I can’t find 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="50226" 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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-50226" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50226"
                     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="50278" data-post-id="50278">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="AstonJ" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/AstonJ/120/15_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  AstonJ
                    <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 everyone for taking part in the conversation <img src="https://forum.elixirforum.com/images/emoji/apple/purple_heart.png?v=15" title=":purple_heart:" class="emoji" alt=":purple_heart:" loading="lazy" width="20" height="20"></p>
<p>Discussions like this are incredibly useful for developers like myself who are transitioning from the old ‘monolith’ way of doing things and are on a quest for something better.</p>
<p>I believe this (and finding it in the Elixir/Phoenix world) is actually a fantastic selling point - while many people may come for the speed, distribution, concurrency and fault tolerance I reckon they might stay because the eco-system pushes them towards good solid ‘modern’ approaches to building software that is resilient, less frustrating and scalable in every sense of the word. All the while making it fun (easy?) and interesting <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>
<hr>
<p>With that said, back to the topic. Although it’s very early for me to judge at present as I’ve still got 20% of the course to go through and we sadly won’t be using Ecto in the course (so I can’t yet fully picture a typical app) I am very excited by what I’ve seen so far. Much of what Dave has said seems to answer the burning question I often had when creating apps in other languages (that surely there is a better way of doing things).</p>
<p>Having said that, I can see a few challenges that might need to be overcome. For instance, if everything is created as separate services, and Phoenix should only be used for communicating via the web, then we might lose functionality or conveniences that Phoenix provides that we might want to use in the non-Phoenix part of our (overall) app - so those might need to be somehow moved from Phoenix or reworked in some way. The obvious one is validations (though I believe these are in Ecto - so maybe not an issue after all).</p>
<p>There’s probably more that I’m not aware of. José mentioned operational concerns and I would love to read about those too.</p>
<hr>
<p>With regards to optimising for on-boarding new folks, I wonder if this could be worked around by having a <code>--simple</code> flag on app creation and where the generators reflect that (monolith?) ‘style’. This would explicitly let people know that it’s a learning tool, or one for quick prototyping or for creating the simplest of sites/apps. But perhaps more importantly it will spearhead a brave new direction, ‘the Elixir way’ of doing things. (I would actually be super excited by this! As if I could get any more excited about Elixir and Phoenix that is!)</p>
<p>The reason I think this is worth investigating was actually commented by Chris himself in his keynote, when he referred to <a class="mention" href="/u/sasajuric" rel="nofollow">@sasajuric</a>’s feedback of where an expert team were somewhat led down a not ideal path because they thought the Phoenix way was what it was telling you to do via generators.</p>
<hr>
<p>One final thing I would like to say is that it’s a very exciting time to be a developer! And an Elixir developer at that! I’m extremely happy to see that José, Chris and everyone in the Elixir, Phoenix and Ecto teams have this pursuit of reflection &gt; perfection - and equally heartened to see that experienced members of the community are part of that transition, by feeling able to have conversations and inspire discussions like this.</p>
<p><img src="https://forum.elixirforum.com/images/emoji/apple/purple_heart.png?v=15" title=":purple_heart:" class="emoji only-emoji" alt=":purple_heart:" 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="50278" 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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-50278" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50278"
                     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="50290" data-post-id="50290">
  <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 no-group" data-username="pragdave" data-post="15" data-topic="8623">
<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 really don’t buy the “ease-of-entry based on new user expectations” argument. If I did, I’d write a PHP interpreter as part of Phoenix.</p>
</blockquote>
</aside>
<p><a href="https://github.com/bragful/ephp" rel="noopener nofollow ugc"><em>*cough*ephp*cough*</em></a></p>
<p>But yeah, overall I agree with pragdave.  And honestly, as I’ve mentioned before, I’m not even a fan of umbrella apps.  Umbrella’s encourage a lot more interconnections between sections then what should really exist.  I instead make my parts as lots of little dependencies that I then bring into a main app that does all the configuring and more.  If I need a couple sections communicate between then I setup a channel between them at this point (not like a phoenix channel, but a set of behaviours in a sub project that both depend on, then setup their communication modules in the config).  I find it keeps it very very clean and maintainable.</p>
<aside class="quote no-group" data-username="pragdave" data-post="18" data-topic="8623" data-full="true">
<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 point still holds: it’s still one big application. It should be many.</p>
</blockquote>
</aside>
<p>This precisely, this is what I do.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="19" data-topic="8623">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>It is really hard to agree that Phoenix v1.3 became more coupled to the database compared to previous versions. It has gone from an application that accessed the database in your controllers, channels and models to one that puts this access behind isolated modules with discrete APIs. Removing the database access in a Phoenix v1.3 app should require localized changes to your lib/app instead of rewriting most of your web layer.</p>
</blockquote>
</aside>
<p>And this, 1.3 became less coupled to ecto, but I still do not like the monolithic apps that hold many (to use phoenix terms) contexts when a context should be its own standalone application/dependency.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="19" data-topic="8623">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>I also have strong reservations about having different applications that depend on the same database instance, as those are effectively coupled at the operation level and you will run into issues depending on how you coordinate things such as migrations. I would like to see both development and operation concerns being taken into account on those discussions. But since I have already phrased those concerns elsewhere, I won’t rehash them here.</p>
</blockquote>
</aside>
<p>I pass the Repo one of my dependencies should access into its config, which it then bakes in to their calls at build time.  ^.^</p>
<p>That is really how it should be done I’d say, usually I pass the Repo module around as an argument, but currently I’m just using things like <code>@Repo unquote(Application.get_env(:this_app, :repo) || throw ":this_app does not have :repo defined")</code> in more places than I probably should.  I should probably make a library to simplify a lot of this repetition too…  &gt;.&gt;</p>
<aside class="quote no-group" data-username="pragdave" data-post="21" data-topic="8623">
<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 say contexts are wrong. I do say that encouraging new developers to place them inside the same project as the view layer is not a good idea. So in that way, 1.3 created a good idea (contexts/services) but then encouraged it to be used in a way that can lead to lots of coupling, and to Monorails. (And, as we’re discussed, umbrella projects don’t fix it.)</p>
</blockquote>
</aside>
<p>Ditto, make lots of little applications and bring them in as dependencies.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="8623">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>“offering contexts directly in Phoenix and not in a separate app”. <img src="https://forum.elixirforum.com/images/emoji/apple/sweat_smile.png?v=15" title=":sweat_smile:" class="emoji" alt=":sweat_smile:" loading="lazy" width="20" height="20"></p>
</blockquote>
</aside>
<p>Precisely this!  They should be standalone dependencies as I’ve stated in that huge Contexts thread.  ^.^;</p>
<aside class="quote no-group" data-username="tkruthoff" data-post="23" data-topic="8623">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tkruthoff/48/3063_2.png" class="avatar"> tkruthoff:</div>
<blockquote>
<p>Would parallel applications still run in the same BEAM, and if not, would you then create a client module and a server module, where by the client modules simply make :rpc calles to known servers?  And the client and server code live in the same application, but when you need to use only the client you do not “start” the server?</p>
</blockquote>
</aside>
<p>They all run on the same beam.  Even right now your beam instance is running probably a few dozen or more applications.  <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="50290" data-batch-url="/posts/batch_likers">
                        6
                      </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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-50290" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50290"
                     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="50315" data-post-id="50315">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>It’s possible that we are overthinking this and if I’ve got to choose between one of these approaches, I think Phoenix is getting it right by encouraging and enabling separation rather than forcing it.</p>
<p>Completely separate applications come with a lot of hidden complexity that doesn’t generally need to be introduced until you really <em>require</em> it. The whole microservice vs monolith discussion generally boils down to isolation of dependency trees and resource consumption at its root. If a monolith is built with an object oriented language, you end up with this horrifying blur of inheritance chaining that’s incredibly messy to untangle. If you go microservices from the start it’s good long term but you pay for it up front with potentially unwarranted complexity.</p>
<p>With the approach from Phoenix and Umbrellas you don’t have a tangled mess, thanks to the way Elixir is designed. You’ve got smaller parts in their own zones that are significantly easier to separate when you finally NEED to.</p>
<p>Learning curve and on-boarding are a huge deal for a language. Determining trade-offs that get people moving quickly in the right direction is a key and it’s one of those things that is hard because you’re always sacrificing something. It’s something programmers debate about constantly because business factors like turnover, training, learning curve and time to market are real factors that matter beyond ideal architecture. Ideal architecture seems a lot easier when those other factors aren’t included IMO.</p>
<p>In that regard and from a community standpoint, I really do think that Phoenix 1.3 has nailed that balance. Like anything else in programming, it’s always a question of trade-offs and hidden costs.</p>
<p>If we aim for architectural purity instead of that balance, we aren’t going to be much better off than the “OMG Benchmarks!” crowd. If productivity, learning curve, training time, etc aren’t a factor then why aren’t we just using Erlang?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="50315" data-batch-url="/posts/batch_likers">
                        18
                      </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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-50315" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50315"
                     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="50318" data-post-id="50318">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Just to mention: When you designing contexts as separate umbrella app it forces you to think about deps and configs.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="50318" 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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-50318" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50318"
                     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="50347" data-post-id="50347">
  <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="AstonJ" data-post="26" data-topic="8623">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/astonj/48/15_2.png" class="avatar"> AstonJ:</div>
<blockquote>
<p>The reason I think this is worth investigating was actually commented by Chris himself in his keynote, when he referred to <a class="mention" href="/u/sasajuric" rel="nofollow">@sasajuric</a>’s feedback of where an expert team were somewhat led down a not ideal path because they thought the Phoenix way was what it was telling you to do via generators.</p>
</blockquote>
</aside>
<p>My comment which Chris cited should be regarded in the context of Contexts <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"><br>
In particular, I’m not at all convinced that we should enforce separate OTP apps. Contexts basically nudge us to move web-unrelated concerns to another function in another module. That’s a simple separation of concerns with a very little overhead. Separate apps lead to much more operational and mental overhead, and I’m not convinced this is a good starting option. Personally, I feel that with contexts, it should be fairly straightforward to split an app later on, if needed, as it should mostly boil down to moving some modules and some parts of config. So IMO contexts are a very good trade-off between approachability and some sane default decoupling.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="50347" data-batch-url="/posts/batch_likers">
                        17
                      </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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-50347" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50347"
                     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="50381" data-post-id="50381">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I think the question is, WHY. Why do database calls need to be broken into other services. What is gained? What are the concrete advantages from a development, performance, and operational perspective? How does that weigh against the additional complexity introduced?</p>
<p>If the answer is “well, because. Because it’s not Rails”, then I don’t think that’s a sufficient answer. If the impetus is architectural purity (“that’s not how it should be done in Elixir!”), without regard for the implications in real projects and real development, I’m unconvinced.</p>
<p>I’m not saying there aren’t advantages to breaking everything into microservices. But most apps that have a data layer can have a data model that is by necessity a series of highly coupled dependencies. And efficiently querying that model often requires that those dependencies be maintained. Breaking that into microservices loses a lot, and again, I’d have to be very clearly convinced that what is gained makes up for it. I think there is so much talk about “X is good and Y is bad” without real world examples of why, and what the implications are then you lose what X gives you because Y is so great.</p>
<p>As others have said, I think that contexts do a good job of at least a first pass of separation of concerns (even though there may be data dependencies between contexts). I’m not sure that there’s much need to make all applications, even basic applications, require much more than that in terms of complexity.</p>
<p>At the end of the day, architectural purity loses to real world concerns every time, in my book. Unless that purity has real world advantages.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="50381" data-batch-url="/posts/batch_likers">
                        13
                      </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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-50381" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50381"
                     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>
    <div class="postbit" id="50390" data-post-id="50390">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="drewmca" data-post="31" data-topic="8623">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/d/a9adbd/48.png" class="avatar"> drewmca:</div>
<blockquote>
<p>I think the question is, WHY.</p>
</blockquote>
</aside>
<p>This is very good question, and the only question that matters. The answer is a cliche, but it’s “to build better, more maintainable software”.</p>
<p>I think contexts were introduced because some people (me included) complained about inadequate separation of business logic from the infrastructure provided by Phoenix. It is awesome that the team tried to solve the problem, I am not on the side of these that think it’s a good enough solution, however.</p>
<p>Like <a class="mention" href="/u/pragdave" rel="nofollow">@pragdave</a>, I strongly believe that the “web” or “ui” app should be merely an interface to the underlying application - or applications most likely. Now it’s the question of how thick or thin this layer should be.</p>
<p>Database access layer, in my humble opinion, does <em>not</em> belong to the web UI interface layer for sure. It is an implementation detail, that the business logic application would use <em>internally</em> and <em>behind the scenes</em>. Ideally, this can be done using Ecto schemas that are as dumb as possible. In my app, I do not put <em>any</em> validation-related logic there, the Ecto schemas define just schema and relationships between schemas. These Ecto schemas also would not leak to the UI directly.</p>
<p>The “core” application, that provides the business logic, most likely keeps the Ecto schemas internally. The responsibility is to respond to either queries or commands issued by user, and either return some stuff (for query) or update some stuff in database (command), sending e-mails, generating reports, updating external services in the process. You can have many “core” applications in fact, which is probably good practice in most cases except simple problem domains.</p>
<p>How does user interact with our “core” application? They submit forms. Or they click on a link that can be mapped to empty form submit. In general case they call some endpoint on the UI web app, passing 0 or more arguments along. This input needs to be validated, business logic checked against “core” application, and if such <em>command</em> is looking like something user can do, it’s been passed over to “core” application for execution. The question if the modules responsible for casting forms to commands, and initializing validation is responsibility of UI or back-end “core” app is open and will vary from case to case in my opinion.</p>
<p>So the above is the ideal breakdown <em>in my humble opinion</em>, for most real life cases. I do <em>not</em> believe, however, that all the work above has the same weight in terms of making the software maintainable, and predictable: the <em>most important part</em> is separating command/form validation from underlying schemas that persist / read things from database. By doing so you no longer think in terms of CRUD app, instead of commands issued by user. You can also avoid many permissions-related bugs in the code, such as mass-assignment related issues.</p>
<p>Now, how to achieve that? In Rails we used to <code>import Virtus.model</code> to our so called “form objects”. You can do exactly the same, with Ecto schemas that are <em>not</em> backed up by any table. This way you integrate well with default form builder, gettext, etc. If you have an API, that layer can be totally separated from Ecto library, and either use your own, or something like <code>vex</code>.</p>
<p>So while I appreciate effort to make separation of modules in Phoenix, I think it went slightly less important way. Separating form validation from actual schemas does seem like a more important task for me. And it’s true you can easily do it on your own, but it’s not what the generators teach users to do <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="50390" data-batch-url="/posts/batch_likers">
                        9
                      </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/discussion-dont-add-a-database-layer-to-your-phoenix-application/8623/32">Post #31</a>
	                </div>
	            </div>
              <div id="likers-container-50390" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="50390"
                     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 #31"></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/8623/load_more?page=4">Load more posts (52 remaining)</a>
</div></template></turbo-stream>