¿Por qué los paquetes y módulos son conceptos separados en Java 9?

21

Java 9 tendrá módulos además de paquetes. Por lo general, los idiomas tienen uno u otro. Y la mayoría de los programadores perciben dos términos como sinónimos. Los módulos están construidos sobre paquetes, tratándolos como primitivos. El patrón compuesto sugiere tratar los primitivos y los compuestos de manera uniforme. De lo contrario, sucederán cosas malas. Por ejemplo, mire el proyecto Valhalla, donde intentan adaptar el supertipo común para primitivo (valor) y tipos de referencia.

¿Los módulos y paquetes representan nociones semánticamente separadas? Lo que significa que es sensato tener ambos para cualquier idioma (separación de preocupaciones). ¿O Java tiene que tener ambos como tributo a la compatibilidad con versiones anteriores?

¿Por qué introducir un nuevo concepto en lugar de aumentar el existente?


JSR 376 : "Sistema de módulo de plataforma Java" implementado dentro del proyecto Jigsaw .

De acuerdo con SOTMS

Un módulo es una colección de código y datos con nombre y autodescripción. Su código está organizado como un conjunto de paquetes que contienen tipos, es decir, clases e interfaces Java; Sus datos incluyen recursos y otros tipos de información estática.

JLS evita cuidadosamente definir qué es un paquete . De Wikipedia :

Un paquete de Java es una técnica para organizar clases de Java en espacios de nombres similares a los módulos de Modula, proporcionando programación modular en Java.

Sé que citar Wikipedia es una mala práctica, pero refleja un entendimiento común. Desde la entrada en programación modular:

El término paquete a veces se usa en lugar de módulo (como en Dart, Go o Java). En otras implementaciones, este es un concepto distinto; en Python, un paquete es una colección de módulos, mientras que en el próximo Java 9 se planea la introducción del nuevo concepto de módulo (una colección de paquetes con control de acceso mejorado).

usuario2418306
fuente
3
¿Creo que estás haciendo muchas preguntas todos juntos aquí? 1) ¿Son los módulos y paquetes la misma idea semántica? 2) (si no 1), ¿son los jigsawmódulos de estilo solo una mejora técnica sobre los paquetes? 3) (si no es 1 y si es 2), es Java simplemente (o aparentemente) manteniendo ambos conceptos por compatibilidad con versiones anteriores. Algunas de estas preguntas son respondibles, algunas están principalmente orientadas a la opinión. Creo que una edición que simplifica las aclaraciones buscadas está en orden aquí.
Tersosauros
1
@Tersosauros Has clasificado "algunas" preguntas como fuera de tema, pero no has etiquetado cuál es cuál. Lo veo como una sola pregunta (1). Otro se resolverá automáticamente. La compatibilidad con versiones anteriores de Java no es una pregunta. Entonces, java introdujo módulos para parchear defectos de diseño de paquetes o dos nociones son preocupaciones realmente separadas. Y la confusión se debe al mal nombre.
user2418306
1
Quiero aclarar la pregunta. Pero necesito entender qué parte de ella crees que no tiene respuesta. Cuando pienso que solo hay una parte.
user2418306
Ahh, entiendo la confusión. Creo que la pregunta n. ° 1 es responsable (la respuesta es "Sí, pero no", que es donde entra el n. ° 3). Estoy de acuerdo con el n. ° 3, obviamente Java no va a cambiar lo que una palabra clave de lenguaje como packagees / hace / significa, ni van a cambiar a sistemas de classpath (seamos sinceros, bastante horribles) en el JRE. Pregunta # 2 Creo que está orientada principalmente a la opinión (es responsable , pero mi respuesta y la de otra persona pueden diferir y ninguno de nosotros necesariamente estaría equivocado).
Tersosauros
1
Intente hacer una pregunta clara por adelantado, luego suministre el material de apoyo.
Jay Elston

Respuestas:

22

El concepto de un módulo es diferente de la instanciación de ese concepto.

Java siempre ha tenido módulos. Un método es un módulo, también lo es una clase y también un paquete. Un módulo es una unidad de organización en la que se ocultan los detalles internos, y que se comunica con otros módulos a través de contratos acordados. Por ejemplo, un método es un módulo porque tiene elementos internos ocultos (el código y las variables locales) y un contrato (los parámetros y el tipo de retorno). Los módulos pueden estar compuestos de módulos de nivel inferior, por ejemplo, las clases contienen métodos.

