2012-01-11 17 views
5

Soy nuevo en compiladores Java modernos y máquinas virtuales, así que tengo curiosidad por saber qué problemas técnicos encuentran los grandes proyectos Java (más de 5000 clases considerables), durante la compilación y en tiempo de ejecución, a medida que crece el nudo gordiano de las dependencias de paquetes.¿Existen razones técnicas para evitar la creación de dependencias de paquetes muy enredados en grandes proyectos de Java?

En grandes proyectos de C++, puede tener problemas técnicos (dejando de lado todas las inquietudes de mantenimiento) si se aleja de un gráfico de dependencias de biblioteca acíclica (o paquete) en proyectos grandes.

Algunos ejemplos

  • de compilación que se quede sin memoria si la mayor parte de un árbol de código fuente está incluido
  • vinculación también puede hacerlo si se incluyen demasiados archivos de objetos (archivos de objetos generalmente se correlacionan con los paquetes en C++ proyectos)

El problema se agrava considerablemente con la instanciación de plantillas en línea. Las estaciones de trabajo modernas no están equipadas para compilar y vincular un proyecto que reúne la mayoría de las 5000 clases considerables en una u otra fase de la compilación.

Los desarrolladores de Java que he preguntado no creen que las limitaciones técnicas sean una razón para evitar dependencias de paquetes circulares (se aplican otras motivaciones). ¿Hay alguno?

+0

Independientemente de las limitaciones técnicas de Java, las dependencias de paquetes cíclicos pueden conducir a un monolito. Evitarlos puede ser útil. –

+0

@ AndyThomas-Cramer - ¿Qué es una "dependencia del paquete" en Java? No creo que exista tal cosa (en lo que se refiere al compilador). –

+0

@TedHopp: consulta la respuesta a tu comentario similar a continuación. –

Respuesta

4
  1. El compilador de Java (javac) no compila todas las clases, al mismo tiempo, pero en lugar de uno en uno, descubrir de forma dinámica sin compilar o rancios .class archivos.

  2. No hay que vincule. En su lugar, todos los archivos .class se empaquetan juntos en un archivo jar una vez compilado. Esto es básicamente una compresión ZIP y este paso ni siquiera es necesario.

  3. El compilador de Java es moderadamente simple debido a la simple sintaxis y semántica del lenguaje. No hay mucha metaprogramación, tipo de inferencia, etc. El compilador de Scala, por ejemplo, es mucho más lento porque el lenguaje en sí es mucho más complicado.

Dicho esto, no encuentro ninguna limitación técnica para compilar proyectos grandes y enredados. Obviamente, el tiempo de construcción crece y una vez que excede 10 minutos se convierte en un dolor, pero eso no es realmente un problema.

El problema real con referencias enredadas, circulares y cruzadas es el mantenimiento del código fuente. Principalmente es mucho más difícil refactorizar el código. Una vez que el proyecto alcanza cierto tamaño (más de 5000 clases probablemente sean alrededor de medio millón de LOC), los desarrolladores intentarán dividirlo en pedazos. Extrae bibliotecas, módulos y capas. Si las dependencias son tan fuertes, este proceso es casi imposible.

+1

Supongamos que tiene A.java y B.java, sin archivos .class. Si la clase A depende de la existencia de B.class para compilar, y la clase B depende de la existencia de A.class para compilar, el compilador los compilará a la vez (ya que los archivos .class simplemente no se pueden generar secuencialmente). Una estrategia para un compilador sería generar incrementalmente los archivos .class: hacer suficiente de A.class para compilar B, luego retroceder y finalizar A.class. En mi libro, eso todavía los está recopilando juntos. –

+0

Tomasz lo tiene en pocas palabras. No es un problema de compilación, es una cuestión de buena modularidad. No pondría miles de líneas de código en un método, ni miles de métodos en una clase. Se modulariza para hacer que el código sea más fácil de entender para un desarrollador humano. Para detenerse en el nivel de clase simplemente no es escalable, necesita módulos de nivel superior. Los frascos, los frijoles, los paquetes, etc. cumplen esta función, pero cuando contienen más que una cantidad de clases pensadas, necesita algo intermedio, y los paquetes son lo que tiene en Java. Y una estructura de módulo debe ser acíclica. –

1

Realmente no existen las dependencias de paquetes en Java. Solo hay dependencias de clase (e interfaz). Cuando importa un paquete en Java, solo le está diciendo al compilador cómo resolver los nombres (para que no necesite calificar completamente todas las clases o el nombre de importación estático que usa).

Las dependencias circulares entre miles de clases probablemente pondrían al compilador de rodillas.

+0

Esa es una declaración muy fuerte. De hecho, existe una dependencia entre los paquetes de Java, y existen herramientas para mostrarlos. Se podría decir que el compilador ignora las dependencias del paquete. –

+0

@ AndyThomas-Cramer - ¿Qué es una dependencia entre paquetes de Java? ¿Qué lo crea? ¿Qué efecto tiene? En lo que se refiere a una jerarquía de paquetes, no hay ningún valor semántico en lo que se refiere al lenguaje Java; es estrictamente una herramienta de administración de código. –

+0

Existen dependencias en granularidades múltiples, entre métodos, clases, paquetes, archivos jar. Algunos son relevantes para el compilador, y otros no. Existe una diferencia entre decir "esta dependencia no tiene ningún efecto en términos del lenguaje/compilador" y decir "realmente no existe tal cosa como las dependencias del paquete". –

Cuestiones relacionadas