Ofreceré una versión ligeramente diferente de esto. ¡Una biblioteca central, en muchos casos, es una excelente idea!
Si tiene dos proyectos separados, deben estar en dos depósitos de código separados. Ahora dependen de una funcionalidad común. Consideremos, por ejemplo, las aplicaciones de procesamiento de paquetes. La funcionalidad común puede incluir:
- Asignadores de memoria
- Protocolo de resolucion de DIRECCION
- Árbol AVL
- Código de serialización para protocolos binarios
- Matriz dinámica
- Lista de hash de estilo kernel de Linux con cabeza unida individualmente y nodos medios doblemente vinculados
- Tabla de picadillo
- Código de procesamiento de encabezado TCP / IP
- Lista regular vinculada con cabeza doblemente vinculada y nodos medios doblemente vinculados
- Biblioteca de registro
- Varios (confía en mí, ¡necesitas esto para cosas pequeñas y triviales o tu número de módulos diferentes será tan grande como 100!)
- Biblioteca de captura de paquetes
- Biblioteca de interfaz de E / S de paquetes
- Estructura de paquete de datos
- Bloqueo de cola para comunicación entre subprocesos
- Generadores de números aleatorios
- Árbol rojo-negro
- Algún tipo de implementación de temporizador
Ahora, diferentes aplicaciones de procesamiento de paquetes pueden necesitar un subconjunto diferente de estos. ¿Debería implementar una biblioteca central con un repositorio de código fuente, o debería tener 18 repositorios diferentes para cada uno de estos módulos? Recuerde que estos módulos pueden tener interdependencias, por lo que la mayoría de estos módulos pueden depender, por ejemplo, del módulo misceláneo.
Afirmaré que tener una biblioteca central es el mejor enfoque. Reduce la sobrecarga de muchos repositorios de código fuente. Reduce el infierno de dependencias: una versión particular de los asignadores de memoria puede necesitar una versión particular de un módulo misceláneo. ¿Y si desea que la versión 1.7 del asignador de memoria dependa de varios 2.5 y la versión 1.2 del árbol AVL según varios 2.6? Es posible que no pueda vincular varios 2.5 y 2.6 varios al mismo tiempo a su programa.
Entonces, adelante e implemente la siguiente estructura:
- Repositorio de la biblioteca principal
- Proyecto # 1 repositorio
- Proyecto # 2 repositorio
- ...
- Proyecto #N repositorio
He visto que cambiar a este tipo de estructura desde la estructura:
- Proyecto # 1 repositorio
- Proyecto # 2 repositorio
- ...
- Proyecto #N repositorio
Ha llevado a un mantenimiento reducido y a un mayor intercambio de código a través de mecanismos sin copia.
También he visto proyectos que utilizan la siguiente estructura:
- Repositorio de asignadores de memoria
- Depósito de protocolos de resolución de direcciones
- Repositorio de árboles AVL
- Código de serialización para repositorio de protocolos binarios
- Repositorio de matriz dinámica
- Lista de hash de estilo kernel de Linux con cabecera individualmente vinculada y repositorio de nodos medios doblemente vinculados
- Repositorio de tablas hash
- Repositorio de código de procesamiento de encabezado TCP / IP
- Lista vinculada regular con cabecera doblemente vinculada y repositorio de nodos medios doblemente vinculado
- Registro de repositorio de la biblioteca
- Repositorio misceláneo (confía en mí, ¡necesitas esto para cosas pequeñas y triviales o tu número de módulos diferentes será tan grande como 100!)
- Repositorio de la biblioteca de captura de paquetes
- Repositorio de biblioteca de interfaz de E / S de paquetes
- Repositorio de estructura de datos de paquetes
- Cola de bloqueo para repositorio de comunicación entre subprocesos
- Repositorio de generadores de números aleatorios
- Repositorio de árboles rojo-negro
- Algún tipo de repositorio de implementación de temporizador
- Proyecto # 1 repositorio
- Proyecto # 2 repositorio
- ...
- Proyecto #N repositorio
... y el infierno de dependencia y la proliferación de números de repositorio han sido problemas genuinos.
Ahora, ¿debería usar una biblioteca de código abierto existente en lugar de escribir la suya propia? Necesitas considerar:
- Problemas de licencia. A veces, el mero requisito de dar crédito al autor en la documentación proporcionada puede ser demasiado, ya que 20 bibliotecas generalmente tendrán 20 autores distintos.
- Soporte de versión de sistema operativo diferente
- Dependencias de la biblioteca particular.
- Tamaño de la biblioteca particular: ¿es demasiado grande para la funcionalidad proporcionada? ¿Proporciona demasiadas funciones?
- ¿Es posible la vinculación estática? ¿Es deseable la vinculación dinámica?
- ¿Es la interfaz de la biblioteca lo que quieres? Tenga en cuenta que en algunos casos escribir un contenedor para proporcionar la interfaz deseada puede ser más fácil que reescribir el componente completo usted mismo.
- ... y muchas, muchas otras cosas que no he mencionado en esta lista
Usualmente uso la regla de que todo lo que esté por debajo de 1000 líneas de código que no requiera algo más allá de la experiencia del programador debe implementarse por su cuenta. Nota: las 1000 líneas incluyen pruebas unitarias. Por lo tanto, no recomendaré escribir 1000 líneas de código por su cuenta si requiere 10 000 líneas adicionales para las pruebas unitarias. Para mis programas de procesamiento de paquetes, esto significa que los únicos componentes externos que he usado son:
- Todo lo que proporciona una distribución estándar de Linux, porque hay tantas líneas de código que no tiene sentido volver a implementar Linux. Parte de la reimplementación de Linux también estaría más allá de mi nivel de experiencia.
- Bison / flex porque el análisis LALR está más allá de mi nivel de experiencia y más de 1000 líneas de código. Ciertamente podría escribir un analizador de descenso recursivo por mi cuenta, pero Bison / flex son tan útiles que los veo útiles.
- Netmap, porque tiene más de 1000 líneas y más allá de mi nivel de experiencia
- Implementación de temporizador basada en lista de omisión de DPDK, porque está más allá de mi nivel de experiencia, aunque es inferior a 1000 líneas de código (aunque tengo implementaciones de temporizador alternativas que no usan listas de omisión)
Algunas cosas que he implementado por mi cuenta porque son simples incluyen incluso cosas como:
- MurMurHash
- SipHash
- Mersenne Twister
... porque las implementaciones personalizadas de estos pueden permitir una gran alineación, lo que lleva a un rendimiento mejorado.
No hago criptografía; si lo hiciera, agregaría algún tipo de biblioteca criptográfica en la lista, ya que escribir algoritmos criptográficos por su cuenta puede ser susceptible a ataques de temporización de caché, incluso si puede con pruebas exhaustivas de la unidad, demuestre que son compatibles con los algoritmos oficiales.