Algo sobre o espaço para nome

Estou programando em PHP . E um pouco sobre JS . Uma vez eu programei em Java , ainda mais cedo - no LotusScript . Tentei um gosto de python e dart . Basic , Fortran , Pascal , Prolog , VisualBasic , ++ / , perl - em tudo isso, também retratei algo executável. Linguagens de programação me interessam em termos de criação de aplicativos de computador. Aplicações web. Aplicações web sofisticadas. Aqueles que escrevem pessoas que não estão familiarizadas. Mais precisamente, eles não estão familiarizados pessoalmente - eles se conhecem por assinaturas em confirmações no repositório comum e por apelidos em rastreadores de bugs. Não sou muito inteligente para programar em / ++ para vários sistemas operacionais e, portanto, estou programando em PHP para Magento .


Então, voltando ao tópico do artigo, posso dizer que o espaço para nome é um dos pilares muito importantes nos quais a escrita de aplicativos Web complexos se baseia em um grupo de desenvolvedores não familiarizados.


Neste texto, por namespace, quero dizer namespace do ponto de vista do PHP , não namespace do ponto de vista do python :


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

Pela primeira vez, deparei-me com um espaço para nome ao aprender Java , quando tentei entender o segredo da diretiva " pacote ":


 package com.sun.source.util; 

O objetivo desta diretiva não era claro e o que exatamente deveria ser indicado nela, se alguma linha pudesse ser indicada. A recomendação dos autores do idioma para usar como parte do nome do pacote registrado no seu domínio (na sua empresa) parecia um tanto extravagante. Agora todo mundo, todo mundo, qualquer pessoa tem seu próprio domínio, e essa recomendação não é muito embaraçosa, e há 15 a 20 anos eu pensei muito sobre qual domínio usar como o nome do meu primeiro pacote e o que poderia afetar no futuro. Somente mais tarde, quando maven aplicativos usando o maven , apreciei o insight desta recomendação.


Gerentes de dependência


Os gerentes de dependência me ajudaram a entender o significado do espaço para nome. Se o seu código usa código de terceiros, que depende de outros pacotes que dependem de terceiros, é muito difícil manter a ordem nesse despejo. No entanto, precisamente devido à regra do domínio posterior para nomear pacotes em um monte de JARs empilhados em um diretório (por exemplo, em WEB-INF/lib ), é fácil navegar:


imagem


Compare com npm ( JavaScript ):


imagem


Em Java desenvolvedores adotaram o nome " back-domain " dos pacotes (como resultado de módulos) bastante amplamente, enquanto em JS não o fizeram. Como resultado, em Java você pode criar independentemente um grande número de pacotes (módulos) sem conflito, sem concordar explicitamente em seus nomes como grupos de desenvolvimento independentes e, em JS você deve usar explicitamente o registro npm . Sim, em Java , o registro de domínio global está implicitamente envolvido na resolução de conflitos, mas qualquer comunidade, não apenas os codificadores Java , pode usar a mesma regra de nomenclatura.


No PHP , o gerenciador de dependências do composer cria uma estrutura de diretórios em dois níveis: ./company/module :


imagem


o que oferece alguma vantagem na navegação de dependência em relação à alocação de nível único.


Aqui estão as estatísticas para os repositórios de pacotes centrais para Java / JS / PHP :


https://mvnrepository.com/repos/central - 3 358 578 frascos indexados
https://www.npmjs.com/ - 872 459 pacotes
https://packagist.org/statistics - 207 560 pacotes (1.472.944 versões)


Provavelmente para o maven todas as versões dos módulos são levadas em consideração nas estatísticas, enquanto os próprios módulos são levados em consideração no npm e no composer .


Para que serve o namespace?


A resposta principal é evitar conflitos entre vários elementos de código (constantes, funções, classes, ...) que têm o mesmo nome, mas estão em módulos diferentes. Os namespaces do Python lidam com isso com êxito. Mas eu ainda usaria o "namespace" aqui entre aspas, porque em essência, está mais próximo do escopo .


O espaço para nome de acordo com as versões Java ( package ) e PHP ( namespace ) permite, em primeiro lugar, endereçar sem ambiguidade um elemento de código específico na comunidade agregada. E essa é uma propriedade do espaço para nome (agrupamento lógico) que possibilita a criação de sistemas de software mais complexos por grupos de desenvolvedores menos conectados.


Endereçando elementos de software


No PHP a classe \Doctrine\DBAL\Schema\Column é endereçada exclusivamente, independentemente de como o código-fonte esteja conectado ao projeto. O IDE pode facilmente formar esse endereço. No PhpStorm, isso é feito assim (clique com o botão direito do mouse em um elemento de código):


imagem


O mesmo PhpStorm será perdido se você aplicar uma técnica semelhante ao código JS (onde não há espaço para nome). Vamos tentar formar o endereço do link para a função de query JS desta maneira:


imagem


A saída é module.query , que não é informativa o suficiente.


