Tengo dificultades para entender por qué debería desarrollar bibliotecas internas para usar exclusivamente para desarrollar aplicaciones internas. Aprecio que si quiero usar el software que alguien fuera de la organización ha escrito, pueden enviarme sus archivos de encabezado y archivos .a o .so y simplemente puedo vincularlo a mi proyecto (suponiendo que estén compilados en el mismo entorno) .
Pero, ¿por qué se debe desarrollar una biblioteca interna solo para vincularla a una aplicación interna cuando tengo acceso al encabezado y a los archivos de implementación y puedo incluirlos en mi árbol fuente y compilarlos todos juntos?
En otras palabras: si se escribe algún código fuente, ¿cómo decide si debe compilarse en una biblioteca binaria y vincularse a su aplicación o simplemente incluirse en los archivos fuente del proyecto y compilarse regularmente?
Cuando digo 'incluir' archivos en cada proyecto, no me refiero a copiar y pegar cada archivo en el árbol de origen del proyecto que se está desarrollando actualmente. Me refiero a desarrollar algún directorio / biblioteca (separado de cualquier proyecto) que contenga código fuente común que se pueda incluir en los archivos de un proyecto de la manera habitual, es decir, #include.
PD Estoy hablando del desarrollo de c / c ++ aquí para múltiples aplicaciones de escritorio.
Respuestas:
Existen numerosas razones para crear bibliotecas y bibliotecas compartidas (en archivos .dll o .so) incluso para uso interno:
Algunas compañías incluso tienen una práctica contable donde los proyectos que crean bibliotecas obtienen algún reembolso por cada reutilización.
fuente
Algunas otras posibles razones que pueden aplicarse a proyectos más grandes y no triviales:
Tiempos de compilación: los enormes proyectos monolíticos de C ++ con miles de archivos, miles de clases, funciones, etc. pueden tardar mucho tiempo en compilarse (lo que perjudica la productividad si desea recompilar cada vez que cambia algunas líneas de código). Las bibliotecas vinculadas estáticamente y dinámicamente se compilan de forma independiente y no es necesario volver a compilar si su fuente no ha cambiado.
Separación lógica de distintos módulos o subsistemas : los sistemas grandes suelen ser más fáciles de administrar si se colocan distintas áreas de funcionalidad en módulos separados, y los desarrolladores no se enfrentan a la búsqueda a través de enormes carpetas / proyectos que contienen miles de archivos / clases.
Límites entre desarrolladores / equipos : los desarrolladores que crean nuevas funcionalidades separadas al mismo tiempo pueden reducir la posibilidad de conflictos de fusión si es posible que cada desarrollador trabaje en módulos diferentes.
Código que no debe liberarse en un entorno activo : por ejemplo, bibliotecas de prueba unitaria o bibliotecas 'simuladas' que se utilizan para pruebas de desarrollador para sustituir un componente del sistema activo (hardware, API, sistemas remotos, bases de datos, etc.)
Indicadores del compilador : si se encuentra en la desafortunada posición de integrarse con la API de un tercero que espera un indicador extraño del compilador, entonces la biblioteca puede ser una "capa de descontaminación" situada entre el API del tercero y el resto de la aplicación.
Características opcionales / Optimización : en sistemas grandes, una aplicación puede esperar antes de cargar ciertos módulos vinculados dinámicamente en la memoria en tiempo de ejecución si no son críticos para la funcionalidad básica de la aplicación.
En general, muchos proyectos internos suelen ser pequeñas micro-aplicaciones que no se benefician al dividirse en bibliotecas separadas. Si está trabajando en un pequeño proyecto como desarrollador solitario, entonces 'podría' no tener que preocuparse por dividir su código en bibliotecas (todavía ...). No olvides el principio YAGNI .
fuente
Su pregunta original podría haber causado un malentendido aquí para la mayoría de esas otras respuestas. Dado que tiene la intención de no copiar el código existente en los proyectos, sino incluir los mismos archivos fuente de diferentes proyectos como referencias , cualquier argumento de "código duplicado" deja de tener sentido, así como muchos otros argumentos presentados.
Tenga en cuenta que esto es a veces (no siempre) una técnica sensata . De hecho, cuando coloca todos los archivos fuente que desea reutilizar en los proyectos en una carpeta de inclusión separada, también construye una biblioteca, una biblioteca de código fuente, no una biblioteca binaria. Especialmente en C ++, cuando se crean bibliotecas genéricas con plantillas, no es inusual tener librerías solo de encabezado, que solo necesitan una inclusión simple y no preparaciones de enlace separadas.
Así que supongo que su verdadera pregunta es: ¿cuándo construir libs de código fuente o cuándo preferir libs binarias precompiladas? En esta respuesta anterior en este sitio , discutí algunos pros y contras de las bibliotecas de solo encabezado, tal vez te ayude. La principal ventaja de las bibliotecas de código fuente es que no requieren ser compiladas con el mismo tiempo de ejecución y / o indicadores de compilador / enlazador compatibles que la aplicación que los usa. Los inconvenientes son los tiempos de compilación adicionales y el requisito de proporcionar acceso al código fuente (que obviamente no es un problema para el tipo de proyectos "internos" que tiene en mente).
fuente
Estoy de acuerdo con otros comentaristas cuando escriben que no debes duplicar el código. En su caso, sin embargo, parece que usted (o las personas con las que trabaja) está creando bibliotecas para el código que no está duplicado en otro lugar.
En este caso, advierto contra la generalización prematura . A menudo hay momentos en que uno siente que una pieza de código será reutilizable. Sin embargo, sin conocer los detalles íntimos de cómo el segundo caso de uso usará dicho código, es muy fácil dedicar más tiempo a las características de "reutilización" que en realidad no serán útiles en los casos adicionales o hacer suposiciones que resulten incorrectas en El segundo caso.
Escribir una "biblioteca" para un caso de uso puede convertirse en un ejercicio muy costoso sin ningún beneficio. Esto me ha mordido varias veces.
Ejemplo de costos:
Mi regla general es: no convierta el código en una biblioteca a menos que tenga al menos 2 lugares separados donde se necesita el código.
fuente
Porque si "los incluye en mi árbol de origen", está duplicando el código .
El problema con eso es que no se beneficiará de ninguna mejora (incluidas las correcciones de errores críticas) realizadas por el proyecto del que copió el código, ni se beneficiarán de las mejoras que realice.
Puede pensar que puede resolver este problema simplemente copiando la versión más reciente del código en su árbol fuente regularmente, tal vez incluso automatizado mediante el uso de un submódulo en git o algo similar. Pero entonces tendrá constantemente una interrupción de compilación debido a cambios incompatibles de API. Por otro lado, una biblioteca tiene una API pública "oficial" que sus desarrolladores saben que no se puede cambiar sin coordinarse con los clientes.
Finalmente, puede haber razones técnicas: ¿podría ser necesario mantener parte del código como biblioteca para que pueda cargarse opcionalmente o incluso cargarse y descargarse a pedido, y así reducir el uso de memoria cuando no se necesita la funcionalidad?
fuente
Me gustaría detallar los costos que su solución tiene a largo plazo.
Claramente, agregar una biblioteca a un proyecto tiene algo de sobrecarga, todo lo anterior si es el primero: los flujos de trabajo deben cambiarse, a veces incluso la infraestructura y a algunos miembros del equipo puede no gustarles (al principio). Por lo tanto, las ventajas de su solución son obvias, ya que ahora impone menos costos .
Sin embargo, a medida que su proyecto crezca, también lo harán los costos de la "pseudo-biblioteca". Suponga que tiene una "pseudo-biblioteca"
A
que es utilizada por una aplicación y un probador de unidades. Cada vez que agrega un cppA
, debe agregarlo a ambos proyectos, de lo contrario no se vincularán.¿Qué pasa si su "pseudo-biblioteca" es utilizada por otra "pseudo-biblioteca"
B
? Tienes que agregar tu nuevo cpp en un montón de proyectos más. ¿Y siB
cambia para usar otra biblioteca? Tendrá que eliminar los cpps deA
en todos los proyectos dependiendo solo deB
.Todo esto sería gratis si se utilizara una biblioteca real. Entonces la pregunta es, ¿cuántos cpps son necesarios para justificar el cambio a una biblioteca real?
Pero espere, hay aún más garantías: a un desarrollador no le gusta este estúpido trabajo de buscar todos los proyectos que necesitan el nuevo cpp y agregará su código / clases en algún lugar en archivos ya existentes, lo que no es algo bueno en A la larga.
Por lo tanto, usar la "pseudo-biblioteca" puede ser un primer paso para romper un proyecto monolítico, pero no debe esperar demasiado para convertirlo en una biblioteca real para poder usar sus ventajas.
fuente
Si la biblioteca solo es utilizada por una aplicación, entonces probablemente no la necesite como una biblioteca separada.
Si la biblioteca es utilizado por 3.500 aplicaciones a continuación, a pesar de todo lo que necesita como una biblioteca independiente.
¿Qué pasa si hay un error en la biblioteca y necesitas arreglarlo? ¿O se produce algún cambio legal o reglamentario que significa que tiene que cambiar la forma en que funciona la biblioteca?
Si está en una biblioteca separada, entonces puede (potencialmente) arreglar la biblioteca, volver a probarla y volver a implementarla, y cada aplicación se beneficia de la corrección.
Si solo está en el código fuente que es "local" para cada aplicación, entonces debe cambiar, reconstruir, volver a probar y volver a implementar cada aplicación individualmente . Ese es un ejercicio mucho más grande (es decir, más costoso).
fuente