1. 4
  1.  

  2. 6

    I’ve become more and more in favour of hardcoding these things. A good language should allow you to express a structured value in a way that doesn’t look “magic”. And your release/deploy infrastructure should be such that you can make a change and release to prod quite quickly. Software exists to solve business problems and has a lifecycle associated with that: when the requirements change, so should the software. And the concerns of audit trail etc. are handled automatically by whatever mechanism you use to handle code changes. No, this doesn’t let users change settings, but most of the time that’s the wrong call IME: most setting changes are behavioural changes that impact the functionality of a piece of software and ought to go through the same release/testing process that any code change would.

    1. 6

      You have a fair point, @lmm.

      I think in our case it’s particularly important not to require a developer intervention to make such changes, because we build systems for our clients and we like to just give the systems to them at some point and move on to our next project. Therefore, whatever we can do to avoid the need of involving our devs in those small changes, the best.

      1. 2

        That doesn’t mean they need to be “hardcoded”, assuming you mean in the code. They can be in a config file that the code reads, but it’s still in the same repository as the code and only changes in the code. I, personally, prefer to separate them out because I find it easier for testing, easier to get a view of what the configuration is, and easier to analyze or consume by other tools.

        1. 1

          I don’t see what difference it makes to testing? If everything’s just code it’s easy to swap out a value with a different one. As for getting a view of what the configuration is, configuration as a value should be readable if the language is any good.

          What kind of analyzing/consuming are you talking about? Again, if it’s just a value, one can integrate with other systems the same way one integrates for anything else (e.g. JSON, ProtoBuf, …)

          1. 1

            It depends on what “hardcoding” means to you. Generally these are not very changeable. I often run tests for which the service is configured different than production, in such a case I like to test the same binary artifact as I would run in prod, so the configuration becomes separate. But, like I said, it depends on what you mean by hardcoding.

            Analyzing/consuming is actually wrong, I shouldn’t have said that. But what I do more often is I programatically generate a config file that is then consumed by the application when run. I prefer to have the config format as an inbetween so it can be inspected by a human when debugging.

            1. 1

              It depends on what “hardcoding” means to you. Generally these are not very changeable. I often run tests for which the service is configured different than production, in such a case I like to test the same binary artifact as I would run in prod, so the configuration becomes separate. But, like I said, it depends on what you mean by hardcoding.

              My preferred approach is a class with a few (static) instances, and then just a bit of code to pick which one to use at runtime (based on a commandline arg or environment variable or the like) - I agree you do end up with a few things that need to be different between blue/green/dev and these things need to be to a certain extent segregated from the code proper (though to my mind a separate package is more than enough). I agree that humans need to be able to view the config, but I tihnk a language always needs a good syntax for structured value literals, because so much of programming ends up being that. If JSON or the like is substantially more readable than what the same value would look like in code, I think that’s a real deficiency in the language.

              1. 2

                If JSON or the like is substantially more readable than what the same value would look like in code, I think that’s a real deficiency in the language.

                For myself, the value is in what you cannot do. I do not want to have to parse code to try to figure out what configuration is actually being used, that is why I like the config file as an intermediate. That way I have a turing complete generating the config and a turing complete language consume it but the config is just values. With discipline you can just get rid of it and use configs direct in the code like you are doing.

      2. 1

        The question for a lot of developers is that these literals contain assumptions about how the program should work, and that changing them dynamically could create unexpected behavior. Dynamism in this case can be with a single process and many variables being updated via RPC of some type, to many processes that communicate where certain subsets are restarted to read the new values.

        How do you model all the various combinations of customer configurations to ensure quality? What about changing those variables once every second, in various combinations?

        These types of things should be done carefully, which this blog post actually is the beginning of, I’m curious how these types of changes are propagated in larger and larger systems, as it’s a very real struggle in most of my work.