Por que pacotes e módulos são conceitos separados no Java 9?

21

O Java 9 terá módulos além dos pacotes. Normalmente, os idiomas têm um ou outro. E a maioria dos programadores percebe dois termos como sinônimos. Os módulos são criados sobre os pacotes, tratando-os como primitivos. Padrão composto sugere tratar primitivos e compostos uniformemente. Caso contrário, coisas ruins vão acontecer. Por exemplo, veja o projeto Valhalla, onde eles tentam adaptar o supertipo comum para tipos primitivos (valor) e de referência.

Os módulos e pacotes representam noções semanticamente separadas? Significando que é sensato ter ambos para qualquer idioma (separação de preocupações). Ou o Java precisa ter os dois como um tributo à compatibilidade com versões anteriores?

Por que introduzir um novo conceito em vez de aumentar o existente?


JSR 376 : "Sistema de módulo de plataforma Java" implementado no projeto Jigsaw .

De acordo com SOTMS

Um módulo é uma coleção nomeada e auto-descritiva de código e dados. Seu código é organizado como um conjunto de pacotes contendo tipos, como classes e interfaces Java; seus dados incluem recursos e outros tipos de informações estáticas.

O JLS evita cuidadosamente definir o que é um pacote . Da Wikipedia :

Um pacote Java é uma técnica para organizar classes Java em espaços de nomes semelhantes aos módulos do Modula, fornecendo programação modular em Java.

Eu sei que citar a Wikipedia é uma prática ruim, mas reflete um entendimento comum. Desde a entrada na programação modular:

O termo pacote às vezes é usado em vez de módulo (como em Dart, Go ou Java). Em outras implementações, esse é um conceito distinto; no Python, um pacote é uma coleção de módulos, enquanto no próximo Java 9 é planejada a introdução do novo conceito de módulo (uma coleção de pacotes com controle de acesso aprimorado).

user2418306
fonte
3
Eu acho que você está fazendo muitas perguntas juntos aqui? 1) Os módulos e pacotes são a mesma ideia semântica? 2) (se não 1), os jigsawmódulos -style são apenas uma melhoria técnica em relação aos pacotes? 3) (se não 1 e 2), é Java simplesmente (ou aparentemente) mantendo ambos os conceitos para compatibilidade com versões anteriores. Algumas dessas perguntas são respondidas, outras são principalmente orientadas para a opinião. Acho que uma edição que simplifica os esclarecimentos solicitados está em ordem aqui.
Tersosauros 28/02
1
@Tersosauros Você classificou "algumas" perguntas como fora de tópico, mas não identificou qual delas. Eu vejo isso como apenas uma pergunta (1). Outros serão resolvidos automaticamente. A compatibilidade com versões anteriores para java não é uma pergunta. Portanto, módulos introduzidos pela Java para corrigir falhas de design de pacotes ou duas noções são preocupações verdadeiramente separadas. E a confusão se deve a nomes incorretos.
user2418306
1
Eu quero deixar a pergunta mais clara. Mas preciso entender qual parte você acha que não pode ser respondida. Quando penso que há apenas uma parte.
user2418306
Ahh, eu entendo a confusão. Eu acho que a pergunta 1 é responsável (essa resposta é "Sim, mas não" - e é aí que entra a terceira). Eu concordo com a # 3, obviamente, Java não está prestes a mudar o que uma palavra-chave de linguagem como packageé / significa / nem vai mudar para (vamos ser sinceros, muito horrível) sistemas de caminho de classe no JRE. Pergunta nº 2, que eu acho que é principalmente orientada para a opinião (é responsável , mas minha resposta e a de outra pessoa podem ser diferentes e nenhum de nós necessariamente estaria errado).
Tersosauros
1
Tente fazer uma pergunta clara com antecedência e forneça o material de apoio.
Jay Elston

Respostas:

22

O conceito de um módulo é diferente da instanciação desse conceito.

Java sempre teve módulos. Um método é um módulo, uma classe e um pacote. Um módulo é uma unidade da organização na qual os detalhes internos estão ocultos e se comunica com outros módulos por meio de contratos acordados. Por exemplo, um método é um módulo porque possui internos ocultos (o código e variáveis ​​locais) e um contrato (os parâmetros e o tipo de retorno). Os módulos podem ser compostos de módulos de nível inferior, por exemplo, as classes contêm métodos.

