¿Por qué usar un sistema de compilación?

Informar un problema Ver fuente Nightly · 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

En esta página, se explica qué son los sistemas de compilación, qué hacen, por qué debes usar un sistema de compilación y por qué los compiladores y las secuencias de comandos de compilación no son la mejor opción a medida que tu organización comienza a escalar. Está dirigido a desarrolladores que no tienen mucha experiencia con un sistema de compilación.

¿Qué es un sistema de compilación?

Básicamente, todos los sistemas de compilación tienen un propósito claro: transforman el código fuente escrito por los ingenieros en objetos binarios ejecutables que las máquinas pueden leer. Los sistemas de compilación no son solo para código creado por personas, también permiten que las máquinas creen compilaciones automáticamente, ya sea para pruebas o actualizaciones para producción. En una organización con miles de ingenieros, es común que la mayoría de las compilaciones se activen automáticamente en lugar de que los ingenieros lo hagan directamente.

¿No puedo usar un compilador?

Es posible que la necesidad de un sistema de compilación no sea evidente de inmediato. La mayoría de los ingenieros no usan un sistema de compilación mientras aprenden a codificar: la mayoría comienza invocando herramientas como gcc o javac directamente desde la línea de comandos, o el equivalente en un entorno de desarrollo integrado (IDE). Siempre que todo el código fuente se encuentre en el mismo directorio, un comando como este funcionará bien:

javac *.java

Esto le indica al compilador de Java que tome cada archivo fuente Java del directorio actual y lo convierta en un archivo de clase binaria. En el caso más simple, esto es todo lo que necesitas.

Sin embargo, tan pronto como se expande el código, comienzan las complicaciones. javac es lo suficientemente inteligente como para buscar en los subdirectorios del directorio actual el código para importar. Sin embargo, no tiene forma de encontrar el código almacenado en otras partes del sistema de archivos (quizás una biblioteca compartida por varios proyectos). También solo sabe compilar código Java. Los sistemas grandes suelen implicar diferentes partes escritas en una variedad de lenguajes de programación con redes de dependencias entre esas partes, lo que significa que ningún compilador para un solo lenguaje puede compilar todo el sistema.

Una vez que trabajes con código de varios lenguajes o varias unidades de compilación, la compilación de código ya no será un proceso de un solo paso. Ahora debes evaluar de qué depende tu código y compilar esas piezas en el orden correcto, posiblemente con un conjunto diferente de herramientas para cada una. Si cambia alguna dependencia, debes repetir este proceso para evitar depender de objetos binarios inactivos. Para una base de código de tamaño moderado, este proceso se vuelve rápidamente tedioso y propenso a errores.

El compilador tampoco sabe cómo controlar dependencias externas, como archivos JAR de terceros en Java. Sin un sistema de compilación, puedes administrar esto descargando la dependencia de Internet, mantenla en una carpeta lib del disco duro y configurando el compilador para que lea las bibliotecas de ese directorio. Con el tiempo, es difícil mantener las actualizaciones, las versiones y la fuente de estas dependencias externas.

¿Qué ocurre con las secuencias de comandos de shell?

