2

I am working on a command-line application that runs simulations. It has to be heavily configurable; the user should be able to provide a very large number (100+) of parameters, some mandatory and some optional. Obviously, these parameters will be used by a variety of classes in the application.

I can see two approaches I can use; which one is a better design in the long run?

Approach 1

Have the (text) input file directly control object creation in the application. For example, user would provide the following input:

root=Simulation time=50 local_species=Sentient strength=3.5 intelligence=7.1 invading_species=Primitive strength=5.1 sociability=2.6 

The application would then recursively create objects of the class specified on the rhs of the equal sign, passing the class' constructor the arguments provided in the relevant sub-branch of the input file, if any. I'm using Python, which supports keyword arguments and default argument values when no argument is provided, but I hope the question isn't terribly language-specific.

For example line 1 would tell the app to create an object of class Simulation, with three constructor arguments. The first constructor argument is time=50. The second argument is an instance of class Sentient, which is created by passing Simulation's constructor arguments strength=3.5, intelligence=7.1. The third argument is an instance of class Primitive, which is created with by passing the constructor arguments strength=5.1, sociability=2.6.

The whole object creation is handled automatically, with just a few lines of (recursive) code. The highest-level object (instance of Simulation in this case) would be passed to the visualization layer.

Approach 2

The input file still looks the same. However, the application's classes now have full control over how they interpret user input. The lhs and rhs values may or may not correspond to keyword parameters and classes. For example, the above input may result in the application creating an instance of class InvasionSimulation with arguments strength_local=3.5, intelligence_local=7.1, strength_invading=5.1, sociability_invading=2.6, and then calling its method set_runtime(time=50), before passing the object to the visualization layer.


One obvious advantage of approach 2 is that the user's input can remain stable even as the application is completely redesigned internally. But I think there's nothing wrong with designating a subset of classes as "public API", and therefore ensuring that it doesn't change in the future, is there?

On the other hand, if the application internally follows something quite similar to approach 1 anyway, it feels that approach 2 requires adding a lot of redundant code: instead of automatically interpreting user input, we now need to do it "by hand" for each class.

Any additional considerations would be much appreciated. Are there any names for these approaches that I can search for?

2
  • You might want to have a look at JCommander - jcommander.orgCommentedJan 22, 2013 at 9:06
  • @SpaceTrucker Unless I missed something, it doesn't support any hierarchy of used defined parameters. If so, it may be quite good for command line parsing but perhaps insufficient for a more heavy-duty configuration file that I need.
    – max
    CommentedJan 22, 2013 at 13:01

2 Answers 2

1

I would use somethink like JAXB (in java and with xml configuration), or some JSON mapper (with JSON configuration) (I don't like languages where number of whitespaces is significant, but thats personal taste). Or some other mapper for your prefered/forced format.

With this, I would use mapped objects if they match what I need inside aplication (approach 1) , and if not I would use them as parameter for factory methods (similar to approach 2), so format of their textual source does not matter, only their content while loaded. This would allow to use multiple input formats without changing anything else than reading of those files.

I would start with approach 1 if it looks promising and refactor later.

3
  • Based on your comment, I'm now thinking to give each class a choice. It it wants, it can do nothing, and the input will be parsed following approach 1 coded in the base class' method parse. Alternatively, it can override parse method with an alternative parsing logic, following approach 2 (of course, if it then needs to create an instance of class that didn't override parse, it will need to supply it with something that looks like a sub-branch of a configuration file). Does this sound reasonable?
    – max
    CommentedJan 22, 2013 at 10:07
  • As long as it does not need information from other parts of configuration (esp. later in configuration) (eg. two parts referencing each other). But that is something to avoid anyway. Second thing: This way object does two greately different things, parsing its initial state from text and doing something usefull. But if used format is stable it should not be problem. But if it was changing, suporting multiple version this way could be problematic to maintain. In that case, parsing should be exteral to object (so different strategies can be used).CommentedJan 22, 2013 at 14:04
  • I'm going to give approach 1 a try. I'm a bit skeptical because I haven't seen it mentioned anywhere.
    – max
    CommentedJan 24, 2013 at 21:05
0

In my personal experience the single best approach to pulling command or config arguments into a command line program is a dictionary. The input is naturally structured as key-value-pairs so it just make sense from an input standpoint, but the bonus is maintainability when you merely have to add new key handlers and never new parsing code as the parser simply pulls everything into a dictionary allowing whatever keys needed. Also it doesn't force scoping onto the consumer of the arguments space, so each argument and value is available by default to any consumer who feels it relevant, you don't have to do leg work to publicize the argument and value to consumers.

Moreover, I have had a habit of creating at start a dictionary available to main which has a list of keys that correspond to arguments, and a list of values which are functions to parsing and handling said keys in so far as those keys require configuration of the system state before processing occurs. For example, a key of v may have a func that parses the value of that arguments key into setting System.Verbosity = true; and the argument parser just calls _startupDictionary[argument](value); and if the function returns false that means the argument was invalid or had an invalid argument, in this way it may notify the argument parser that the system state will be inconsistent given the set of arguments available and cannot therefore process correctly.

3
  • Originally, I followed precisely the same approach (key-value pairs). However, this caused name collisions in keys (e.g., strength in my example) as well as some other problems.
    – max
    CommentedJan 22, 2013 at 6:38
  • @max If you need structure, nest dictionaries so the same parser function can be called, as soon as your parser notices a decent it exits to allow the parent parser to continue with it's dictionary parser.CommentedJan 22, 2013 at 13:41
  • So all user input would be converted to a mulit-level (nested) dictionary structure, and passed to the application? That would be very similar to what I'm trying now with approach 2, right? Would you allow each class to grab only the items in one level of this structure, or to look as deep as it wants?
    – max
    CommentedJan 22, 2013 at 13:59

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.