2014-02-28
Yet another problem with configuration by running commands
One of the divides in how programs, daemons, and systems get configured is between configuration files and what I'll call 'configuration by command', where you set up the system by running commands and the system persists them behind your back in some magical or at least internal way. I've written previously about the ways that configuration by command harms manageability but today I stumbled over another problem with it.
Put simply, configuration by command robs you of things to copy. When you have a system that is set up through configuration files, you have a ready made source of things to copy and modify; you find one of the configuration files, make a copy, and change things. When you have a system that's set up by running commands you can see the end state but you almost never have something that will dump out the commands necessary to recreate that end state so that you can copy and modify them. Want to set up another instance of the system? You get to reverse engineer the full set of magic commands and options necessary, which may mean that you have to learn, understand, and perhaps master the entire system.
The real fix for this is something that all too few 'configuration by command' systems have, which is a way to not just report the configuration but to dump out the commands necessary to reproduce it. Documentation is only a partial help and then only if it's clear and ideally has any number of examples.
(This entry is brought to you by yet another attempt to set up a
serial port under Solaris OmniOS. Unlike last time there is another configured serial port
whose configuration I would be happy to copy and modify slightly, except
for this exact problem.)
Arguments for explicit block delimiters in programming languages
Suppose that you have a language where indentation levels are significant; either they explicitly delimit blocks (as in Python) or mismatched indentation is an error. I maintain that this is a good thing in a language in general because it makes human semantics match computer semantics. One of the big questions about such a language is whether it should have explicit block delimiters or rely purely on indentation levels.
A lot of people will likely argue for the Python approach of implicit delimiters, ie that blocks are created and exited by indentation alone. Although I like Python, I actually tilt towards at least allowing and perhaps requiring explicit delimiters. I see two advantages to explicit delimiters.
First, explicit delimiters are in fact explicit. They provide
confirmation that you did indeed intend to create a new block or
to exit one and that you didn't just accidentally get the indentation
wrong on a line. This is going to be especially important in a
language where you can create new block levels at any time (not
merely after a language construct such as if
or while
) and such
blocks can have semantic meaning such as containing block-local
variables.
(Note that Python is not such a language. Unlike C, where you can create
a block anywhere just by dropping in {
and }
, Python blocks can only
be started after specific statements.)
Without explicit delimiters there are a number of ways for block errors to creep in, even in languages like Python. I feel that the explicitness of block delimiters is definitely suited for languages that are designed with an eye towards software engineering pragmatics in the line of Go's design; in such languages you'd rather make the programmers do a bit of extra work than have an error slip by.
Second, explicit delimiters enable you have to have blocks that are smaller than a single line and to have several such blocks on one line. Consider:
if (acheck()) { b = 10; fred(); } else { b = 30; barney(); }
You can't do this without explicit block delimiters. Of course, some people will probably say that you shouldn't do this even with block delimiters; if you agree, this is not a very compelling point and may in fact be an argument against explicit block delimiters.
I personally like such compact blocks, in part because of issues like anonymous functions (or real lambdas) where you may well want to put several short statements on a single line and in fact explicitly package them up as a block for the lambda.
(I believe that lacking a good syntax for such inline code blocks is one
reason that Python has such a limited lambda
operator.)