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:

Comparer avec npm
( JavaScript
):

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
:

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):

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:

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:

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):

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
/ ....