Quelque chose à propos de l'espace de noms

Je programme en PHP . Et un peu sur JS . Une fois que j'ai programmé en Java , même plus tôt - en LotusScript . J'ai essayé un goût de python et de dart . Basic , Fortran , Pascal , Prolog , VisualBasic , ++ / , perl - sur tout cela, j'ai également décrit quelque chose d'exécutable. Les langages de programmation m'intéressent en termes de création d'applications informatiques. Applications Web. Applications Web sophistiquées. Ceux qui écrivent des gens qui ne se connaissent pas. Plus précisément, ils ne sont pas personnellement familiers - ils se connaissent par les signatures dans les commits dans le référentiel commun et par les surnoms dans les trackers de bogues. Je ne suis pas trop intelligent pour programmer en / ++ pour différents OS, et donc je programme en PHP pour Magento .


Donc, pour revenir au sujet de l'article, je peux dire que l'espace de noms est l'un des piliers très importants sur lesquels l'écriture d'applications Web complexes repose sur un groupe de développeurs qui ne se connaissent pas.


Dans ce texte, par espace de noms, je veux dire espace de noms du point de vue de PHP , pas espace de noms du point de vue de python :


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

Pour la première fois, je suis tombé sur un espace de noms lors de l'apprentissage de Java , lorsque j'ai essayé de comprendre le secret de la directive " package ":


 package com.sun.source.util; 

Le but de cette directive n'était pas clair, et ce qui devrait être indiqué exactement si une ligne pouvait être indiquée. La recommandation des auteurs de la langue à utiliser dans le nom du package enregistré sur votre domaine (dans votre entreprise) semblait quelque peu extravagante. Maintenant, tout le monde, tout le monde, tout le monde a son propre domaine, et cette recommandation n'est pas très gênante, et il y a 15-20 ans, je pensais beaucoup au domaine à utiliser comme nom pour mon premier package et à ce qu'il pourrait affecter à l'avenir. Ce n'est que plus tard, lorsque j'ai créé des applications à l'aide de maven , que j'ai apprécié la perspicacité de cette recommandation.


Gestionnaires de dépendance


Les gestionnaires de dépendances m'ont aidé à comprendre la signification de l'espace de noms. Si votre code utilise du code tiers, qui dépend d'autres packages qui dépendent de tiers, il est très difficile de maintenir l'ordre dans un tel vidage. Néanmoins, précisément en raison de la règle de domaine arrière pour nommer les packages dans un tas de fichiers JAR empilés dans un répertoire (par exemple, dans WEB-INF/lib ), il est assez facile de naviguer:


image


Comparer avec npm ( JavaScript ):


image


En Java développeurs ont adopté assez largement le nom de « domaine arrière » des packages (en raison des modules), alors que dans JS ne l’ont pas fait. Par conséquent, en Java vous pouvez créer indépendamment un grand nombre de packages (modules) sans conflit sans convenir explicitement de leurs noms en tant que groupes de développement indépendants, et en JS vous devez utiliser explicitement le registre npm . Oui, en Java , le registre de domaine global est implicitement impliqué dans la résolution des conflits, mais toute communauté, pas seulement Java encodeurs Java , peut utiliser la même règle de dénomination.


En PHP , le gestionnaire de dépendances du composer crée une structure de répertoires à deux niveaux: ./company/module :


image


ce qui donne un certain avantage dans la navigation de dépendance par rapport à l'allocation à un niveau.


Voici les statistiques des référentiels de packages centraux pour Java / JS / PHP :


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


Très probablement pour maven toutes les versions des modules sont prises en compte dans les statistiques, tandis que les modules eux-mêmes sont pris en compte dans npm et composer .


À quoi sert l'espace de noms?


La réponse principale est d'éviter les conflits entre différents éléments de code (constantes, fonctions, classes, ...) qui portent le même nom mais qui se trouvent dans des modules différents. Les espaces de noms Python y parviennent avec succès. Mais je prendrais toujours "l'espace de noms" ici entre guillemets, car en substance, il est plus proche de la portée .


L'espace de noms selon les versions Java ( package ) et PHP ( namespace ) permet, tout d'abord, d'adresser sans ambiguïté un élément de code spécifique dans la communauté agrégée. Et c'est une propriété de l'espace de noms (regroupement logique) qui permet de créer des systèmes logiciels plus complexes par des groupes de développeurs moins connectés.


Adressage des éléments logiciels


En PHP la classe \Doctrine\DBAL\Schema\Column est adressée de manière unique, quelle que soit la façon dont le code source est connecté au projet. L'IDE peut facilement former cette adresse. Dans PhpStorm, cela se fait comme ceci (clic droit sur un élément de code):


image


Le même PhpStorm est perdu si vous appliquez une technique similaire au code JS (où il n'y a pas d'espace de noms). Essayons de former l'adresse du lien vers la fonction de query JS de cette manière:


image


La sortie est module.query , qui n'est pas assez informative.


Pour aborder la fonction de query dans la documentation (correspondance, traqueur de bogues, etc.), vous devez vous référer à une ligne de code spécifique dans le fichier:


image


Résultat: ./node_modules/express/lib/middleware/query.js:25