Lo que falta en el núcleo de Java (pre-9) es un módulo desplegable . Todos los tipos de módulos anteriores no son unidades desplegables que se puedan copiar. Java tiene un artefacto desplegable llamado archivo JAR, pero estos no son módulos porque no tienen encapsulación o contrato: en tiempo de ejecución los archivos JAR desaparecen, todos se fusionan en un solo "classpath".

OSGi abordó la falta de módulos desplegables en 1998 con el concepto de un "paquete". Estos son archivos JAR físicamente y contienen paquetes, pero OSGi define metadatos adicionales junto con un sistema de tiempo de ejecución para admitir la encapsulación y los contratos a ese nivel.

Java 9 aborda la falta de módulos desplegables de manera similar a OSGi. Podría decirse que esto era completamente innecesario porque OSGi existe y funciona, pero esa es una discusión completamente diferente ...

Desafortunadamente, Java 9 enturbia las aguas al nombrar el nuevo concepto de módulo solo como un "módulo". ¡Esto no significa que los métodos, clases y paquetes dejen de ser módulos! Un "módulo" J9 es solo otra instancia del concepto de módulo . Al igual que los paquetes OSGi, los módulos J9 están hechos de paquetes y son artefactos físicos (generalmente archivos JAR nuevamente) que se pueden copiar. El sistema de tiempo de ejecución los comprende y los reifica.

Resumen: sí, los módulos y paquetes J9 son nociones semánticamente separadas. Obviamente, Java tiene que conservar su concepto de paquete existente para la compatibilidad con versiones anteriores. Tenga en cuenta que la palabra "paquete" se usa de manera bastante diferente en Java que en otros lenguajes o en sistemas de administración de paquetes como RPM. Los nuevos módulos J9 (y los paquetes OSGi) se parecen mucho más a los paquetes en RPM que a los paquetes Java.

Neil Bartlett
fuente
El paquete no cumple con su definición de módulo. Debido a la débil encapsulación y la falta de medios para agregar otros paquetes y refinar su visibilidad. Las clases pueden contener clases o campos anidados. Los métodos pueden contener cierres o llamar a otros métodos. Los paquetes no pueden "comunicarse" con otros paquetes.
user2418306
Estoy en desacuerdo. Los paquetes tienen información oculta (tipos de acceso, métodos y campos predeterminados, también conocido como paquete privado). Los paquetes ciertamente "se comunican" porque el código dentro de un paquete puede invocar código en otros paquetes. Esto se realiza contra un contrato, es decir, los tipos y métodos públicos del otro paquete.
Neil Bartlett
Tenga en cuenta que la capacidad de agregar artefactos modulares en el mismo nivel (por ejemplo, métodos que contienen cierres, clases que contienen clases anidadas) NO forma parte de mi definición de módulo. Si considera que esto es una parte necesaria de la definición del módulo, los "módulos de Java 9" tampoco son módulos.
Neil Bartlett
No niego que los paquetes tengan información oculta . Dije que no es suficiente. importPuede acoplar paquetes. Pero no hay forma de estructurar paquetes como ciudadanos de primera clase. Esas deficiencias (y limitaciones de OSGi) se describen en JSR 376.
user2418306
¿Puedes explicar por qué los módulos Java 9 tampoco son módulos ?
user2418306
10

Permítanme arriesgarme con una respuesta, aunque gran parte puede ser suposiciones / división de pelos / despotricar, etc.

¿Son la misma cosa? Bueno si y no

De este artículo de JavaWorld sobre "Modularidad en Java 9" :

Paquetes como solución modular

Los paquetes intentan agregar un nivel de abstracción al panorama de programación Java. Proporcionan facilidades para espacios de nombres de codificación únicos y contextos de configuración. Sin embargo, lamentablemente, las convenciones de paquetes se eluden fácilmente, lo que a menudo conduce a un entorno de acoplamientos peligrosos en tiempo de compilación.

Como @ user2418306 (OP) insinuó, " módulos son paquetes bien hechos " . Los módulos y paquetes en Java (a partir de Java 9, obviamente) son (como pregunta OP) semánticamente lo mismo. Es decir, son colecciones de bytecode JVM precompilados, con otros metadatos , esencialmente , son bibliotecas .

Bueno, cual es la diferencia?

Sin embargo, la diferencia está en los metadatos dentro de cada uno de ellos. Los packagemanifiestos de Java , o los manifiestos JAR, a menudo no son mantenidos por los desarrolladores de la biblioteca, ni proporcionan ningún contrato seguro sobre lo que proporciona el paquete JAR /. Como se explica aquí (artículo de JavaWorld nuevamente) :

