Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvement handleCommand #18

Open
jaapio opened this issue Jan 25, 2017 · 3 comments
Open

Improvement handleCommand #18

jaapio opened this issue Jan 25, 2017 · 3 comments

Comments

@jaapio
Copy link

jaapio commented Jan 25, 2017

At the moment all resources must extend AbstractResource and should use the contructor from that class. I think we can improve that.

In the hydrator we know what type of Resource should be create Async or sync. So we can help the user to call the wait method when in sync mode. I would suggest that we inject a commandHandler object in to the class on a property that's annotated with the @handler annotation. We will have 2 types of handlers, sync and async. In pseudo code they look like this:

final class AsyncHandler implements HandlerInterface
{
    /**
     * @var LoopInterface
     */
    private $loop;
    /**
     * @var CommandBusInterface
     */
    private $commandBus;
    
   public function __construct(CommandBusInterface $commandBus)
    {
        $this->commandBus = $commandBus;
    }
    /**
     * @param $command
     * @return CancellablePromiseInterface
     */
    protected function handleCommand($command): CancellablePromiseInterface
    {
        return $this->commandBus->handle($command);
    }
}
final class SyncHandler implements HandlerInterface
{
    /**
     * @var LoopInterface
     */
    private $loop;
    /**
     * @var CommandBusInterface
     */
    private $commandBus;
    
   public function __construct(AsyncHandler $handler)
    {

    }
    /**
     * @param $command
     * @return mixed
     */
    protected function handleCommand($command)
    {
        return wait($this->handler->handleCommand($command))
    }
}

Resource example

Class MyResource implements ResourceInterface
{
    /** @handler */
    private $handler;

   public function respository() {
        return $handler->handlerCommand(new Repository());
   }
}

I think this might even remove the need of having 2 different classes for async and sync resources. However when you want to define the return types of the methods like Repository you still need those.

Another benifit is that you are giving the control of the constructor back to the user. So he could use it in instanciate new objects that can be persisted for example.

@WyriHaximus
Copy link
Member

Like the idea. But removing the need for two classes it going to be an issue mainly because of the return types.

Another benifit is that you are giving the control of the constructor back to the user. So he could use it in instanciate new objects that can be persisted for example.

What would you use constructor control for? The constructor is called somewhere hidden inside the hydrator, so only way we can hand access to it is through the container. Take a look at https://github.com/Ocramius/GeneratedHydrator and at the classes generated to get an idea how it works internally. Because pretty much any object we assign to a resource is suboptimal (had an galore of issues with that). Also for persisting resources extracting and rehydrating should do the trick.

@jaapio
Copy link
Author

jaapio commented Jan 30, 2017

I would like to do something like this:

$invoice = new Invoice($contact, [$line1, $line2]);
$client->sendInvoice($invoice);

Invoice will be an immutable object without setters, But I want to be able to create it. With the current implementation this is impossible. Or I should pass the dependencies of the resource class.

We could move to doctrine/instantiator to be able to create new instances in the hydrator. And assign the suggested handler via the hydrator to the new create object.

@WyriHaximus
Copy link
Member

WyriHaximus commented Jan 30, 2017

What about adding a factory method that calls the constructor with two exception throwing dummies. And after that the factory method can set the values on the object:

$invoice = Invoice::create($contact, [$line1, $line2]);
$client->sendInvoice($invoice);

The reason I went with the current package to hydrate is performance: https://github.com/Ocramius/GeneratedHydrator#performance-comparison
I don't have any experience with doctrine/instantiator, but we could try it out 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants