[HN Gopher] Configuration Complexity Clock (2012)
       ___________________________________________________________________
        
       Configuration Complexity Clock (2012)
        
       Author : jelder
       Score  : 44 points
       Date   : 2025-04-02 12:00 UTC (3 days ago)
        
 (HTM) web link (mikehadlow.blogspot.com)
 (TXT) w3m dump (mikehadlow.blogspot.com)
        
       | praptak wrote:
       | I have this optimistic belief that there exists this platonic
       | ideal of a configuration language which isn't a programming
       | language but is still expressible enough.
       | 
       | I think of it as an algebra of configurations and there are at
       | least two existing languages that implement this ideal. One of
       | them is Jsonnet and the other is internal to Google (and might
       | have influenced Jsonnet).
       | 
       | That said, obviously a good language is not enough. You still
       | need good judgement about which stuff goes into configuration.
        
       | feelamee wrote:
       | Why not take an existing small language, which have good
       | documentation and tooling? E.g. lua. It can be integrated very
       | fast and anyone can learn it in a few minutes.
       | 
       | > In the pub after work someone quips, "we're back where we
       | started four years ago, hard coding everything, except now in a
       | much crappier language."
       | 
       | For me it's not the same. Four years ago - you hardcoding values
       | in (probably) compiled language. So, you were need to recompile
       | it each time the value changes. Now - you writing (probably) in
       | interpretet DSL. So, your compiled app can reload it at runtime.
        
       | rednafi wrote:
       | I feel similarly about environment variables. Envvar issues are a
       | pain to debug in cloud VMs and CI pipelines.
       | 
       | Oftentimes, changing the envvar value doesn't propagate without a
       | container restart anyway.
       | 
       | I wish that instead of all these vaults and similar tools, cloud
       | providers would let me pipe in a flat text file and read config
       | from there.
       | 
       | Anything that requires a more complex setup should live with the
       | code.
       | 
       | In many scenarios, the increased cognitive burden that comes with
       | these hierarchical config files, DSLs, and rule engines is just
       | not worth the yield. Redeploying isn't hard unless we're talking
       | about a multi-region, globally distributed system.
        
       | zevv wrote:
       | "we're back where we started four years ago, hard coding
       | everything, except now in a much crappier language."
       | 
       | Not sure if I agree with this. A proper designed DSL has the
       | advantage of being much closer to the domain of the problem it is
       | supposed to solve. Your code written in the DSL now might end up
       | as 'hard coded' part of the application, but it likely conveys
       | much more meaning in much less code because it is tailored to the
       | core functionality of the application.
        
         | masfuerte wrote:
         | Design a DSL. But instead of implementing it, implement the
         | same abstractions in the functions (or classes or whatever) of
         | your code. Effectively, you are implementing the DSL without
         | the parser and AST.
         | 
         | When you chain these functions together into business logic
         | they will be just as readable as the DSL would have been. But
         | you still get an IDE with code completion, debugging, etc.
        
       | bob1029 wrote:
       | I made almost two full trips around this clock over the last
       | decade on a single project.
       | 
       | One of the biggest takeaways for me is that if you choose to do
       | the DSL, you need to think super hard about your target audience
       | and how _they_ think about the world.
       | 
       | For me, the whole point of DSL is to get the developers working
       | on common modules that the business could string together without
       | too much babysitting.
       | 
       | The first DSL we tried was python, interpreted by way of iron
       | python / C#. This did not stick with the business people at all.
       | It was pure ball-and-chain for the development team.
       | 
       | The second DSL we tried is SQL. The verdict is still out on that
       | one, but the amount of traction so far is almost infinite in
       | comparison to the prior attempts. You can get a non-developer to
       | build SQL queries that express BL if you are patient with them
       | and provide some examples. The tooling is also substantially
       | better if you are using something like SQLite and can easily pass
       | the DB around to play with.
       | 
       | If I was going to approach this fresh, I'd set the clock to noon
       | and then remove the battery. The amount of overhead and risk
       | required to support a DSL is substantial. Even if you use SQL and
       | leverage mostly existing tools, you are forcing developers to
       | build things in a very particular way that isn't necessarily
       | ideal in terms of a pure code solution.
       | 
       | I think you can do a purely hard coded solution that is
       | approachable by the business if it is structured well enough and
       | made available in a friendly context like GitHub. Let the
       | business use the web tool to propose PRs over well documented
       | code they can mostly understand. Maybe there's an "internal"
       | folder that only the neckbeards touch. You can draw your battle
       | lines wherever you please.
       | 
       | For the hardcoded only approach wherein the business people are
       | involved, the choice of language is very important, but I don't
       | know how to have that conversation constructively in this forum.
        
       | Xmd5a wrote:
       | I tend to do a lot of data-oriented programming, including at the
       | meta-programming level, which blends with the problem of
       | configuration. A pattern I found that works well this use case
       | and covers the whole clock is the following:
       | 
       | - DSL as functions T, args* -> T, where T is your configuration
       | type -- or, as I like to call it, a plan. Since under function
       | composition it's insensitive to composition order (associativity
       | of the monoid), you can layer DSL functions on top of each other
       | freely.
       | 
       | - Literal values as implicit functions. Once the plan is built
       | and before it is run/compiled/interpreted, I cast any literal
       | value in the datatype to a function returning that value. It's a
       | design principle that allows me to hard-code behavior when a
       | literal value is not enough by just swapping it with a lambda.
       | 
       | - Once this kind of homogeneity is ensured, and given the points
       | above, I can extend my DSL and the behavior it describes with
       | point-free function combinators. I get conditionals, advanced
       | composition (parallelism for instance) , instrumentation
       | (debugging), etc... without burdening my DSL with ad-hoc,
       | invasive implementations. More importantly I can reuse these
       | facilities across DSLs.
        
       | MoreQARespect wrote:
       | This ("the rule of least power") is a rule I abide by
       | religiously:
       | 
       | https://en.wikipedia.org/wiki/Rule_of_least_power
       | 
       | I build lots of DSLs/configuration languages but Im pretty
       | militant about killing them if requirements dictate a need for
       | anything resembling loops or conditionals. Those are the the
       | klaxon warning bells telling you that you should just be writing
       | code/a library.
        
       | CraigJPerry wrote:
       | I'm working on this just now and this article was one of the ones
       | passed around when I was working through the design. I found that
       | article's framing really useful for several of the discussions.
       | 
       | I'm heavily down the path of composability, it's all ended up
       | very monadic but I've resisted the DSL idea. One thing that I've
       | still to solve is some kind of polyglot binding. If I'm saying no
       | dsl and you get to express config in a regular programming
       | language, it'd be nice if I could say your home / preferred
       | language. Every way I've come up with for that so far just sucks.
        
       | jstanley wrote:
       | I actually really don't like moving configuration out to a config
       | file unless it actually is necessary. I also don't like feature
       | flags except where actually necessary.
       | 
       | Yes this gives you more power to change things with config
       | instead of code, but it means that from now on you have to treat
       | those values as abstract quantities rather than as something you
       | can actually reason about.
       | 
       | Prefer to put configuration near where it is used. Prefer to put
       | utility functions near where they are used. A single page of code
       | is your "cache" and accessing information in the same page is way
       | faster than having to look elsewhere, and that's even if you
       | already know where to look.
       | 
       | Obviously you need to make exceptions for things that genuinely
       | need to be configured elsewhere, but if it doesn't need to be
       | configured elsewhere, please just configure it right by where you
       | use it. It makes debugging and understanding the code a lot
       | easier.
       | 
       | Option 1:                   sub truncate {           my ($self,
       | $str, %opts) = @_;           my $max_length = $opts{max_length}
       | // $self->max_length // get_optional_config('max_length') // 15;
       | return substr($str, 0, $max_length);         }
       | 
       | Option 2:                   sub truncate {           my ($self,
       | $str) = @_;           my $max_length = 15;           return
       | substr($str, 0, $max_length);         }
       | 
       | In option 1 you have 3 different places to specify max_length
       | (and you just know that $self->max_length is going to look in
       | more than one place as well...). Trying to divine the actual
       | behaviour of truncate() from this code is very difficult, and it
       | gets worse for functions that do more complicated things and are
       | configured by multiple interacting parameters.
       | 
       | In option 2 you know it truncates at 15 characters, no
       | exceptions.
        
       | Artoooooor wrote:
       | Going full circle on the clock looks like achieving full inner-
       | platform effect: https://en.wikipedia.org/wiki/Inner-
       | platform_effect. In short - we make our application so
       | configurable that the "configuration" language mimics the
       | platform our application is wrote in, albeit poorly.
        
       | myst wrote:
       | I know one application that went full cycle from the get go:
       | Emacs.
        
       | oftenwrong wrote:
       | I've had the misfortune of working on "enterprise" software where
       | avoidance of "hard-coding" went so far that the core system did
       | almost nothing other than exist as a way to plug in mutable
       | functionality. All in the name of not having to re-build, or to
       | re-deploy, and being able to tell the customer that no code
       | changes would be required, even though the "configuration" was
       | practically code, and required many of the things that code might
       | require, like qualified configuration developers, test suites,
       | and detailed deployment plans. Truly madness. In the era of
       | software as a service via internet, software is more "soft" than
       | it has ever been. You can change it and deploy it to production
       | any time you please.
        
       ___________________________________________________________________
       (page generated 2025-04-05 23:02 UTC)