Something about namespace

    I program on PHP. And a little bit on JS. Once I programmed on Java, even earlier - on LotusScript. Tasted pythonand dart. Basic, Fortran, Pascal, Prolog, VisualBasic, С++/ С, perl- on all this, I also figured 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 on С/ С++for different OS, and therefore I program on PHPfor 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, by namespace, I mean the namespace from the point of view PHP, not the namespace from the point of view of python'a:


    I first encountered the namespace when studying Javawhen 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 is rather easy to navigate:


    Compare with npm( JavaScript):


    In the Javadevelopers, the “ reverse-domain ” name of the packages is widely accepted (as a result, the modules), but c JSis not. As a result, Javayou can independently create a large number of non-conflicting packages (modules) without explicitly coordinating their names by independent groups of developers, and JSyou need to explicitly use the npm registry for this . Yes, the global registry of domains isJava implicitly involved in conflict resolution , but the same naming rule can be used by any community, and not only by coders.Java

    The PHPdependency manager composercreates a two-level directory structure ./company/module::


    which gives some advantage in navigating dependencies over single-level placement.

    Here are the statistics for the central package repositories for Java/ JS/ PHP: - 3,358 578 indexed jars - 872 459 packages - 207 560 packages (1 472 944 versions)

    Likely to maven'take into account the statistics and all versions of modules, while in npmand composercounted exactly the modules themselves.

    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 of version Java( package) and PHP( namespace) primarily allows you to uniquely address a specific element of the code in the aggregate community. And this is the property of the namespace (logical grouping) and makes it possible to create more complex software systems by less connected groups of developers.

    Addressing software items

    The PHPclass \Doctrine\DBAL\Schema\Columnis 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):


    The same PhpStorm is lost if you apply a similar technique for the JS-code (where there are no namespaces). Let's try to form the address for the link to the JSfunction in a similar way query:


    At the exit, we have module.querythat is not informative enough.

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


    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 references to various elements of the project code to remain relevant much longer than references to a line in a file.

    Detect conflicting code versions

    Today's complex applications can not be developed without the dependencies management ( 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 JSsuch does not arise because of the lack namespace'ov. I myself came across a situation when, when installing in Magentoadditional modules, the number of different versions of the library loaded by them was jQueryover 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 PHPallows you to easily detect such conflicts at the IDE level (for example, I made a second file with a duplicate of the class inside):


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

    Autoload code

    Function spl_autoload_registerin PHPallows a developer to not bother those exactly where the files from the source of his classes. 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 the Zend1abstract adapter to work with the database was determined as follows:


    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 Zend2where namespaces are already used, a similar class definition looks like this:

    classAdapterimplements ... {}

    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 file ./vendor/composer/autoload_namespaces.phpthat the bootloader creates composerin PHPorder to work ./vendor/autoload.php:

    $vendorDir = dirname(dirname(__FILE__));
    $baseDir = dirname($vendorDir);
        '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 source codes in different libraries can be located in different paths (different intramodular structures), and composerwhen forming a project, it creates a map of the logical class hierarchy imposing on the file system. And namespaces play a significant role in this overlay.

    To assess this role, it is enough to try to split a npmmodule 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 ES6and the absence of a namespace in the sense of a logical grouping of the code will probably lead to the appearance of ES6names in large -projects, similar to the names in Zend1( Module_Path_To_Class).


    The identifier of objects in IoC containers is a string (at least in PHP). In a simple example it is quite possible to use the type identifiers dbAdapter, serviceA, serviceBetc. But the larger the project, the more difficult it is to find out where the object is created with an identifier, for example, searchFilterListand 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.


    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 on Java/ PHP/ C++... cannot be achieved by developers with similar qualifications on JavaScript/ Python/ C/ ....

    Also popular now: