views:

41

answers:

2

I've got a program where a lot of classes have really complicated configuration requirements. I've adopted the pattern of decentralizing the configuration and allowing each class to take and parse the command line/configuration file arguments in its c'tor and do whatever it needs with them. (These are very coarse-grained classes that are only instantiated a few times, so there is absolutely no performance issue here.) This avoids having to do shotgun surgery to plumb new options I add through all the levels they need to be passed through. It also avoids having to specify each configuration option in multiple places (where it's parsed and where it's used).

What are some advantages/disadvantages of this style of programming? It seems to reduce separation of concerns in that every class is now doing configuration stuff, and to make programs less self-documenting because what parameters a class takes becomes less explicit. OTOH, it seems to increase encapsulation in that it makes each class more self-contained because no other part of the program needs to know exactly what configuration parameters a class might need.

+1  A: 

Regardless of the way you do it, you have several "modules" which compete for the same sequence of command-line arguments. There must be some cooperation so that the same command-line arguments can be processed by your classes without clashes.

By having each class implements the parsing, you simply make that cooperation implicit. There is no module dedicated to the cooperation between your classes. The problem becomes a matter of documentation rather than a matter of code. It is not bad but it may seductively appear as if the problem has simply "gone away". To be brief, this practice requires more discipline.

Also, it will make major overhauls of command-line argument syntax more difficult.

Thomas Pornin
Overall, good points, but all classes use the same getopt lib, which isn't going to change.
dsimcha
+1  A: 

it seems to increase encapsulation in that it makes each class more self-contained because no other part of the program needs to know exactly what configuration parameters a class might need.

If I understand what you're proposing, it really makes each class hide their dependencies.

The dependencies in this case may be simple (primitive), but if a class needs an username and password to function correctly, it should say so in its constructor. Otherwise, the class' callers need to look at the source code or documentation to use it.

Jeff Sternal
That's one school of thought. I guess that, to some extent, this goes back to the ages-old explicitness vs. encapsulation argument. Sometimes there's a tradeoff between the two. I tend to favor encapsulation. Some favor explicitness.
dsimcha
I suppose it's a question of whether the class can do its work without the settings. You can't *encapsulate* dependencies - if a dependency isn't provided, the class throws an exception or quietly fails, which is the opposite of encapsulation. Another way to say this is that they aren't encapsulated if you have to provide them. (Via configuration file or command-line arguments.)
Jeff Sternal
@Jeff: Yes, exceptions are thrown in some cases, but they're not meant to be caught. They're meant to simply display an error message and terminate the program. Also, a lot, but not all, of the options are simply optional flags with reasonable defaults. In these cases no exception is thrown.
dsimcha
Perhaps I've misunderstood what you're doing. From the question, it sounds like you're proposing something akin to replacing .NET's `DateTime` constructors (to take an example at random) with a single new constructor like this: `DateTime(params object[] args)`. Is that unfair?
Jeff Sternal
@Jeff: I don't use .NET, I'm using D, but it's more like `string[] args`. The parameters in question are basically integers, strings and flags. Nothing is more complicated than this.
dsimcha