Supongamos que tu proyecto de afición comienza lo suficientemente simple como para que puedas compilarlo solo con un compilador, pero comienzas a encontrarte con algunos de los problemas descritos anteriormente. Tal vez todavía no creas que necesitas un sistema de compilación y puedes automatizar las partes tediosas con algunas secuencias de comandos de shell simples que se encargan de compilar las cosas en el orden correcto. Esto ayuda durante un tiempo, pero pronto comienzas a encontrarte con más problemas:

  • Se vuelve tedioso. A medida que tu sistema se vuelve más complejo, comienzas a pasar casi tanto tiempo trabajando en tus secuencias de comandos de compilación como en el código real. La depuración de secuencias de comandos de shell es complicada, ya que cada vez más hackeos se superponen.

  • Es lento. Para asegurarte de no depender accidentalmente de bibliotecas inactivas, tu secuencia de comandos de compilación compila cada dependencia en orden cada vez que la ejecutas. Piensas en agregar algo de lógica para detectar qué partes deben reconstruirse, pero eso suena muy complejo y propenso a errores para una secuencia de comandos. O piensas en especificar qué partes se deben reconstruir cada vez, pero vuelves al cuadrado.

  • ¡Buenas noticias! ¡Llegó la hora del lanzamiento! Averigua mejor todos los argumentos que debes pasar al comando jar para hacer la compilación final. Y recuerda cómo subirlo y enviarlo al repositorio central. Además, compila y envía las actualizaciones de la documentación, y envía una notificación a los usuarios. Quizás esto requiera otra secuencia de comandos...

  • ¡Desastre! Tu disco duro falla y ahora debes volver a crear todo el sistema. Fuiste lo suficientemente inteligente como para mantener todos tus archivos fuente en el control de versiones, pero ¿qué sucede con las bibliotecas que descargaste? ¿Puedes volver a encontrarlas y asegurarte de que fueran de la misma versión que cuando las descargaste por primera vez? Es probable que tus secuencias de comandos dependan de herramientas específicas que se instalaron en lugares específicos. ¿Puedes restablecer ese mismo entorno para que las secuencias de comandos vuelvan a funcionar? ¿Qué sucede con todas esas variables de entorno que configuraste hace mucho tiempo para que el compilador funcionara correctamente y luego olvidaste?

  • A pesar de los problemas, tu proyecto tiene el éxito suficiente como para que puedas comenzar a contratar más ingenieros. Ahora te das cuenta de que los problemas anteriores no necesitan ningún desastre; debes pasar por el mismo proceso de inicio doloroso cada vez que un desarrollador nuevo se une a tu equipo. Y, a pesar de tus mejores esfuerzos, aún hay pequeñas diferencias en el sistema de cada persona. Por lo general, lo que funciona en la máquina de una persona no funciona en el de otra, y cada vez se requieren unas horas de rutas de herramientas de depuración o versiones de biblioteca para descubrir dónde se encuentra la diferencia.

  • Decides que necesitas automatizar tu sistema de compilación. En teoría, esto es tan simple como obtener una computadora nueva y configurarla para ejecutar la secuencia de comandos de compilación todas las noches con cron. Aún debes pasar por el doloroso proceso de configuración, pero ahora no tienes el beneficio de que un cerebro humano sea capaz de detectar y resolver problemas menores. Ahora, todas las mañanas, cuando ingresas, ves que la compilación de anoche falló porque ayer un desarrollador realizó un cambio que funcionaba en su sistema, pero no en el sistema de compilación automatizado. Cada vez es una solución simple, pero ocurre con tanta frecuencia que terminas por pasar mucho tiempo todos los días descubriendo y aplicando estas soluciones simples.

  • Las compilaciones se vuelven cada vez más lentas a medida que el proyecto crece. Un día, mientras esperas a que se complete una compilación, observas con tristeza el escritorio inactivo de tu compañero de trabajo, que está de vacaciones, y te gustaría aprovechar toda esa capacidad de procesamiento desperdiciada.

Te topaste con un problema clásico de escala. Para un solo desarrollador que trabaja como máximo en doscientas líneas de código durante una o dos semanas como máximo (lo que podría haber sido toda la experiencia hasta ahora para un desarrollador júnior que acaba de graduarse de la universidad), todo lo que necesitas es un compilador. Las secuencias de comandos pueden llevarte un poco más lejos. Sin embargo, en cuanto necesitas coordinar entre varios desarrolladores y sus máquinas, incluso una secuencia de comandos de compilación perfecta no es suficiente, ya que se vuelve muy difícil tener en cuenta las diferencias menores en esas máquinas. En este punto, este enfoque simple falla y es hora de invertir en un sistema de compilación real.