N
N
Nikita Roschenko2015-12-22 19:28:44
PHP
Nikita Roschenko, 2015-12-22 19:28:44

How to choose the right architecture (OOP) for the task?

I can’t choose the right architecture for the task, I’m writing something like a site aggregator.
There is an Account model with the following fields: login, password, provider_name
There is a Manager class, in the constructor of which the Account model is passed. The Manager class has a getProvider() method. Which initializes and returns an object of the Provider class according to the value of the provider_name property in the Account model.
Each aggregated site has its own Provider class that can implement interfaces, for example: ProfileInterface, MessageInterface, NewsInterface, etc.
Interfaces describe the basic methods for working with the site. So that you can work in a loop (using the instanceof construct) with different sites without thinking about what happens inside the Provider class.
So it turns out that when the Provider class implements several interfaces, then everything is fine, but when the number of implemented interfaces becomes more than 5-10, the file becomes unreadable, there are too many methods in the Provider class.
Suppose there are such providers:
Social/VK/Provider
Social/OK/Provider
Social/Facebook/Provider
The Manager class, receiving the Account object in the constructor by the provider_name field, finds the required Provider, for example, Social/VK/Provider and initializes it and returns the Provider object. That is, authorization is carried out on the Vkontakte website in the constructor of the Provider class.
Next, there is a task to get news from all accounts:

foreach($accounts as $account) {
    $provider = Manager::getProvider($account);
    if ($provider instanceof NewsInterface) {
        $news = $provider->getNews();
        //...
    } else continue;
}

First of all, I remembered traits, but the fact is that methods from different interfaces can use each other (for example, a trait describing the implementation of the MessageInterface interface uses a trait describing the implementation of the ProfileInterface interface). And in almost every trait there is work with the database, the connection of which is in the property of the Provider object.
In general, traits work, but not aesthetically beautiful. I'm sure there is a better implementation, but I can't find it.
Thanks in advance for any comment and suggestion =)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexey Ukolov, 2015-12-22
@alexey-m-ukolov

So that you can work in a loop (using the instanceof construct) with different sites without thinking about what happens inside the Provider class.
That's what polymorphism is for. Instanceof is an antipattern.
By and large, the replacement of traits is aggregation. Inject the necessary handlers in the provider's constructor and call them already:
class FooProfileThing implements ProfileThingInterface {}

class FooMessageThing implements MessageThingInterface {}

class FooProvider extends Provider
{
  public function __constructor($bar)
  {
    $this->bar = $bar;
    $this->profileThing = new FooProfileThing;
    $this->messageThing = new FooMessageThing;
  }
}

In this way, you will respect the principle of single responsibility and will be able to more intelligently build a hierarchy of these objects.
And anyway, what are these Profile , Message , News objects for which you created an interface? Why does Provider behave like profile, message and news at the same time? Are these entities really the same type?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question