0

I have a controller that is violating Open and Closed Principle. I'm trying to figure out how to solve this with certain conditions. Here is the implementation.

struct BasicRecording
{
  void show() {}
  void hide() {}
};

struct AdvanceRecording
{
  void show() {}
  void hide() {}
};

class NotSolidRecordingSettingsController
{
  BasicRecording br;
  AdvanceRecording ar;
public:
  void swithToAR();
  void swithToBR();
};

void NotSolidRecordingSettingsController::swithToAR()
{
  br.hide();
  ar.show();
};

void NotSolidRecordingSettingsController::swithToBR()
{
  ar.hide();
  br.show();
};

The problem here is if I have a new recording settings, I would need to go back inside settings controller and add that new recording settings. If I inject the BasicRecording and AdvanceRecording in NotSolidRecordingSettingsController, then the Object instantiating NotSolidRecordingSettingsController will need to do the instantiating of BasicRecording and AdvanceRecording. But then that Object then violates OCP. Somebody has to create the object.

How can I design this to be OCP without just off loading the Not OCP part to some other thing?

Is there a particular design pattern for this kind of problem?

user3904534
  • 309
  • 5
  • 13

1 Answers1

0

In the SOLID principles, OCP is really a consequence of SRP -- a class should have a single responsibility, and its code should only change when its internal requirements -- the requirements associated with its one job -- change.

In particular, a class shouldn't have to change because it's clients change. It may have a lot of clients and you don't want to mess with its code every time it gets new clients or the existing clients need to do something different. Hence OCP. Note that in OCP, "closed for modification" means you don't mess with it when you change the stuff that uses it. You do modify it when its own internal requirements change. That's just maintenance.

So OCP is about how classes relate to their clients, BUT, there are classes that have no clients. Their job is not to be services, and they are not used by other classes or to implement APIs, etc. These classes do not need to worry about OCP, because they naturally have no reason to change other than a change to their internal requirements.

A great example of such a class is what is sometimes called a "composition root" (googlable). Its single responsibility is to define how the system is built from its components. This is the guy that creates all the objects and injects them into everywhere they're needed.

You need a composition root that injects the settings panes into the controller (and whatever triggers them, because you can't have a method called switchToAR anymore). This class' job is to define the system by creating the required objects. When the arrangement of objects needs to change, then, that is a change to its internal requirements and you can go ahead and modify its code without violating SOLID.

(or you can have all that stuff read from configuration instead, but that is just implementing the composition root in config instead of your programming language. Sometimes that is a good idea, and sometimes not)

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87