Para abordar a função de query na documentação (correspondência, rastreador de erros, etc.), você deve consultar uma linha de código específica no arquivo:


imagem


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


Obviamente, ao alterar o número de linhas em um arquivo ou mover / renomear um arquivo, teremos na documentação um endereço desatualizado do elemento do programa que nos interessa.


Portanto, o uso do espaço para nome permite que os links para vários elementos do código do projeto permaneçam relevantes por muito mais tempo do que os links para uma linha em um arquivo.


Detectando versões conflitantes do código


Aplicativos complexos modernos não podem ser desenvolvidos sem gerenciadores de dependência ( maven , composer , npm , ...). Ao mesmo tempo, nossas dependências extraem suas dependências, que são próprias, etc., o que, como resultado, pode levar a conflitos de versão para o mesmo pacote extraído de diferentes dependências ( jar hell ).


No JS isso não ocorre devido à falta de namespace'ov. Eu mesmo me deparei com uma situação em que, ao instalar módulos adicionais no Magento número de versões diferentes da biblioteca jQuery carregada por eles excedeu 5-6. Por um lado, esse comportamento confere maior liberdade aos próprios desenvolvedores, por outro lado - mais liberdade exige mais qualificações. Bem, a busca por erros em um conjunto de dependências com várias versões - as qualificações são uma ordem ou duas mais altas que as qualificações para criar esses mesmos erros.


O uso do namespace no PHP facilita a detecção de tais conflitos no nível do IDE (por exemplo, criei um segundo arquivo com uma duplicata da classe dentro):


imagem


Portanto, a tarefa de detectar elementos de código duplicados em um projeto se torna bastante fácil de realizar.


Inicialização de código


A função spl_autoload_register no PHP permite que o desenvolvedor não se preocupe exatamente onde os arquivos com as fontes de suas classes estão localizados. Em qualquer projeto, você pode substituir essa função e implementar seu próprio algoritmo de carregamento de script pelo nome da classe. Sem o uso de um espaço para nome, era necessário escrever nomes bastante encaracolados para as classes para garantir sua exclusividade em um projeto complexo (especialmente levando em conta as bibliotecas de terceiros). No Zend1 adaptador abstrato para trabalhar com o banco de dados foi definido da seguinte maneira:


 abstract class Zend_Db_Adapter_Abstract {} 

Para garantir a exclusividade, era necessário, em essência, adicionar espaço para nome ao nome da classe. É claro que, ao usar esses nomes de classe no código, você precisa aumentar os olhos ao longo das linhas.


No Zend2 , onde os namespaces já são usados, uma definição de classe semelhante se parece com isso:


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

O código eventualmente se torna mais legível, mas o resultado mais significativo do uso do espaço para nome é a possibilidade de unificar a funcionalidade do carregador de classes com a ligação da hierarquia lógica das classes à estrutura do arquivo. Aqui está um trecho do arquivo ./vendor/composer/autoload_namespaces.php que o composer cria no PHP para o carregador ./vendor/autoload.php funcionar:


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

Pode-se observar que os códigos-fonte em diferentes bibliotecas podem ser localizados de diferentes maneiras (diferentes estruturas intra-módulo), e o composer ao formar o projeto, cria um mapa de sobreposição da hierarquia lógica de classes no sistema de arquivos. E os namespaces desempenham um papel significativo nessa sobreposição.


Para avaliar essa função, basta tentar dividir algum módulo npm em vários módulos menores e reconstruir seu projeto para usar dois novos módulos em vez de um grande. A propósito, a presença de classes no ES6 e a falta de um espaço para nome no sentido de agrupamento lógico de código provavelmente levará ao aparecimento de nomes semelhantes aos do Zend1 ( Module_Path_To_Class ) em grandes projetos do ES6 .


IoC


O identificador de objetos em contêineres IoC é uma string (pelo menos em PHP ). Em exemplos simples, identificadores como dbAdapter , serviceA , serviceB etc. são perfeitamente aceitáveis. Porém, quanto maior o projeto, mais difícil é searchFilterList onde o objeto com o identificador é criado, por exemplo, searchFilterList e onde ele é usado. A saída lógica é usar nomes de classe como identificadores de objetos. Nesse caso, a lógica de criação de objetos pelo contêiner se torna previsível, e o código-fonte e os locais de uso são determinados elementarmente pelo IDE. O espaço para nome permite organizar todas as classes de projeto em uma estrutura lógica e usar os caminhos apropriados ao criar objetos com um contêiner.


Sumário


À luz do exposto, acredito que as linguagens de programação que usam nativamente os namespaces para estruturar o código-fonte usando o agrupamento lógico de seus elementos permitem a criação de aplicativos mais complexos com menos custo do que as linguagens que não possuem um agrupamento lógico. Portanto, a complexidade máxima dos aplicativos que podem ser criados em Java / PHP / C++ / ... não pode ser alcançada por desenvolvedores com as mesmas qualificações em JavaScript / Python / C / ....

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


All Articles