1

I'm trying to figure out the best way to structure a custom module that uses the Queue API in D8. I'm new to D8 and a bit rusty with OOP so forgive me if I'm breaking some recommended design pattern here...

I created a single custom module where multiple different queues need to process items differently, but each queue has common functionality that they may need to use between each other. So my question is, should I create an abstract base class that extends QueueWorkerBase, make processItem abstract, and then add common functionality to the base class?

Something like this:

In src/Plugin/QueueWorker/ProcessQueueBase.php

abstract class ProcessQueueBase extends QueueWorkerBase {

  /**
   * @inheritDoc
   */
  abstract public function processItem($data);

  protected function doSomethingCommon(){
    // Some common logic
  }
}

In src/Plugin/QueueWorker/ProcessQueueOne.php

class ProcessQueueOne extends ProcessQueueBase {

  /**
   * @inheritDoc
   */
  public function processItem($data){
    // Do stuff now

    parent::doSomethingCommon();
  }    
}

In src/Plugin/QueueWorker/ProcessQueueTwo.php

class ProcessQueueTwo extends ProcessQueueBase {

  /**
   * @inheritDoc
   */
  public function processItem($data){
    // Do stuff now

    parent::doSomethingCommon();
  }    
}

OR should I create separate classes that all extend QueueWorkerBase and then just create services for the common functionality.

Something like this:

In DoSomethingService.php:

class DoSomethingService {

  public function doSomethingCommon(){
    // Do something
  }

}

In src/Plugin/QueueWorker/ProcessQueueOne.php

class ProcessQueueOne extends QueueWorkerBase {

  /**
   * @inheritDoc
   */
  public function processItem($data){
    // Do stuff

    $do_something = \Drupal::service('mymodule.doSomething');
    $do_something->doSomethingCommon();
  }    
}

In src/Plugin/QueueWorker/ProcessQueueTwo.php

class ProcessQueueTwo extends QueueWorkerBase {

  /**
   * @inheritDoc
   */
  public function processItem($data){
    // Do stuff

    $do_something = \Drupal::service('mymodule.doSomething');
    $do_something ->doSomethingCommon();
  }    
}
  • This is a PHP question basically. But if you have classes that share a majority of the same functionality, you would fill in the methods in the abstract class and extend the class, then override (or add) methods you need to alter functionality for. – Kevin Mar 14 at 19:52
  • 3
    If you put the common method in a service then it runs in its own class instance which persists during the request. So this depends on whether the common method uses any states and whether they should persist in each plugin instance or in the shared service. – 4k4 Mar 14 at 20:46
  • 1
    I'd prefer the latter, but with injecting dependencies. Although Traits are another possibility. If the it's common operations that don't depend on state then a trait could be pretty useful. – mradcliffe Mar 15 at 2:03
  • @mradcliffe My plan was to inject the dependencies, but for the sake of simplicity I chose not to write the full code for it. – Keven Mar 15 at 2:38
0

I would suggest an abstract base class, but instead of creating another function ::doSomethingCommon, partially implement ProcessQueueBase::processItem and call parent::processItem from the subclasses.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.