On-the-fly Le Chatelier

From: JKop (NULL_at_NULL.NULL)
Date: 07/15/04


Date: Thu, 15 Jul 2004 17:05:43 GMT


I have a "system", this system is 5 values:

A
B
C
D
E

Each of these values is dependant upon all others. If you want an analogy,
then take your pick:

A) Electricity: Current is proportional to Voltage, and also to Resistence

B) Gases: Volume is proportional to Pressure, and also to Temperature

So if one value changes, they all change.

Anyway, at then end of the whole design, I want my GUI to be able to just
work with it similar to the following:

cout << somesystem.GetA();
cout << somesystem.GetB();
cout << somesystem.GetC();
cout << somesystem.GetD();
cout << somesystem.GetE();

I want to create a class to represent this system. The particular class with
which the GUI will work doesn't need to have any Set functions, so the bare
minimum would be:

class SystemX
{
public:

            int GetA() const;
            int GetB() const;
            int GetC() const;
            int GetD() const;
            int GetE() const;
};

or maybe even:

class SystemX
{
public:

            virtual int GetA() const = 0;
            virtual int GetB() const = 0;
            virtual int GetC() const = 0;
            virtual int GetD() const = 0;
            virtual int GetE() const = 0;
};

Now... in actually implementing this system, I *could* use 5 separate
variables and update them all at precisely the moment one of them changes.
Like so:

class SystemX
{
private:

            int A;
            int B;
            int C;
            int D;
            int E;

public:

            int GetA() const
            {
                        return A;
            }

            int GetB() const
            {
                        return B;
            }

            int GetC() const
            {
                        return C;
            }

            void SetA(int in_A)
            {
                        //Super algorithm

                        A = in_A;

                        B = A + 4;
                        C = A / 9;
                        D = 42 - A;
                        E = A * A - 5;
            }

            //And the rest SetB SetC...
};

The problem with this is that it's inefficent because the values need only
be calculated when they've to be displayed.
            So, moving on, I may come to:

class SystemX
{
private:

            enum { aA, bB, cC, dD, eE } specified_value;

            int value;

public:

            void SetA(int in_A)
            {
                        value = in_A;
                        specified_value = aA;
            }

            void SetB(int in_B)
            {
                        value = in_B;
                        specified_value = bB;
            }

            void SetC(int in_C)
            {
                        value = in_C:
                        specified_value = cC;
            }

            int GetA() const
            {
                        switch ( specified_value )
                        {
                        case aA:

                                    return value;

                        case bB:
                                    //certain algorithm
                        case cC:
                                    //ceratin algorithm
                        }
            }

            int GetB() const
            {
                        switch ( specified_value )
                        {
                        case aA:
                                    //certain algorithm
                        case bB:

                                    return value;

                        case cC:
                                    //certain algorithm
            }

            //and so on.
};

I'm not out-right saying that this is a bad method, but for the moment I'll
pursue an alternative. But.. before I get into that, I'd like advice on
splitting this class in half - I don't want the class that the GUI will work
with to even know about SetA, so would the following be advisable:

class SystemXInterface
{
public:

            virtual int GetA() const = 0;
            virtual int GetB() const = 0;
            virtual int GetC() const = 0;
            virtual int GetD() const = 0;
            virtual int GetE() const = 0;
};

class SystemXImplementation : public System XInteface
{
            void SetA(int); // ...
            void SetB(int); // ...
}

How is this usually done? Is the above any good?

Annnnyyyyyway... at the moment, this is how my system is:

class SystemXInterface
{
protected:

            int specified_value;

public:

            virtual int GetA() const = 0;
            virtual int GetB() const = 0;
            virtual int GetC() const = 0;
            virtual int GetD() const = 0;
            virtual int GetE() const = 0;

            void SetSpecifiedValue(int in_specified_value)
        {
                        specified_value = in_specified_value;
        }

        int GetSpecifiedValue(void) const
        {
                return specified_value;
        }

        virtual ~SystemXInterface() {}
};

class SystemXImp_SpecifiedA
{
public:
            virtual int GetA() const
            {
                        return specified_value;
            }

            virtual int GetB() const
            {
                        //algorithm
            }

            virtual int GetC() const
            {
                        //algorithm
            }

            //and so on
}

class SystemXImp_SpecifiedB
{
public:
            virtual int GetA() const
            {
                        //algorithm
            }

            virtual int GetB() const
            {
                        return specified_value;
            }

            //and so on
}

And here's how I'm interacting with it:

void DisplaySystem(SystemXInterface& intr)
{
            cout << intr.GetA();
            cout << intr.GetB();
            cout << intr.GetC();
            cout << intr.GetD();
            cout << intr.GetE();

            //Nice and simple!
}

int main()
{
            //If you want to manipulate A, then

            SystemXImp_SpecifiedA blah(567);

            DisplaySystem(blah);

            //If you want to manipulate D, then

            SystemXIMp_SpecifiedD blah(926);
 
            blah.SetSpecifiedValue(437);

            DisplaySystem(blah);
}

Okay, so basically I'd just like all sorts of comments, questions and
suggestions. Like:

A) Should I leave the private member variable "specified_value" in my
SystemXInterface class, or should I put another class in between called
"SystemXImplementation" and put the "specified_value" in that, and then make
the following relationship:

class SystemXInterface
{
public:

            virtual int GetA() const = 0;
            virtual int GetB() const = 0;
            virtual int GetC() const = 0;
            virtual int GetD() const = 0;
            virtual int GetE() const = 0;
};

class SystemXImplementation : public SystemXInterface
{
protected:
            
            int specified_value;

public:

            void SetSpecifiedValue(int in_specified_value)
            {
                        specified_value = in_specified_value;
            }

            int GetSpecifiedValue(void)
            {
                        return specified_value;
            }
};

class SystemXImp_SpecifiedA : public SystemXImplementation
{
public:

            virtual int GetA() const
            {
                        return specified_value;
            }

            virtual int GetB() const
            {
                        //algorithm
            }

            virtual int GetC() const
            {
                        //algorithm
            }
};

class SystemImp_SpecifiedB : public SystemXImplementation
{
public:

            virtual int GetA() const
            {
                        //algorithm
            }

            virtual int GetB() const
            {
                        return specified_value;
            }

            virtual int GetC() const
            {
                        //algorithm
            }
}

Any thoughts?

B) Should I cache values? Or should I leave that up to the user. For example
if some calls GetB, and then later calls it again without the system having
changed, should I have it cached, or should I calculate it all over again,
ie. should it be built-in class behaviour or should it be the user's
problem?

C) Any other things, like how I should name my variables and classes.

Thanks!

-JKop