📜 ⬆️ ⬇️

Something about namespace

I am programming in PHP . And a little bit on JS . I once programmed in Java , even earlier - in LotusScript . I tasted python and dart . Basic , Fortran , Pascal , Prolog , VisualBasic , ++ / , perl - for all this I also depicted something executable. Programming languages ​​interest me from the point of view of creating computer applications. Web applications. Complicated web applications. Those who write strangers to each other people. More precisely, personally unfamiliar - they know each other by signatures in commits to a common repository and by nicknames in bug trackers. I am not too smart to program in / ++ for different operating systems, and therefore I program in PHP for Magento .


So, returning to the topic of the article, I can say that the namespace is one of the very important pillars on which the writing of complex web applications is based on a group of poorly-known developers.


In this text, under the namespace, I mean the namespace from the point of view of PHP , and not the namespace from the point of view of python 'a:


 <?php namespace Vendor\Project\Module\Component\Unit; 

I first encountered the namespace when learning Java , when I tried to comprehend the secret of the " package " directive:


 package com.sun.source.util; 

It was unclear the purpose of this directive and what exactly to specify in it, if you could specify any string. The recommendation from the authors of the language to use as part of the name of the package registered to you (to your company) domain looked somewhat extravagant. Every now and everyone has their own domain and this recommendation is not very embarrassing, but 15-20 years ago I really thought about what domain to take as the name for my first package and what this might affect in the future. Only later, when I compiled applications using maven 'a, did I appreciate the insight of this recommendation.


Dependency managers


The dependency managers helped me understand the meaning of the namespace. If your code uses third-party code, which depends on other packages that depend on third parties, it is very difficult to maintain order in such a dump. However, precisely because of the reverse-domain rule for naming packages in a heap of JARs dumped in one directory (for example, in WEB-INF/lib ), it’s easy to navigate:


image


Compare with npm ( JavaScript ):


image


In Java developers have widely adopted the “ reverse domain ” name of packages (as a result, modules), but not in JS . As a result, in Java you can independently create a large number of conflict-free packages (modules) without explicitly coordinating their names by independent groups of developers, and in JS , you need to explicitly use the npm registry . Yes, in Java , the global registry of domains is implicitly involved in conflict resolution, but the same naming rule can be used by any community, and not just Java coders.


In PHP , the dependency manager composer creates a two-level directory structure: ./company/module :


image


which gives some advantage in the navigation of dependencies before single-level placement.


Here are the statistics on the central package repositories for Java / JS / PHP :


https://mvnrepository.com/repos/central - 3,358,578 indexed jars
https://www.npmjs.com/ - 872 459 packages
https://packagist.org/statistics - 207 560 packages (1 472 944 versions)


Most likely for maven ', all the versions of the modules are taken into account in the statistics, while the modules themselves are taken into account in npm and composer .


What is the namespace for?


The main answer is to prevent conflicts of different code elements (constants, functions, classes, ...) that have the same name but are in different modules. The namespaces of the python version successfully cope with this. But I would still take the "namespace" here in quotes, because in essence, it is closer to scope .


The namespace according to Java ( package ) and PHP ( namespace ) primarily allows you to uniquely address a specific element of the code in aggregate generality. And this is the property of the namespace (logical grouping) and makes it possible to create more complex software systems with less connected groups of developers.


Addressing software items


In PHP the \Doctrine\DBAL\Schema\Column class is addressed uniquely, no matter how the source code is connected to the project. IDE can easily generate this address. In PhpStorm, this is done like this (by right-clicking on a code element):


image


The same PhpStorm is lost if you apply a similar trick to the JS code (where there are no namespaces). Let's try to create the address for the reference to the JS query function in a similar way:


image


At the output, we have a module.query , which is not informative enough.


To address the query function in the documentation (correspondence, bug tracker, etc.) you have to refer to a specific line of code in the file:


image


Result: ./node_modules/express/lib/middleware/query.js:25


Of course, if we change the number of lines in a file or move / rename a file, we will have in the documentation the outdated address of the program element of interest to us.


Thus, the use of the namespace allows links to various elements of the project code to remain relevant much longer than links to a line in a file.


