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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Though, if actual behavior differs between environments, do try to keep the differing code minimal, as it will be difficult to test. Best perhaps to wrap the case for each environment in its own function, even, that you could at least specifically call from tests?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="214978" 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/a-universal-way-to-detect-environment-in-phoenix/39934/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-214978" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="214978"
                     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="214979" data-post-id="214979">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ojinari" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ojinari
                    <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">
								<aside class="quote no-group" data-username="soup" data-post="11" data-topic="39934">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/soup/48/31425_2.png" class="avatar"> soup:</div>
<blockquote>
<p>I think Jose is also implying that instead of checking against the env en todo, it’s better design to check against specific configurations, which is more readable and maintainable:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">if Application.get_env(:my_app, :do_use_service) ...
if Applcation.get_env(:my_app,  :logging_is_enabled) ...
</code></pre>
<p>vs</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">if Application.get_env(:my_app, :mode) ==  :dev then do_use_service()
</code></pre>
</blockquote>
</aside>
<p>How is the 1st better than the 2nd?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="214979" 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/a-universal-way-to-detect-environment-in-phoenix/39934/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-214979" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="214979"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Because this may infer a lot implications that are hard to understand for a second person (or your future self).</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># checked in
#   - my_mod.logger to decide on which logging endpoint to use
#   - my_mod.xyx.fn() to infer abc or ars.
config :my_app, :mode, :dev
</code></pre>
<p>And then one day you set <code>:mode = :prod</code> but the check never accounted for it or forgets to check and you have a very hard to find bug in some obscure location.</p>
<p>Or you want to have two staging envs and now you’re updating all your if/case to check <code>env == :staging or env == :staging_site_b</code>.</p>
<p>VS</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">config :my_app, :remote_logging_url, "https://dev.local"
config :my_app, :xyz_use, :abc
</code></pre>
<p>Which is both explicit in what you are configuring and allows for finer configuration and should actually remove the need for checks in your code.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">case :mode do
  :dev -&gt;  Logger.set_receiver("http://dev.local")
  :staging -&gt;  Logger.set_receiver("http://staging_1.internal-1.com")
  :prod -&gt; Logger.set_receiver("http://www.remote.com")
end
</code></pre>
<p>becomes</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">Logger.set_receiver(Application.get_env(:my_app, :remote_logging_url)
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="214981" 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/a-universal-way-to-detect-environment-in-phoenix/39934/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-214981" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="214981"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

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


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="ojinari" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  ojinari
                    <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">
								<aside class="quote no-group" data-username="soup" data-post="15" data-topic="39934">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/soup/48/31425_2.png" class="avatar"> soup:</div>
<blockquote>
<p>And then one day you set <code>:mode = :prod</code> but the check never accounted for it or forgets to check and you have a very hard to find bug in some obscure location.</p>
</blockquote>
</aside>
<p>Why would I set “mode: :prod” in config/dev.exs ?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215037" 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/a-universal-way-to-detect-environment-in-phoenix/39934/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-215037" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215037"
                     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="215041" data-post-id="215041">
  <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 quote-post-not-found" data-username="ojinari" data-post="17" data-topic="39934">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/o/50afbb/48.png" class="avatar"> ojinari:</div>
<blockquote>
<p>it’s not about VALUES in my code, it’s about BEHAVIOUR</p>
</blockquote>
</aside>
<p>Values can affect behaviour though and that’s what people are trying to suggest here.</p>
<p>Say you have a UI where you show a secret key. In dev you want to show the whole secret, while in prod (and other envs) only the last few characters are supposed to be shown. This is different behaviour.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyUI do
  defp format_secret(&lt;&lt;_start::binary-size(12), rest::binary-size(4)&gt;&gt; = secret) do
    case Mix.env() do
      :dev -&gt; secret
      _ -&gt; "…" &lt;&gt; rest
    end
  end
end
</code></pre>
<p>Instead of depending on the environment to select behaviour directly you can bundle up the behaviour (e.g. in functions or modules) and let the environment select the behaviour via configuration.</p>
<p>Step 1: Bundle up behaviour</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule SecretFormatter do
  @callback format(binary) :: binary
end

defmodule SecretFormatter.SecretFull do
  @behaviour SecretFormatter

  @impl true
  def format(secret), do: secret
end

defmodule SecretFormatter.SecretTail do
  @behaviour SecretFormatter

  @impl true
  def format(&lt;&lt;_start::binary-size(12), rest::binary-size(4)&gt;&gt;), do: "…" &lt;&gt; rest
end

defmodule MyUI do
  defp format_secret(secret) do
    case Mix.env() do
      :dev -&gt; SecretFormatter.SecretFull.format(secret)
      _ -&gt; SecretFormatter.SecretTail.format(secret)
    end
  end
end
</code></pre>
<p>Step 2: Use config to select the behaviour</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># config.exs
config :my_app, MyUI, secret_formatter: SecretFormatter.SecretTail

# dev.exs
config :my_app, MyUI, secret_formatter: SecretFormatter.SecretFull
</code></pre>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyUI do
  defp format_secret(&lt;&lt;_start::binary-size(12), rest::binary-size(4)&gt;&gt; = secret) do
    formatter = Application.fetch_env!(:my_app, __MODULE__) |&gt; Keyword.fetch!(:secret_formatter)
    formatter.format(secret)
end
</code></pre>
<p>This is quite a bit longer as you can see, but this is also the most elaborate setup with gives you a lot of compiler help, the ability to mock things using Mox in tests and such. You could also just name the two different ways to format things and configure the name for each.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># config.exs
config :my_app, MyUI, secret_format: :tail

# dev.exs
config :my_app, MyUI, secret_format: :full
</code></pre>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyUI do
  defp format_secret(secret) do
    case Application.fetch_env!(:my_app, __MODULE__) |&gt; Keyword.fetch!(:secret_format) do
      :full -&gt; secret
      :tail -&gt; "…" &lt;&gt; rest
    end
  end
end
</code></pre>
<p>The important bit is that you put the different code paths (currently per env) into something independently callable and make the decision which of those to call a configuration concern instead of compile time or runtime decisions in the codebase itself.</p>
<p>The second example might also show that <code>Mix.env</code> is also just a value you use to make decisions. It’s just way less flexible and less visible than using configuration. Configuration allows you to map env =&gt; behaviour in one common place instead of scattered all over the codebase.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="215041" data-batch-url="/posts/batch_likers">
                        10
                      </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/a-universal-way-to-detect-environment-in-phoenix/39934/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-215041" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="215041"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>