There are only two hard things in Computer Science: cache invalidation and naming things.
— Phil Karlton
Magento Dependency Injection implementation comes with the very powerful concept of Virtual Types. However, with great power comes great responsibility. Virtual types provide a declarative way to create multiple instances of a single PHP class, each with a different constructor argument. This allows developers to implement new functionality or change Magento behavior with less code and so with fewer bugs. As with any other subject in programming, a good naming of virtual types allows writing code that is easy to understand and support. In this post we describe the future naming scheme that Magento will be using from now on for naming of virtual types. Feedback is welcome!
Magento merges all di.xml files for an area so all virtual types are available from all modules. Therefore, a virtual type declared in one module may be used or even reconfigured in another. That's great! But what if two modules create virtual types with the same name? A name collision occurs and a single virtual type will be created instead of two separate instances. Worse yet, such an inapplicable Dependency Injection configuration may not trigger any error or exception and lead to hard-to-detect bugs.
To avoid naming conflicts, all virtual type names should:
be in PHP FQCN (Full Qualified Class Name) format without leading backslash (e.g. Magento\Catalog\Pricing\Price\Pool)
use Vendor\Module\ as a root namespace (equal to the PHP root namespace of the module where the virtual type is introduced)
To name a virtual type, just answer the question "If there is no suitable ready-to-use implementation, what PHP class would I have to create and how would it be named?"
Magento already uses the above naming convention in some places but there are a lot of virtual type names that use camel case. Does that mean that all of them will be renamed in upcoming Magento release? No! Existing virtual type names will not be changed for backward compatibility reasons. Only new virtual type names from now on will follow this rule.
We chose FQCN-like virtual type names because we tried to satisfy additional criteria that are significant to us:
virtual type names should be consistent with other names in Magento
naming should help provide backward compatibility
naming should not expose implementation details (when some object injects a dependency it should not matter whether it is a virtual type or real PHP class)
naming should help a developer discover code (where to search for injected dependency: in di.xml or in PHP code?)
avoid conflicts of virtual types and PHP classes
naming should allow introduction of nested scopes
FQCN-like names have two flaws. First, naming conflicts between virtual types and PHP classes are possible. This issue is not critical because virtual types and PHP classes share the same Vendor\Module\ namespace, so it is easy for the module developer to control names.
Second, FQCN-like naming scheme does not readily allow differentiation of virtual types from PHP classes. This is a subject of serious concern. If you are using the PhpStorm Magento 2 plugin, it allows developers to navigate to virtual type declarations or to PHP class source code. Nevertheless, Magento does not want to impose any IDE or other tools. Developers should work with an environment that is comfortable for them.
An alternative naming approach that we considered was Vendor_Module::virtualTypeName. This naming scheme explicitly distinguishes between PHP classes and virtual types. But it also has an important drawback as it creates difficulties with respect to supporting backward compatibility.
In conclusion, this post has described the planned new naming convention for virtual types. This approach avoids virtual type name conflicts and allows Magento code to evolve without breaking backward compatibility. We always welcome community feedback, so please leave any comments below either in support of the proposal, or sharing your opinions on a better approach.