Detect conflicting code versions


Modern complex applications cannot be developed without dependency managers ( maven , composer , npm , ...). At the same time, our dependencies pull their dependencies, which pull theirs, etc., which as a result can lead to conflicts over versions for the same package, pulled through different dependencies ( jar hell ).


In JS this does not occur due to the lack of namespaces. I myself came across a situation when, when installing additional modules in Magento number of different versions of the jQuery library loaded by them exceeded 5-6. On the one hand, such behavior gives more freedom to the developers themselves, on the other - more freedom makes greater demands on qualifications. Well, the search for errors in such dependencies of different versions is a qualification two orders of magnitude higher than the qualifications for creating these very errors.


Using namespaces in PHP makes it easy to detect such conflicts at the IDE level (for example, I made a second file with a duplicate of the class inside):


image


Thus, the task of detecting duplicate code elements in a project becomes fairly easy to accomplish.


Autoload code


The spl_autoload_register function in PHP allows the developer not to bother with exactly where the files with the source codes of his classes are located. In any project, you can override this function and implement your own script loading algorithm by class name. Without the use of the namespace, it was necessary to write out quite curly names for classes to ensure their uniqueness within a complex project (especially with regard to third-party libraries). In Zend1 abstract adapter for working with the database was defined as follows:


 abstract class Zend_Db_Adapter_Abstract {} 

To ensure uniqueness, in essence, it was necessary to add a namespace to the class name. Of course, when using such class names in the code, you have to widen your eyes wide by the lines.


In Zend2 , where namespaces are already used, a similar class definition looks like this:


 namespace Zend\Db\Adapter; class Adapter implements ... {} 

The code eventually becomes more readable, but the most significant result of using namespace is the ability to unify the class loader functionality with the logical hierarchy of classes attached to the file structure. Here is an excerpt from the ./vendor/composer/autoload_namespaces.php file, which creates a composer in PHP for the bootloader ./vendor/autoload.php to work:


 <?php $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( 'Zend_' => array($vendorDir . '/magento/zendframework1/library'), 'Yandex' => array($vendorDir . '/allure-framework/allure-codeception/src', $vendorDir . '/allure-framework/allure-php-api/src', $vendorDir . '/allure-framework/allure-php-api/test'), 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'), 'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src'), 'PhpCollection' => array($vendorDir . '/phpcollection/phpcollection/src'), 'PHPMD\\' => array($vendorDir . '/phpmd/phpmd/src/main/php'), 'OAuth\\Unit' => array($vendorDir . '/lusitanian/oauth/tests'), 'OAuth' => array($vendorDir . '/lusitanian/oauth/src'), ... 

It can be seen that the source codes in different libraries can be located in different paths (different intramodular structures), and the composer creates a map of the logical class hierarchy over the file system when the project is created. And namespaces play a significant role in this overlay.


To assess this role, it is enough to try to break up some npm module into several smaller modules and rebuild your project to use two new modules instead of one large one. By the way, the presence of classes in ES6 and the absence of a namespace in the sense of a logical grouping of the code will probably lead to the appearance of names similar to those in Zend1 in large ES6 Zend1 ( Module_Path_To_Class ).


IoC


The object identifier in IoC containers is a string (at least in PHP ). In simple examples, it is quite possible to use identifiers like dbAdapter , serviceA , serviceB , etc. But the larger the project, the more difficult it is to searchFilterList where the object is created with an identifier, for example, searchFilterList and where it is used. The logical way out is to use class name objects as identifiers. In this case, the logic of creating objects by the container becomes predictable, and the source code and places of use are determined by the IDE. The namespace allows you to organize all project classes in one logical structure and use the appropriate paths when creating objects with a container.


Summary


In the light of the above, I believe that programming languages ​​that natively use namespaces to structure the source code using a logical grouping of its elements make it possible to build more complex applications with less cost than languages ​​that do not have a logical grouping. Accordingly, the maximum complexity of applications that can be created in Java / PHP / C++ / ... cannot be achieved by developers with similar qualifications in JavaScript / Python / C / ....


')

Source: https://habr.com/ru/post/434968/


All Articles