Reputation: 63
What is the best approach to reduce coupling between modules?
For example, if I have an Invoice
package and it is related to theCustomer
package.
What I understand is that I would have to use a system of "hooks" to inject, for example, a tab with the list of customer invoices in the edit view of a customer.
And in turn, use an event system to know, from the perspective of the "Invoice" package, when, for example, someone tries to delete a client.
What I want to achieve is to reduce the coupling so that if I delete the invoice package, the client package is not affected.
How can I get it? Using Laravel's event system? Using a custom class like the following?
My Hooks class:
class HookRepository
{
/**
* The repository items.
*
* @var \Illuminate\Support\Collection
*/
protected $items;
/**
* Create a new repository instance.
*
* @return void
*/
public function __construct()
{
$this->items = collect();
}
/**
* Dynamically call methods.
*
* @param string $method
* @param array $arguments
* @return mixed
*/
public function __call(string $method, array $arguments)
{
return $this->items->{$method}(...$arguments);
}
/**
* Register a new hook callback.
*
* @param string|array $hook
* @param callable $callback
* @param int $priority
* @return void
*/
public function register($hook, callable $callback, int $priority = 10): void
{
$this->items->push(compact('hook', 'callback', 'priority'));
}
/**
* Apply the callbacks on the given hook and value.
*
* @param string $hook
* @param array $arguments
* @return mixed
*/
public function apply(string $hook, ...$arguments)
{
return $this->items->filter(function ($filter) use ($hook) {
return !! array_filter((array) $filter['hook'], function ($item) use ($hook) {
return Str::is($item, $hook);
});
})->sortBy('priority')->reduce(function ($value, $filter) use ($arguments) {
return call_user_func_array($filter['callback'], [$value] + $arguments);
}, $arguments[0] ?? null);
}
}
Upvotes: 1
Views: 300
Reputation: 2869
Using interfaces and abstract classes to implement Open/Close principle from SOLID
Note: If you are doing this in hope you will avoid refactoring your code. Forget it. :) It will only make it a lot easier which already is a huge benefit.
Avoid using hooks to realize Structural and/or Behavioral patterns.
edit> Neither Package nor Hook is a part of Laravel or Design Patterns lingo.
This itself should give you a hint.
Let me play a guessing game:
<?php
PackageInterface {
public function enable();
public function disable();
public function isEnabled();
public function getHooks(): HookInterface[];
}
HookInterface {
public function injectView();
// or maybe
public function injectIntoView($view);
}
It purely depends on your circumstances when you will load your packages and inject something into view.
You can for example enable()
the Package when $invoice->wasPaid()
or when Customer enabled the package himself $customer->enable($package)
Upvotes: 1