¿No son los archivos JAR lo suficientemente modulares?

Los archivos JAR y el entorno de implementación en el que operan mejoran en gran medida las numerosas convenciones de implementación heredadas que de otro modo estarían disponibles. Pero los archivos JAR no tienen unicidad intrínseca, aparte de un número de versión poco utilizado, que está oculto en un manifiesto .jar. El archivo JAR y el manifiesto opcional no se utilizan como convenciones de modularidad dentro del entorno de tiempo de ejecución Java. Por lo tanto, los nombres de paquetes de clases en el archivo y su participación en un classpath son las únicas partes de la estructura JAR que prestan modularidad al entorno de tiempo de ejecución.


Una queja sobre otros idiomas / entornos, etc.

Otra área discutida en ese artículo son los sistemas como Maven , que administran las dependencias para usted como parte del proceso de compilación. Desde esta página en el sitio de Apache Maven :

Gestión de dependencias:

Maven fomenta el uso de un repositorio central de JAR y otras dependencias. Maven viene con un mecanismo que los clientes de su proyecto pueden usar para descargar cualquier JAR requerido para construir su proyecto desde un repositorio JAR central como el CPAN de Perl. Esto permite a los usuarios de Maven reutilizar los JAR en todos los proyectos y fomenta la comunicación entre proyectos para garantizar que se aborden los problemas de compatibilidad con versiones anteriores.

Ahora para hablar sobre el futuro como si hubiera estado allí

Como mencionó esa página , otros idiomas (como Perl) tienen repositorios de paquetes (como CPAN ). Esta es una tendencia creciente (lo digo porque me da la gana, sin ninguna prueba contundente), durante la última década más o menos. Las herramientas como las gemas de Ruby , PyPi de Python y el administrador de paquetes Node ( npm) se basan en esto para proporcionar una forma coherente de configurar un entorno (desarrollo, construcción, prueba o tiempo de ejecución, etc.) con las cosas correctas (paquetes, módulos, gemas, artilugios, etc.). Una idea (creo) fue " prestada " de los sistemas de distribución Linux® como Debian's apt , RedHat'srpm, etc. (Aunque, obviamente, ha evolucionado al menos una generación y ha hecho que todo esto sea más agradable).


Los módulos Java , aunque no necesariamente agregan nada que no pueda hacer ya, hacen que las herramientas para la gestión de dependencias / paquetes y entornos de compilación automatizados sean MUCHO más fáciles. Si eso hace que los módulos sean "mejores", me niego a decir. :PAG

Tersosauros
fuente
1
El artículo tiene solo 1 año y, sin embargo, ya está obsoleto. Se centra en cómo el control de versiones es una característica fundamental de un módulo. Los módulos de rompecabezas no tendrán información de versión. Nada en el ámbito de la gestión de dependencias cambiará para el usuario final. Para las herramientas de construcción, las cosas serán mucho más difíciles de hecho. Como necesitan soportar realidades paralelas de classpathy modulepath. Y saltar a través de aros para apoyar las pruebas unitarias. La premisa de que dos conceptos son equivalentes porque representan una colección de cosas más los metadatos es demasiado audaz para que yo acepte. Además, a mitad de camino, de repente has sustituido el frasco por el paquete.
user2418306
No dije " dos conceptos son equivalentes ", dije que son "semánticamente lo mismo", que es lo que preguntaste. Además, ha editado la pregunta desde que respondí para mencionar específicamente JSR-376 , en oposición a Jigsaw, que es lo que se dijo anteriormente: - /
Tersosauros
Jigsaw abarca (implementos) JSR-376. La pregunta sigue vinculada a ambos, por lo que no se hizo daño. El diccionario define la equivalencia como la calidad o el estado de tener el mismo significado. Y semánticamente, con respecto al significado. Lo siento, pero estás siendo pedante con los detalles incorrectos aquí. Has dicho que son equivalentes. Pero no proporcionaste ningún razonamiento. En su lugar, consulte el artículo que explica cómo los paquetes y los tarros no pueden ser módulos. Pero los próximos módulos tampoco pueden ser módulos del artículo. Reclamar equivalencia y luego proporcionar diferencia entre los 2 (3) es contradictorio.
user2418306
La respuesta a la pregunta no puede ser sí y no. Dos conceptos semánticamente equivalentes o no. No lobotomice mis comentarios y vuelva a la pregunta original. ¿Necesita un lenguaje ambos conceptos o este es un problema específico de Java Legacy? Si necesita aclaraciones, me complace ayudarlo.
user2418306