On Tuesday, 1 August 2017 at 17:46:57 UTC, H. S. Teoh wrote:
I think UDA-driven configuration parsing is ultimately the right direction to go. And by that I mean more than just command-line parsing, but the parsing of configuration parameters in general, including command-line options, configuration files, etc.. Usually a lot of boilerplate is involved in constructing a parser, enumerating options, then mapping that to configuration variables, adding helpful descriptions, etc.. All of which are a maintenance burden on the programmer, because any of these components can become out-of-sync with each other: the parsing of parameters, the mapping of these parameters to internal variables, and the help text.


args.d uses the same parser for command line options and for the config file. The parser gets adapted between the two with some compile time parameters.


With UDAs, it's possible to unify all three in one declaration, thereby ensuring things will never go out-of-sync, and also greatly reduces the amount of boilerplate the programmer has to type.

I didn't look too closely at args.d yet, but in my implementation, I have UDAs for specifying alternate names for common configuration parameters (e.g., "outfile=..." instead of "outputFilename=..."). This allows more user-friendly option names, and also decouples it from internal variable naming schemes.

I found that good variable names make good command line option names.
And you remove one indirection, which I always like.
Plus, you can always use short options, which are checked for uniqueness at compile time by args.d.


There's also UDAs for optionally flattening a nested struct, so that internally I can have separate structs for configuring each module, but the main program combines all of them into a single flattened struct, so that to the user all the options are top-level (can specify "outfile=..." instead of "backend.outputFilename=..."). The user shouldn't need to know how the program is organized internally, after all, yet I can still properly encapsulate configuration parameters relevant to only that module, thereby avoiding spaghetti dependencies of modules on a single global configuration struct.

I thought about that as well, but didn't do it because if found:

--mysql.ipAddress Type: string default: localhost Help: --redis.ipAddress Type: string default: localhost Help:

looks and works just awesome.
At least better than --mysqlipAddress and --redisipAddress.


Reply via email to