O que falta no Java principal (pré-9) é um módulo implementável . Todos os tipos de módulo acima não são unidades implantáveis ​​que podem ser copiadas. Java possui um artefato implementável chamado arquivo JAR, mas estes não são módulos porque não possuem encapsulamento ou contrato: no tempo de execução, os arquivos JAR desaparecem, todos se fundindo em um único "caminho de classe".

O OSGi abordou a falta de módulos implementáveis ​​em 1998 com o conceito de "pacote". Esses são arquivos JAR fisicamente e contêm pacotes, mas o OSGi define metadados adicionais junto com um sistema de tempo de execução para suportar o encapsulamento e os contratos nesse nível.

O Java 9 aborda a falta de módulos implementáveis ​​de maneira semelhante ao OSGi. Indiscutivelmente, isso foi completamente desnecessário porque o OSGi existe e funciona, mas essa é uma discussão totalmente diferente ...

Infelizmente, o Java 9 atrapalha as águas, nomeando o novo conceito de módulo apenas como "módulo". Isso não significa que métodos, classes e pacotes deixem de ser módulos! Um "módulo" J9 é apenas mais uma instanciação do conceito de módulo . Como os pacotes configuráveis ​​OSGi, os módulos J9 são feitos de pacotes e são artefatos físicos (geralmente arquivos JAR novamente) que podem ser copiados. O sistema de tempo de execução os compreende e reifica.

Resumo: sim módulos e pacotes J9 são noções semanticamente separadas. Obviamente, o Java precisa manter seu conceito de pacote existente para compatibilidade com versões anteriores. Observe que a palavra "pacote" é usada de maneira bastante diferente em Java do que em outras linguagens ou em sistemas de gerenciamento de pacotes como o RPM. Os novos módulos J9 (e pacotes OSGi) são muito mais parecidos com pacotes no RPM do que os pacotes Java.

Neil Bartlett
fonte
O pacote não atende à sua definição de módulo. Devido ao encapsulamento fraco e falta de meios para agregar outros pacotes e refinar sua visibilidade. Classes podem conter classes ou campos aninhados. Os métodos podem conter encerramentos ou chamar outros métodos. Pacotes não podem "se comunicar" com outros pacotes.
user2418306
Discordo. Os pacotes têm ocultação de informações (tipos de acesso, métodos e campos padrão, também conhecidos como package-private). Pacotes certamente "se comunicam" porque o código dentro de um pacote pode invocar o código em outros pacotes. Isso é feito contra um contrato, ou seja, os tipos e métodos públicos do outro pacote.
Neil Bartlett
Observe que a capacidade de agregar artefatos modulares no mesmo nível (por exemplo, métodos contendo fechamentos, classes contendo classes aninhadas) NÃO faz parte da minha definição de módulo. Se você considera que isso é uma parte necessária da definição do módulo, "Java 9 modules" também não são módulos.
Neil Bartlett
Não nego que os pacotes tenham ocultação de informações . Eu disse que não é suficiente. importpode acoplar pacotes. Mas não há como estruturar pacotes como cidadãos de primeira classe. Essas lacunas (e limitações de OSGi) são descritos no JSR 376.
user2418306
Você pode explicar por que os módulos Java 9 também não são módulos ?
user2418306
10

Deixe-me arriscar em uma resposta, embora grande parte possa ser suposições / rachaduras / reclamações, etc.

Eles são a mesma coisa? Bem, sim e não

A partir deste artigo JavaWorld sobre "A modularidade em Java 9" :

Pacotes como uma solução modular

Os pacotes tentam adicionar um nível de abstração ao cenário de programação Java. Eles fornecem recursos para namespaces de codificação exclusivos e contextos de configuração. Infelizmente, porém, as convenções de pacotes são facilmente contornadas, frequentemente levando a um ambiente de acoplamentos perigosos em tempo de compilação.

Como @ user2418306 (OP) sugeriu, " módulos são pacotes feitos corretamente " . Módulos e pacotes em Java (a partir do Java 9, obviamente) são (como o OP pede) semanticamente a mesma coisa. Ou seja, são coleções de bytecode da JVM pré-compiladas, com outros metadados - essencialmente , são bibliotecas .

Bem, qual é a diferença?

No entanto, a diferença está nos metadados dentro de cada um deles. packageManifestos Java , ou manifestos JAR, geralmente não são mantidos por desenvolvedores de bibliotecas, nem fornecem um contrato seguro quanto ao que o pacote JAR / fornece. Conforme explicado aqui (artigo do JavaWorld novamente) :

Os arquivos JAR não são modulares o suficiente?

