简体   繁体   中英

How should services communicate between each other?

While learning from @tereško's answer on how should a model be structured, I can't find what is the best way for communication between the services. I also found this answer which is a similar situation I'm dealing with, but the example is great for showcase. So, in that sense, how do I retrieve the recognition service inside of a Blog service for example, when the service has only access to a domain and mapper factory objects. Do I send it from the controller? Or do I need to send a service factory too?

Update : I did not provide an example since I mentioned that the second answer of tereško is pretty similar to what I am trying to achieve. I am trying to build a BlogService that for example stores a post. In order to store the author of the post, I am trying to retrieve the (his called) recognition service in order to get the logged in user (which is apparently the author of the post).

class BlogService
{
    public function storePost($title, $content)
    {
        $post   = $this->domainFactory->build('Post');
        $mapper = $this->mapperFactory->build('Post');

        $post->setTitle($title);
        $post->setContent($content);
        $post->setAuthor( /* get logged in user */ );

        $mapper->save($post);
    }
}

The theory

So basically your question is "how to share a domain object from Recognition service with some Content service?" . I have been actually thinking on this for some time.

As I see it, there are 4 options here. Two shitty, one good one and one in-between:

  1. Previously mentioned "pass the service factory" approach.

    This is the most naive solution, because in a real world situation you will end up with uncontrollable growth for the object graph - service containing services containing services .. ad nauseum .

    It's unsustainable, but quick.

  2. Alter the Recognition service in such a way, that it spits back an Account instance to the controller, which then in turn passes is to other services.

    Essentially you would end up creating an intentional leak between layers in order to minimize complexity. You could call this "architectural denormalization".

    It's a hack and a bad architecture.

  3. Use a DI container to share domain objects (and even mappers) between services.

    This way is more elaborate previous two, but it also would let you get rid of the factories inside your services entirely.

    Best option , but requires additional skill and code.

  4. Use your domain object factory to create the instance of Account (and either all others or selected ones) only once.

    Kinda like in this post, but for domain objects. Of course you will need some way to also bypass the "cache", because a large group of domain objects will require an ability to be initiated more than once. Thus - a need for some configuration.

    A tricky half-way solution, but lets you keep familiar API within services.

Confession

I myself am currently using the option 2. The reason for it is that I don't have a DI container which I could use (and I thought of "option 4" only 5 minutes ago). Most of what you see under description "PHP DI container" are actually various service locators (in which case you are better off with bunch of factories anyway).

If you want to go with DI container, my endorsement goes to Auryn .

And reason I am not using it myself is, because I am really arrogant, I want to make my own DI container.

PS

Instead of writing this:

 $post->setAuthor($user);

You should be writing something like this:

$post->setAuthorId($user->getId());

.. for two reasons:

  • You are not using an active record. Therefore you have no need for the Post instance to manage it's relations with other entities. That's what you have a service for.
  • If you passed the entire Account instance, you would end up extracting the ID anyway. So you would be violating Law of Demeter of no practical benefit.

My guess is that domainFactory and mapperFactory are instances of Abstract Factory pattern.

Since your BlogService already requires those 2 abstract factories why not have the third, ServiceFactory.

Responsibility of this object would be to create (preferably abstract) products, Services.

http://en.wikipedia.org/wiki/Abstract_factory_pattern

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM