Magento – How to load model without $objectManager and without inject dependencies

magento2modelobject-manager

I am reading that I should never use $objectManager directly to load model

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$subscriber = $objectManager->get('Magento\Newsletter\Model\Subscriber')->loadByEmail($email);

But I should inject an instance of model in class constructor.

public function __construct(
    ...
    \Magento\Newsletter\Model\Subscriber $subscriber
) {
    ...
    $this->_subscriber= $subscriber;
}

But now let's take one simple example of observer class:

public function execute(\Magento\Framework\Event\Observer $observer)
{        
  if($this->_customerSession->isLoggedIn()){      
    //check if subscribed
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $subscriber = $objectManager->get('Magento\Newsletter\Model\Subscriber')->loadByEmail($email);        
    if($subscriber->getId()){
      //do some things
    }               
  } elseif() {

  } elseif() {

  }  
  ... 
}

Only if customer is logged in we need to call subscriber model, this is only in 10%. By injecting model in constructor, we call this model in 90% of cases when we don't need it. This is just simple example, real scenario is with 4 extra models used in observer. Also checking if logged in is just example.

I don't see any sense to load 4 extra models in 90% of cases just because it looks nice. Is there any other proper method to load models or is it fine to simply use objectmanager directly?

Another example would be helper class of 10 functions that is used in different controllers and actions but only some functions require extra models. I guess it wouldn't make sense to create 10 extra helper classes for each function.

So if using objectmanager directly is not recommended what would be proper way to not load models when they are not actually needed?

Best Answer

First of all, you should use factors for noninjectable classes.

Second, use Proxy for optional dependencies.

For example in your case

public function __construct(
    ...
    \Magento\Framework\App\ResourceConnection $connectionResource,
    \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory
) {

you need to configure DI as

<type name="..\Observer">
    <arguments>
        <argument name="connectionResource" xsi:type="object">
            \Magento\Framework\App\ResourceConnection\Proxy
        </argument>
    </arguments>
</type>