¿Por qué desarrollar bibliotecas internas para aplicaciones internas?

10

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.

Andrew Murtagh
fuente
Posible duplicado de dividir un solo proyecto en bibliotecas
mosquito

Respuestas:

25

Existen numerosas razones para crear bibliotecas y bibliotecas compartidas (en archivos .dll o .so) incluso para uso interno:

  1. La reutilización en proyectos es mucho más limpia
  2. Separación de responsabilidades: parte de su código puede ser más adecuado para diferentes desarrolladores o equipos
  3. Puede beneficiarse de las mejoras en las bibliotecas que hacen otros equipos sin tener que localizar el código específico
  4. Tiempos de compilación más rápidos, si la biblioteca es estable, no necesita reconstrucción.
  5. Espacio en disco: puede tener solo la biblioteca y los encabezados en el proyecto
  6. Si usa bibliotecas compartidas, puede ahorrar memoria con solo una copia cargada en la RAM, incluso si varios programas la están usando
  7. Generalmente terminas con una mejor documentación y pruebas de las bibliotecas
  8. Diseño y código más limpios: pensar en estructurar cosas en bibliotecas debería dar como resultado grupos relacionados de funcionalidad en cada biblioteca y se tiende a separar el código genérico, en las bibliotecas , de los detalles de la aplicación, en la aplicación .
  9. Si tiene algoritmos patentados en bibliotecas, puede restringir el acceso a la fuente, por ejemplo, no permitir que los contratistas o equipos externos accedan a la fuente.
  10. El código de la biblioteca se puede colocar bajo una licencia diferente a la Aplicación de la que se escribió originalmente, algunas empresas incluso han sido conocidas por las bibliotecas de código abierto de las que están orgullosas, ganando grandes elogios en la comunidad de código abierto y en ocasiones contribuyeron mejoras importantes. espalda.

Algunas compañías incluso tienen una práctica contable donde los proyectos que crean bibliotecas obtienen algún reembolso por cada reutilización.

Steve Barnes
fuente
1
O en una variación del punto 9, puede liberar la biblioteca con una licencia diferente que el código de la aplicación principal.
Michael Borgwardt
@MichaelBorgwardt: un buen punto que indica el punto 10 anterior.
Steve Barnes
Además, tener algo de código como una biblioteca separada ayuda a evitar accesos directos durante la programación, como "Agregaré este parámetro adicional aquí ..." y ayuda a encontrar mejores formas de implementar las funciones requeridas.
Valdas
11

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 .

Ben Cottrell
fuente
3
@downvoter: ¿podría explicar el motivo del voto negativo? La retroalimentación sobre las respuestas es útil para mejorar la calidad de este sitio para todos.
Ben Cottrell
4

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).

Doc Brown
fuente
Es cierto que me refería a una biblioteca de código fuente que es común a múltiples proyectos en los que solo hace referencia a los archivos que necesita a través de la típica directiva #include: no conocía el término hasta que lo dijo y editaré el pregunta ahora Su respuesta vinculada también es muy útil.
Andrew Murtagh el
@ AndrewMurtagh: el hecho de que aceptaras tan rápido la respuesta de MichaelBorgwardt me sorprendió, porque lo que escribió parece ser un malentendido de él o mío.
Doc Brown
bueno, él aclaró la confusión inicial que tenía acerca de cuándo agrupar código que sería común a múltiples proyectos en un solo paquete (ya sea en bibliotecas binarias o bibliotecas de código fuente) pero concedido, estaba hablando de tener un solo directorio de fuente código que podría compartirse entre proyectos y no copiar y pegar cada archivo en cada proyecto, ya que podría necesitarlos.
Andrew Murtagh el
2

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:

  1. Tiempo / energía gastada en considerar casos de uso "generales"
  2. Tiempo dedicado a hacer que la "biblioteca" sea distribuible a su "cliente" (su propio código)
  3. Presión futura para hacer uso de la "biblioteca" incluso si no coincide completamente con el próximo caso de uso

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.

Sam
fuente
2
He visto casi exactamente las mismas razones utilizadas por algunos desarrolladores como por qué su código está todo en un solo archivo fuente de línea> 20k. Cuando se combina con nombres peculiares y comentarios pobres, pronto tiene un código que es más rápido reescribir que mantener.
Steve Barnes
Gran punto: ciertamente no estoy argumentando en contra de escribir código legible y fácil de mantener. Los archivos separados, los métodos / clases bien nombrados y la estructura del paquete son componentes importantes de mantenimiento. Mi punto es solo que los costos de escribir + distribuir una biblioteca son elevados cuando solo hay un caso de uso para la "biblioteca".
Sam
1
Por el contrario, no estoy argumentando que necesariamente necesite empaquetar y distribuir una biblioteca en todos los casos, solo que escribir y estructurar como si su código algún día se convirtiera en una biblioteca generalmente vale un poco de esfuerzo y a menudo paga dividendos incluso si el código nunca se convierte distribuido como una biblioteca.
Steve Barnes
1

¿por qué debería desarrollarse 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?

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?

Michael Borgwardt
fuente
1
Entonces, según tengo entendido, la razón principal para convertir un fragmento de código en una biblioteca es cuando se va a usar en diferentes proyectos (incluso si están todos desarrollados internamente) para que ese código no se duplique, actualice y mantenga ¿por separado? Y si solo va a desarrollar un solo proyecto, entonces no hay necesidad de convertir algo en una biblioteca (a menos que tenga la intención de usarlo en otros proyectos en una fecha posterior).
Andrew Murtagh
@ AndrewMurtagh: Sí, así es exactamente como lo diría. Aunque puede haber razones técnicas también; No estoy tan familiarizado con el desarrollo de C / C ++: ¿tal vez es necesario mantener parte del código como biblioteca para que pueda cargarse opcionalmente o incluso cargarse y descargarse a pedido y, por lo tanto, reducir el uso de memoria cuando no se necesita la funcionalidad?
Michael Borgwardt
Creo que eso puede ser posible a través de bibliotecas compartidas. Gracias por aclarar, marcaré su respuesta como aceptada.
Andrew Murtagh el
Casi todos los VCS de la última década admiten referencias externas o submódulos. Esto eliminó el código duplicado y el problema de corrección de errores. Podría incluir más información sobre por qué estas no son una solución viable si aún cree que son problemas válidos.
Sirisian
Piense también en mantenimiento. 1) La lib se puede mantener de forma independiente y en paralelo. 2) Es el código fácil de reemplazar. 3) La base de código pequeña es más fácil de administrar para equipos pequeños y más fácil de entender para todos. 4) si el tiempo de comercialización es crítico, preferirá tener compilaciones más rápidas. El código en libs es un código que no compila una y otra vez en la tubería (IMO). 5) Es un código confiable reutilizable ... Lo hiciste ;-)
Laiv
1

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" Aque es utilizada por una aplicación y un probador de unidades. Cada vez que agrega un cpp A, 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 si Bcambia para usar otra biblioteca? Tendrá que eliminar los cpps de Aen todos los proyectos dependiendo solo de B.

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.

Ead
fuente
0

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?

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).

Phill W.
fuente