4

(The code I'd have to post is huge, I'll resume to just function names)

I'm currently faced with the following issue on my project: I have a "each module from this framework can have a small view that users use to control its behavior" view-container sort of.

Basically each module can have a visual spot in a list, where users can click and see what they can do with the said module, thing is, my modules all respect the ModuleInterface interface, so the system knows they are in fact a module and each module must respect the following:

shouldItLoad, loadModule, getModuleName, getStartingAction, getPriority all of which are essential, it sounds like it does a lot, but it's a must, yet I still feel like if I add more on top of this, I end up with an object that just does too much.

It just turned out now that I'd like each object that wants to be on that view-container to also respect the ViewBlock interface, which would have a few functions on its own, just for my system to be able to ingest them and create that view.

We're now at minimum 9-10 functions, just so that I can get it to work. It's a hell to read through and most importantly, it does so many things, but:

  1. It's still that module's job to define its parameters for its view, not something else.
  2. If I were to opt in to passing a reusable ViewBlockObject which my Module then sets data to, ingests it and keeps it, I still have a lot of overhead, not to say that now **I cannot enforce a contract (since I'd need to keep my ViewBlockObject in a variable inside of Module).

What would the solution be here? How can I make each Module have behavior that must be respected by each of them that wants to have a view, without overheading the Module object itself?

  • sounds liek you need a ViewModel for the module – Ewan Apr 10 at 10:55
  • @Ewan Can you help me with this, any links? I can read code from other languages pretty ok-ish, but looking for something PHP-y (not necessary, I just need the blueprints). – coolpasta Apr 10 at 10:56
4

The answer is simple: put in the module the functions all modules must provide, not more, but not less either.

The single responsibility principle does not mean that a class should do only one thing. The do-one-thing-and-do-it-well is a different principle, that applies mainly to functions. The SRP only says there should be one reason to change, as Uncle Bob, the inventor of that principle, explains himself (and his disciples confirm). Both principles are often mistakingly confused, which sometimes lead to over-engineering. So consider the principle essentially from the point of view of cohesion and coupling in case of future changes. So it’s more about the causal responsibility for a change rather than the responsibility of the class itself

The other principle you should have a look at however, would be the interface segregation principle. Are you sure that all the functions promised by your interface is relevant for all modules ?

  • I see. Also, not all Module have to be ViewBlock, only these who have a need for it will be using the interface. Also, while it might sound weird, I'm a bit proud of the Module interface, because it contains solely the functions each of the objects of its type must respect, religiously. There's not a case where you'd need less than that (possibly more, depending on what the future features request). – coolpasta Apr 10 at 11:13
1

When it feels like there are too many methods the principle to consider is low coupling.

The SOLID principles are not the only principles. Please respect the sound principles that don't have awesome public speakers backing them.

The first thing I'll chalange you on is shouldItLoad. How about never you mind? Just tell me it's time to load and I'll load if I feel like it. If something needs to be told I loaded tell me what and I'll tell that. You just worry about telling me when.

Following tell-don't-ask like that might help you simplify your interface. Nothing complicates an interface like being a control freak that must know every little detail of what's going on. No, push the details away and make something else deal with them.

Similarly rather then ask to getStartingAction how about you just call start when it's time to start? Also, be sure you have a good reason not to just always start right after a load.

0

If you feel that a class implementing the interface does more than should be in a single class, you can still separate the things you think belong together into separate classes.

Then, a single class that implements the interface can compose those classes. It contains instances of those classes and just redirects calls to the outer methods to those classes.

I'm a little bit interested in how multiple classes all interact with all of the same members of the same interface. I can't say without seeing it, but that hints at some room to refactor the classes that depend on the interface. Does one method interact with all of those dependencies? If not, does that method look a lot like duplicate code?

Or, among the classes that depend on the interfaces, do different public methods use different members of the interface without overlap? In that case maybe they could or should be separate classes. Using different members of the interface might suggest that methods in that class are doing different things.

If the latter turns out to be the case, then it could result in classes that only use some interface members, which in turn leads to segregating the interface, which in turn solves the original problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.