What's a hard dependency and what's a soft dependency?

There are three different dependency parsers (implementations of Magento\Setup\Module\Dependency\ParserInterface):

  • code: looks for classes used in code
  • config/xml: looks for dependencies in module declaration
  • composer/json: looks for dependencies in composer.json

The only one that makes a distinction between hard and soft dependencies is the composer parser (see: Magento\Setup\Module\Dependency\Parser\Composer\Json::extractDependencies())

A soft dependency is a package, listed in "suggest", a hard dependency a package in "require".

The default dependency type is hard, that means dependencies found by the other parsers are always hard (see Magento\Setup\Module\Dependency\Report\Dependency\Data\Dependency::__construct()).


A simple and clear explanation (from the Magento U fundamentals course):

Hard dependency

Implies that a module cannot function without the other modules on which it depends.

Example of hard dependencies include:

  • The module contains code that directly uses logic from another module (instances, class constants, static methods, public class properties, interfaces and traits).
  • The module contains strings that include class names, methods names, class constants, class properties, interfaces, and traits from another module.
  • The module de-serializes an object declared in another module.
  • The module uses or modifies the database tables used by another module.

Magento_AdminNotification has a hard dependency on Magento_Store

Soft dependency

Implies that a module can function without the other modules on which it depends.

Example of soft dependencies include:

  • The module directly checks another module's availability.
  • The module extends another module's configuration.
  • The module extends another module's layout.

Magento_AdvancedPricingImportExport has a soft dependency on Magento_CatalogImportExport with code like this:

if (!$model instanceof \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType) {
    throw new \Magento\Framework\Exception\LocalizedException(
        __(
            'Entity type model must be an instance of'
            . ' \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType'
        )
    );
}

If a module uses code from another module, it should declare the dependency explicitly.

EDIT: just noticed that this is also clearly explained in the official doc: https://devdocs.magento.com/guides/v2.3/architecture/archi_perspectives/components/modules/mod_depend.html