Os arquivos JAR e o ambiente de implementação em que operam aprimoram bastante as muitas convenções de implantação herdadas disponíveis. Mas os arquivos JAR não possuem exclusividade intrínseca, além de um número de versão raramente usado, oculto em um manifesto .jar. O arquivo JAR e o manifesto opcional não são usados ​​como convenções de modularidade no Java Runtime Environment. Portanto, os nomes dos pacotes das classes no arquivo e sua participação em um caminho de classe são as únicas partes da estrutura JAR que emprestam modularidade ao ambiente de tempo de execução.


Um discurso retórico sobre outros idiomas / ambientes, etc.

Outra área discutida nesse artigo são sistemas como o Maven , que gerenciam dependências para você como parte do processo de criação. A partir dessa página no site do Apache Maven :

Gerenciamento de dependência:

O Maven incentiva o uso de um repositório central de JARs e outras dependências. O Maven vem com um mecanismo que os clientes do seu projeto podem usar para baixar quaisquer JARs necessários para a construção do seu projeto a partir de um repositório JAR central, como o CPAN do Perl. Isso permite que os usuários do Maven reutilizem JARs entre projetos e incentiva a comunicação entre os projetos para garantir que os problemas de compatibilidade com versões anteriores sejam resolvidos.

Agora, para falar sobre o futuro como se eu estivesse lá

Como a página mencionou, outros idiomas (como Perl) têm repositórios de pacotes (como CPAN ). Essa é uma tendência crescente (digo porque sinto vontade, sem nenhuma prova enfática), ao longo da última década ou mais. Ferramentas como as gemas de Ruby , PyPi do Python e o gerenciador de pacotes Node ( npm) se baseiam nisso para fornecer uma maneira consistente de configurar um ambiente (desenvolvimento, construção, teste ou tempo de execução, etc.) com as coisas certas (pacotes, módulos, gemas, aparelhos, etc). Uma idéia (eu sinto) foi " emprestada " de sistemas de distribuição Linux®, como o Debian apt , o RedHat'srpm, etc. (Embora, obviamente, tenha evoluído pelo menos uma geração e tornado essas coisas mais agradáveis.)


Os módulos Java , embora ainda não incluam necessariamente nada que você não possa fazer, facilitam MUITO as ferramentas para gerenciamento de dependências / pacotes e ambientes de construção automatizados . Se isso torna os módulos "melhores", recuso-me a dizer. : P

Tersosauros
fonte
1
O artigo tem apenas 1 ano e já está obsoleto. Ele mora como o controle de versão é uma característica fundamental de um módulo. Os módulos de serra de vaivém não terão informações sobre a versão. Nada no domínio do gerenciamento de dependência será alterado para o usuário final. Para ferramentas de construção, as coisas ficarão muito mais difíceis de fato. Como eles precisam suportar realidades paralelas de classpathe modulepath. E pule pelos aros para apoiar o teste de unidade. A premissa de que dois conceitos são equivalentes porque representam coleção de coisas mais metadados é muito ousada para eu aceitar. Além disso, no meio do caminho, você de repente substituiu o frasco pelo pacote.
user2418306
Eu não disse que " dois conceitos são equivalentes ", eu disse que eles são "semanticamente a mesma coisa" - e foi sobre isso que você perguntou. Além disso, você editou a pergunta desde que eu respondi para mencionar especificamente o JSR-376 , em oposição ao quebra - cabeças que foi dito anteriormente: - /
Tersosauros
A serra de vaivém abrange (implementa) JSR-376. A pergunta ainda está vinculada a ambos, portanto, nenhum dano foi causado. Dicionário define equivalência como a qualidade ou estado de ter o mesmo significado. E semanticamente - em relação ao significado. Sinto muito, mas você está sendo pedante sobre detalhes errados aqui. Você disse que eles são equivalentes. Mas você não forneceu nenhum raciocínio. Em vez disso, consulte o artigo que descreve como os pacotes e os frascos deixam de ser módulos. Mas os próximos módulos também não são os módulos do artigo. Reivindicar equivalência e depois fornecer diferença entre os 2 (3) é auto-contraditório.
user2418306
A resposta à pergunta não pode ser sim e não. Dois conceitos semanticamente equivalentes ou não. Por favor, não lobotomize meus comentários e retorne à pergunta original. Uma linguagem precisa dos dois conceitos ou esse é um problema específico do legado java? Se precisar de esclarecimentos, fico feliz em ajudar.
user2418306