0

We have a very common calculation Compute that can be done multiple ways. These inherit from some IFoo interface. We'll call them FooRed and FooBlue.

class FooRed : public IFoo
{
public:
   FooRed() = default;
   virtual double Compute() override final; //Inherited from IFoo.
}

A shared_ptr<IFoo> is distributed among many objects so that as they go about their business they can Compute in the same way. The original shared_ptr<IFoo> myFoo = make_shared<FooRed>() sits up above and gets handed out to objects as they get constructed: SubObject(myFoo).

Later in development, its decided that it may be useful for the calculation to change modes from FooRed to FooBlue during runtime. To this end, a template class is written

template<class T>
class Toggleable:
{
protected:
   std::shared_ptr<T> _instance;
   bool _state;
public:
   Toggleable();
   T* const Get() const {return _instance.get()};
   const shared_ptr<T>& GetRef() const {return _instance};
   virtual void Toggle(); //sets _instance to the correct type.
}

And the corresponding FooManager

class FooManager : public Toggleable<IFoo>
{
public:
    virtual void Toggle() override; //Inherited from Toggleable
}

So now the UI or whatever has access to the original FooManager can Toggle it, and references to the internal state are handed out to the objects as needed: SubObject(myFoo->GetRef()). Everyone has the same reference so they all compute in the same way.

However, my first inclination was to make FooManager also implement IFoo itself, sort of like a Container pattern:

class FooManager : public Toggleable<IFoo>, public IFoo
{
public:
    virtual void Toggle() override; //Inherited from Toggleable
    virtual double Compute() override {return Get()->Compute();} //Inherited from IFoo
}

This way, you don't have to change the constructor calls and the implementation of the toggle changes as little of the underlying code as possible. Everyone who already had or was passed an IFoo still sees it as one, and only the parts that now handle the toggling need to see that object as a FooManager or Toggleable.

I also think its more consistent for constructors, since if Foo is Toggleable but Bar isn't, a subobject that needs to do both is constructed with SubObject(myFoo->GetRef(), myBar) in an awkward mix of references to shared pointers and shared pointers. But my coworker said that this sort of multiple inheritance is bad practice, and that this structure muddies the behavior of a manager and the actual Foo.

Is this good practice? How should one properly implement a run-time toggle like this that needs to switch between multiple sub-elements?

4
  • Design patterns are great when you know your patterns and are given a problem that fits one of them. If you don't know what pattern to use, don't ask for a pattern. Ask for a solution, and if someone answers by telling you what pattern to apply, excellent! But not every problem is well-served by a pattern and trying to brute force a problem into fitting a design pattern ends in bad code or tears. That's a mathematical or; quite often you wind up with bad code AND tears. Now I'm going to get off my soap box and see if I understand the question enough to offer a solution. Commented Apr 17, 2024 at 21:31
  • Looks like you aren't necessarily looking for a solution. You're looking for a sanity check. Be cautious with toggleable as it's not thread safe. It would suck if one thread toggled while anther thread had a reference checked out from GetRef. Commented Apr 17, 2024 at 21:47
  • Half sanity check and half solution, I think. Neither I nor my coworker have much formal training in software design; we're both up jumped (non-software) engineers who have found themselves in charge of writing a piece of engineering software. Ultimately he's the lead and his design decisions go, but I'm trying to learn about better design and structure as we go. Figured this would be a good problem to pose to the community. Commented Apr 17, 2024 at 22:00
  • 1
    Some of the best programmers I know are Electrical and Mechanical Engineers. Some of the worst programmers I've met have Comp Sci degrees. I think it comes out in the wash. Commented Apr 17, 2024 at 22:02

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.