Bien sûr, lorsque vous changez le nombre de lignes dans un fichier ou déplacez / renommez un fichier, nous aurons dans la documentation une adresse obsolète de l'élément de programme qui nous intéresse.


Ainsi, l'utilisation de l'espace de noms permet aux liens vers divers éléments du code de projet de rester pertinents bien plus longtemps que les liens vers une ligne dans un fichier.


Détection des versions de code en conflit


Les applications complexes modernes ne peuvent pas être développées sans les gestionnaires de dépendances ( maven , composer , npm , ...). Dans le même temps, nos dépendances tirent leurs dépendances, qui tirent les leurs, etc., ce qui peut entraîner des conflits de version pour le même paquet tiré à travers différentes dépendances ( jar hell ).


Dans JS cela ne se produit pas en raison du manque de namespace'ov. J'ai moi-même rencontré une situation où, lors de l'installation de modules supplémentaires dans Magento nombre de versions différentes de la bibliothèque jQuery chargées par eux dépassait 5-6. D'une part, un tel comportement donne une plus grande liberté aux développeurs eux-mêmes, d'autre part - plus de liberté fait plus de demandes de qualifications. Eh bien, la recherche d'erreurs dans une telle nouilles de dépendances multi-versions - les qualifications sont un ordre ou deux plus élevées que les qualifications pour créer ces mêmes erreurs.


L'utilisation de namespace en PHP permet de détecter facilement de tels conflits au niveau de l'EDI (par exemple, j'ai créé un deuxième fichier avec un doublon de la classe à l'intérieur):


image


Ainsi, la tâche de détection des éléments de code en double dans un projet devient assez facile à accomplir.


Démarrage du code


La fonction spl_autoload_register en PHP permet au développeur de ne pas se soucier exactement de l'emplacement des fichiers avec les sources de ses classes. Dans tout projet, vous pouvez remplacer cette fonction et implémenter votre propre algorithme de chargement de script par nom de classe. Sans l'utilisation d'un espace de noms, il était nécessaire d'écrire des noms assez bouclés pour les classes afin d'assurer leur unicité au sein d'un projet complexe (notamment en tenant compte des bibliothèques tierces). Dans Zend1 adaptateur abstrait pour travailler avec la base de données a été défini comme suit:


 abstract class Zend_Db_Adapter_Abstract {} 

Pour garantir l'unicité, il était nécessaire, en substance, d'ajouter un espace de noms au nom de la classe. Bien sûr, lorsque vous utilisez de tels noms de classe dans le code, vous devez élargir vos yeux le long des lignes.


Dans Zend2 , où les espaces de noms sont déjà utilisés, une définition de classe similaire ressemble à ceci:


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

Le code devient finalement plus lisible, mais le résultat le plus significatif de l'utilisation de l'espace de noms est la possibilité d'unifier la fonctionnalité du chargeur de classe avec la liaison de la hiérarchie logique des classes à la structure du fichier. Voici un extrait du fichier ./vendor/composer/autoload_namespaces.php que le composer crée en PHP pour que le chargeur ./vendor/autoload.php fonctionne:


 <?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'), ... 

On peut voir que les sources dans différentes bibliothèques peuvent être localisées de différentes manières (différentes structures intra-module), et le composer lors de la formation du projet, crée une carte de superposition de la hiérarchie logique des classes sur le système de fichiers. Et les espaces de noms jouent un rôle important dans cette superposition.


Pour évaluer ce rôle, il suffit d'essayer de diviser un module npm en plusieurs modules plus petits et de reconstruire votre projet pour utiliser deux nouveaux modules au lieu d'un grand. Soit dit en passant, la présence de classes dans ES6 et l'absence d'espace de noms au sens d'un regroupement logique de code entraîneront probablement l'apparition de noms similaires à ceux de Zend1 ( Module_Path_To_Class ) dans les grands projets ES6 .


IoC


L'identifiant des objets dans les conteneurs IoC est une chaîne (au moins en PHP ). Dans des exemples simples, des identifiants tels que dbAdapter , serviceA , serviceB , etc. sont parfaitement acceptables. Mais plus le projet est grand, plus il est difficile de searchFilterList où l'objet avec l'identifiant est créé, par exemple, searchFilterList et où il est utilisé. La solution logique consiste à utiliser les noms de classe comme identificateurs pour les objets. Dans ce cas, la logique de création d'objets par le conteneur devient prévisible, et le code source et les lieux d'utilisation sont déterminés de manière élémentaire par l'IDE. L'espace de noms vous permet d'organiser toutes les classes de projet dans une structure logique et d'utiliser les chemins d'accès appropriés lors de la création d'objets avec un conteneur.


Résumé


À la lumière de ce qui précède, je crois que les langages de programmation qui utilisent nativement les espaces de noms pour structurer le code source en utilisant le regroupement logique de ses éléments permettent de créer des applications plus complexes à moindre coût que les langages qui n'ont pas de regroupement logique. En conséquence, la complexité maximale des applications pouvant être créées en Java / PHP / C++ / ... ne peut pas être atteinte par des développeurs ayant les mêmes qualifications en JavaScript / Python / C / ....

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


All Articles