Personally I look at it the other way around: things are clearer to me when
I can see the point at which all configuration values are assembled and
then passed down from parent to child, the same you would do with a purely
functional program that can only operate on it's inputs. All I generally
want to use config.exs for is global, static config (i.e. things which are
only likely to change at compile-time, not runtime). Default values should
be part of the application code, and expect to be overridden as necessary,
rather than using config.exs/application env for that kind of thing. This
keeps configuration closer to the code that needs it, and encourages a more
functional approach to your design.

Because of that functional approach, it becomes considerably easier to test
an Elixir program when you can start a supervision tree, a branch of it, or
a leaf (a single process) by simply passing in the configuration it needs,
which is going to be part of it's interface. Taking it a step further and
allowing one to configure the names of things allows you to start many
instances of what would normally be a singleton process, and test many
scenarios in parallel - this is particularly handy with stateful things
where you need to test different conditions which might conflict with other
in-progress tests.

The more libraries that adopt this approach to configuration, the easier it
gets to configure and test your whole system. The config providers
framework I've made for Distillery is intended to be a way to deal with
legacy applications, as well as providing a mechanism for applications
which use other mechanisms for configuration (i.e. init-style configs,
etcd/Consul, and so on) - but it is not intended to make it easy to put
everything in config.exs/application env; I still strongly believe that we
need to move away from that as much as possible, not out of ideological
purity (which I hope is refuted by the config providers work), but out of
knowing that if we can move away from it as a community, things will get
much better for all of us as a whole.

On Tue, Aug 7, 2018 at 3:33 PM Ivan Yurov <[email protected]> wrote:

> This is a great point that it would be pretty hard to pass anything but
> strings. And validation too. What still bothers me is that it might be
> pretty hard to keep track of settings if they are spread over config.exs
> and init simultaneously. I'll probably go with this Config module idea,
> thanks. At least until there's a common solution.
>
> On Monday, August 6, 2018 at 6:25:18 PM UTC-7, Paul Schoenfelder wrote:
>>
>> > So the idea is to individually resolve these settings in init callback,
>> am I getting it right?
>> https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/repo.ex#L69-L75
>> > Well, if I do that, I'll have to use the ENV variable in dev
>> environment as well, which I wouldn't want to do for obvious reasons: these
>> old configs are just code, when env variables are volatile.
>>
>> I think you are missing the fact that the resolved environment variable
>> can be set conditionally, i.e. only when there is _no_ value found in the
>> application environment. You can do whatever you want in that callback. But
>> yes, the idea is that if there is no value found at that point, you can
>> attempt to resolve configuration from the system environment or elsewhere -
>> it becomes part of your application code and lives alongside the thing
>> being configured.
>>
>> > And what is the rationale, why {:system, var} is so bad if what happens
>> in init callback is essentially the same? Am I missing something here?
>>
>> It isn't the same - one is implicit, the other explicit, amongst other
>> things - in addition, the behavior of `{:system, var}` is not well defined,
>> it depends on the implementation; there is no way to handle converting
>> values to appropriate internal types (i.e. an atom or an integer) or
>> provide defaults. There is no way of knowing if that tuple is used for
>> other purposes in some application or library somewhere or not - the
>> convention was created by Elixir libraries early on, but there are far more
>> Erlang libraries and Elixir libraries which do not use it than those which
>> do, automatically transforming that tuple to the value of the system
>> environment variable is "magical", and is something we in general try to
>> avoid, particularly in cases where it may cause issues with existing
>> applications.
>>
>> By putting configuration handling code in the `init` callback, you can
>> handle falling back to multiple sources, perform type conversions,
>> validation, and more, is explicit, and becomes maintained with your other
>> application code. If you are looking for something that would do that sort
>> of conversion for you, you can simply write a thin Config module which
>> checks for that tuple, and resolves the environment variable, and just
>> invoke that module from the init callback instead.
>>
>> Paul
>>
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/ed34aba1-e22f-4591-a019-6b11dbc19cea%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/ed34aba1-e22f-4591-a019-6b11dbc19cea%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAK%3D%2B-TuWR0Zw4DF82G6zm%2B6PWr0TrtxXEGwHzg6WQfc6KrFdHw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to