Theoretical Question: CLI Argument Passing

Cyrilix

2[H]4U
Joined
Jan 21, 2005
Messages
2,188
Let's say I have an entry point to my application, and it's a main() procedure in class A. The class A does some work, creates an instance of class B, and the instance of B does some work and creates an instance of class C, and so on... D, E, F, until some class K. Basically, I'm about 10 classes down in a fairly complex program (K or 10 is fairly arbitrary as this is a theoretical question but that would probably be fairly realistic in any case). Inside K, I need to finally parse command line arguments which are now required for K to know what it has to do. Say, for instance, that K does some configuration, but how it does its configuration is dependent on the values of passed-in command line arguments at the executable level (top level).

What are my options for getting my command line argument information from A down to K? Just to provide some context, I'm talking about object-oriented language design. If it helps, you can use one of the C-based languages as a structural reference.

If I pass them unmodified via the constructors from B to K, then everything from B (ie., A+1) to J (ie., K-1) serves only as a messenger for data (depends on / moves data that it doesn't care about at all) and is therefore coupled to this data.

Code:
class A
{
    public int main(argc, argv)
    {
        // do something
        B* obj = new B(...);
        obj->execute();
    }
};

class B
{
    public void execute ()
    {
        // do something
        C* obj = new C(...);
        obj->execute();
    }
};

...

class K
{
    public void execute ()
    {
        // wants to parse command line arguments and use them to do something
    }
};

I can also use a class which is statically initialized / has static variables which map to the command line arguments. Say, command line argument parser, ArgParser. This would make it so that only K is tied to the data, nothing else.

Code:
class ArgParser
{
    public static int getValue (const char* key);
    public static void setValue (const char* key, int value);
};

class K
{
    public void execute ()
    {
        int x = ArgParser::getValue("arg1");
        // do something with the value
    }
};

Any other suggestions? Does anyone have any knowledge or know of any books which talk about this specific problem?

Thanks.
 
Last edited:

Zangmonkey

2[H]4U
Joined
Jul 6, 2005
Messages
3,946
This is a linked list. I would have each class expose a PassArgumentAlong method.
 

Cyrilix

2[H]4U
Joined
Jan 21, 2005
Messages
2,188
This is a linked list. I would have each class expose a PassArgumentAlong method.

If you were to do that, it would look something like this?

Code:
class B
{
    private int argc;
    private char** argv;

    public void execute()
    {
        // do something
        C* obj = new C(...);
        obj->passAlong(argc, argv);
    }

    public void passAlong(int argc, char** argv)
    {
        this.argc = argc;
        this.argv = argv;
    }
};

To be honest, I think this is no different from what I previously had mentioned as the first suggestion except that instead of passing it along via the constructor, it's being passed via a method.
 

Tawnos

2[H]4U
Joined
Sep 9, 2001
Messages
3,808
This sounds like a problem for a factory class. Rather than having A->B->C-> ... ->K, have a factory that constructs each in turn. If the construction of B relies on some property of A, either figure out what that property is and extract it, or (less ideal in my opinion, though really it's problem-specific) pass A into B's constructor (appropriate mechanism for doing so is language dependent), B into C's, etc. Then you only need something like this:
Code:
class Program
{
public static int main(string[] args)
{
Car car = CarFactory.BuildCar(args);
}
}

public class CarFactory
{
private CarFactory() {}
public static Car BuildCar(string[] args)
{
Car car = new Car();
CarPartA a = new CarPartA(args);
CarPartB b = new CarPartB(args, A);

(alternatively, have an internal parse args to the factory and use it:
ParseArgs(args);
if (args.needWheels)
{
CarPartA a = new CarPartA();
car.Add(a);
}
)
...
car.Add(a);
car.Add(b); 
...
}

}

CarParts can either be internal classes to CarFactory, independent classes, etc. Really depends what your actual goal is.
 

Wiseguy2001

2[H]4U
Joined
Nov 28, 2001
Messages
3,466
Any other suggestions? Does anyone have any knowledge or know of any books which talk about this specific problem?
Thanks.
Command Pattern, and better yet here's a video that explains it (they have a free trial). Also, please use an interface if you need a number of classes to share the same interface or anybody else who touches that code will want to track you down and kill you.;)
 

Cyrilix

2[H]4U
Joined
Jan 21, 2005
Messages
2,188
Command Pattern, and better yet here's a video that explains it (they have a free trial). Also, please use an interface if you need a number of classes to share the same interface or anybody else who touches that code will want to track you down and kill you.;)

I know I used object oriented programming as a context, but the REAL context is actually TCL programming (this variable cannot change, unfortunately) with iTcl. Interfaces aren't really a TCL abstraction, but you can emulate some features of an interface with a data-less class (though it's not as pure as an interface / there are no language features that support this design).

@Tawnos: I'm currently thinking about your idea and trying to apply it to what I have. It seems interesting, but I'm not sure how easy it will be to apply. Thanks.
 

Whatsisname

[H]F Junkie
Joined
Nov 15, 2000
Messages
10,202
I think processing command line arguments way down the processing chain is a bad start.

Parse your command line arguments first. Deal with quick exit stuff like --help and --version. Then, organize your parameters into a sensible structure and then toss them into the chain.
 

Cyrilix

2[H]4U
Joined
Jan 21, 2005
Messages
2,188
I think processing command line arguments way down the processing chain is a bad start.

Parse your command line arguments first. Deal with quick exit stuff like --help and --version. Then, organize your parameters into a sensible structure and then toss them into the chain.

In this case, some arguments would be processed right away, but there are also some arguments that aren't processed right away. The problem is that you might have a big application that does many things, which wraps many small classes that do a single thing.

If I take your idea and parse all the arguments first, that can be easily done, but what that still leaves me is an object representation of the command line arguments that don't yet need to be used. This object still has to be passed down to class K.

If I decide to simplify the program such that it doesn't do as much (then users have to do a lot more micromanagement - say, instead of running...

Code:
largeProgram -configureX false -configureY true > result.txt

...I would have to run...

Code:
smallProgram -config false > out.txt
smallProgram2 -config true -configFile out.txt > out2.txt
smallProgram3 -config true -configFile out2.txt > result.txt

The above is an example. It would actually be even more complicated than just three small programs (it might be 10-12 small programs with non-cyclic dependencies on each other).
 

Zangmonkey

2[H]4U
Joined
Jul 6, 2005
Messages
3,946
do the intermediate classes need any of the arguments?
If not, what about an event broker pattern?
 
Top