Is there a good practice way of making communication between classes?
For example, I have a CMS I'm working on. In main class it instantiates two new Classes ThemeManager and ModuleManager. Now, I need my Theme Manager to be able to access Module Manager so that it can read loaded modules and print their content in a page.
Is this OK ? Making these two classes public properties of main class. This enables me two-way communication (which I don't necessarily need in this situation):
class MainClass {
public $ThemeManager;
public $ModuleManager;
..........
function instantiate_managers() {
$this->ThemeManager = new ThemeManager($this);
$this->ModuleManager = new ModuleManager($this);
}
}
Or is it this better? Passing one already instantiated to another, since one-way communication will do OK for my purpose:
class MainClass {
private $ThemeManager;
private $ModuleManager;
..........
function instantiate_managers() {
$this->ModuleManager = new ModuleManager();
$this->ThemeManager = new ThemeManager($this->ModuleManager);
}
}
Note that in either way I have to pass these references further to Module class and Theme -> Layout classes.
Maybe it would be better to declare ThemeManager and ModuleManager in global scope since they will be instantiated only once anyway and saves me the trouble of passing their references through each __construct ? I've read somewhere that this is bad practice in OOP and I'm trying to avoid it, but in situations like these this seems like the least hacky way to do it.
Is there a 4th good way to handle communication which I haven't tought about?
I ended up using Pimple for dependency injection method since it felt most natural and was suggested in both answers.
All your approaches sound bad. I could detail on this, but I honestly think that you'd learn best by reading a book on OOP, and then start using a modern PHP (5.3+) framework like ZF2, to get a feel for how it's done.
Dependency injection, highly modular, MVC, it's all in there for you to learn from.
However, within the limitations of your initial design, I would do it like this:
Where an Application
object coordonates the rest of the components. Please note the Application::render()
method which could return the entire html generated by the page.
Although I repeat, I do not think that you mean the right thing when you say "module" or "theme". You should really have a look at a modern PHP framework (PHP 5.3+) and see how software engineers have chosen to design these things.
You are missing for instance the notion of routing.
What you're asking for, is the best way to do dependency injection.
There's many ways to approach it, but in your specific case I would say: Go for option #2. Since your theme needs to be aware of the module, but not the other way round, this will solve your problem in the easiest fashion.
But: don't consider this a 'general answer' for dependency issues in the future. The best way to think about it, is each case individually.
Two more ways to do this:
setModuleManager
).Number two may seem appealing when you learn about. It's simple and central; but I would still be wary. It's a bit of a sledgehammer, and may actually cause you to create too tight dependencies. (loosely coupled is considered a very good thing).
setter methods or constructor arguments force you to be extremely explicit, and I feel it's the best way to learn this stuff.