Las mejores prácticas para compartir pequeños fragmentos de código entre proyectos


102

Siempre trato de seguir el principio DRY estrictamente en el trabajo; cada vez que repito código por flojera, vuelve a aparecer más tarde cuando necesito mantener ese código en dos lugares.

Pero a menudo escribo pequeños métodos (tal vez de 10 a 15 líneas de código) que deben reutilizarse en dos proyectos que no pueden referenciarse entre sí. El método podría tener algo que ver con redes / cadenas / MVVM, etc. y es un método generalmente útil que no es específico del proyecto en el que se encuentra originalmente.

La forma estándar de reutilizar este código sería crear un proyecto independiente para el código reutilizable y hacer referencia a ese proyecto cuando lo necesite. El problema con esto es que terminamos en uno de los dos escenarios menos que ideales:

  1. Terminamos con decenas / cientos de pequeños proyectos, cada uno para albergar las pequeñas clases / métodos que necesitábamos reutilizar. ¿Vale la pena crear un nuevo .DLLsolo por un poquito de código?
  2. Terminamos con un solo proyecto con una colección cada vez mayor de métodos y clases no relacionados. Este enfoque es para lo que hizo una empresa para la que solía trabajar; tenían un proyecto llamado base.commonque tenía carpetas para cosas como las que mencioné anteriormente: redes, manipulación de cadenas, MVVM, etc. Era increíblemente útil, pero hacer referencia a él arrastraba innecesariamente todo el código irrelevante que no necesitabas.

Entonces mi pregunta es:

¿Cómo hace un equipo de software para reutilizar pequeños fragmentos de código entre proyectos?

Me interesa especialmente si alguien ha trabajado en una empresa que tiene políticas en esta área, o que se ha encontrado con este dilema personalmente como yo.


nota: mi uso de las palabras "Proyecto", "Solución" y "Referencia" provienen de un fondo en el desarrollo de .NET en Visual Studio. Pero estoy seguro de que este problema es independiente del idioma y la plataforma.


21
+1, aunque creo que hay un elemento de humor en alguien que trabaja con .NET preocupado por arrastrar código irrelevante a través de una referencia DLL.
JDB

2
¡@ColeJohnson .NET en sí ES una gran referencia! Probablemente mucho más grande que los dlls que haría yo mismo.
George Powell el

2
Lo entiendo. Sin embargo, el compilador JIT de .NET solo carga los métodos necesarios en la RAM (cuando se los llama)
Cole Johnson

1
Cierto. Aunque todavía tiene que distribuir todo el .NET Framework a cualquiera que quiera usar su producto, y los grandes proyectos y las soluciones complejas son más difíciles de administrar.
George Powell

Respuestas:


75

Si realmente son métodos / clases reutilizables, puede escribirlos en un pequeño número de bibliotecas de 'Swiss Army Knife'. Hacemos esto con bastante frecuencia en mi empresa; los llamamos bibliotecas marco:

  • Framework.Data - Utilidades para trabajar con consultas de bases de datos.
  • Framework.ESB - Métodos estándar para interactuar con nuestro bus de servicios empresariales
  • Framework.Logging - Sistema de registro unificado
  • Framework.Services - Utilidades para interactuar con los servicios web.
  • Framework.Strings - Utilidades para manipulación avanzada de cadenas / búsqueda difusa de cadenas, etc.
  • ...

En total, hay alrededor de una docena de bibliotecas. Realmente puede distribuir el código como mejor le parezca, por lo que no tiene que terminar con cientos o volcar todo en un conjunto gigante. Creo que este enfoque se ajusta porque solo algunos de nuestros proyectos necesitarán Framework.Datay solo unos pocos lo necesitarán Framework.Strings, por lo que los consumidores pueden seleccionar solo aquellas partes del marco que sean relevantes para su proyecto en particular.

Si en realidad son solo fragmentos, y no métodos / clases reales que pueden reutilizarse fácilmente, puede intentar distribuirlos como fragmentos de código en el IDE (por ejemplo, fragmentos de código de Visual Studio ). Los equipos con los que he trabajado en el pasado tenían una biblioteca de fragmentos común que facilitaba a todos seguir nuestras prácticas de codificación estándar con código interno también.


44
+1 Este también sería mi enfoque. Interesado en saber cómo decidió dónde colocar el código que se ocupa de cosas de dos o más aspectos. Por ejemplo IPAddressToString. Y si permite que estas bibliotecas se usen entre sí. Por ejemplo, los servicios y los datos probablemente puedan beneficiarse mucho del registro ...
Marjan Venema

55
@MarjanVenema Para el código transversal, depende de qué consumidores encontrarán el método más útil. Porque IPAddressToStringes probable que los consumidores que trabajan con protocolos de red tengan que usar eso, pero los consumidores que juegan mucho con las cadenas pueden no preocuparse realmente por las direcciones IP. Eso probablemente terminaría en un paquete de red en lugar de hacerlo Framework.Strings.
pswg

@MarjanVenema Intentamos evitar las interdependencias. Nuestros servicios y marcos de datos están escritos de tal manera que no hacen ningún registro por sí mismos, pero hacen que sea más fácil para el consumidor escribir el código de registro adecuado. Las bibliotecas de framework pueden hacer referencia entre sí, pero solo por extensión, por ejemplo, Framework.Logging.Gibraltares un complemento particular para el sistema de registro.
pswg

55
+1 Puede tomar estas bibliotecas de marco e implementarlas en un repositorio interno de NuGet (tan simple como una carpeta de red) y tiene una buena manera de administrarlo.
Steven Evers

2
@SteveEvers Estoy trabajando en este momento para configurar eso. : P
pswg

21

No estoy de acuerdo con la respuesta aceptada por muchas razones.

En mi experiencia, cuando veo bibliotecas "misceláneas" como la respuesta aceptada, son una excusa para reinventar la rueda (o no inventada aquí (NIH) ), un pecado mucho mayor que violar No te repitas (DRY) .

A veces, violar DRY puede ser un compromiso razonable, es mejor que introducir un acoplamiento apretado. La reutilización es una preocupación secundaria en comparación con un buen diseño orientado a objetos. Un poco (me refiero a una pequeña cantidad, aplique la regla de tres ) de duplicación es más fácil de entender que una base de código de espagueti.

El enfoque de numerosas bibliotecas de propósito general es un mal ejemplo. Conduce a una granularidad fina de ensamblaje y demasiados ensamblajes es malo. Recientemente reduje un interno de 24 bibliotecas a 6 bibliotecas. Mejoró el tiempo de compilación de varios minutos a ~ 20 segundos. Visual Studio también es más lento de cargar y menos receptivo con más ensamblajes. Tener demasiadas bibliotecas también genera confusión sobre dónde debería vivir el código; Prefiero menos reglas más simples.

¿Por qué las cosas en .Net Framework no son lo suficientemente buenas? El marco es bastante grande; Muchas veces he visto código que vuelve a implementar cosas que ya existen allí. Realmente asegúrese de que sus marcos estén llenando vacíos en el marco .Net y no existan solo por razones estéticas (por ejemplo, "No me gusta el marco .Net aquí" o tal vez alguna optimización prematura )

Introducir otra capa en su arquitectura tiene un costo de complejidad significativo. ¿Por qué existe la capa? He visto una reutilización falsa, con eso quiero decir que el código está construido sobre un marco interno. Hubiera sido mucho más eficiente implementarlo directamente sobre las bibliotecas estándar.

El uso de tecnologías estandarizadas (como el marco .Net y las bibliotecas populares de terceros / de código abierto) tienen beneficios que a menudo superan las ganancias tecnológicas comparativas de construirlo usted mismo. Es más fácil encontrar talento que conozca estas tecnologías y sus desarrolladores existentes invertirán más en aprenderlo.

Mis recomendaciones:

  • No compartir este código.
  • Cree una nueva biblioteca si tiene un propósito coherente, no use el patrón de diseño de bola de barro .
  • Reutilice las bibliotecas de terceros existentes donde sea posible.
  • Prefiere menos ensamblajes, con reglas más simples sobre dónde debería vivir el código.

1
Un beneficio adicional al usar bibliotecas de código abierto donde esté disponible; si encuentra algunas mejoras, puede compartirlas con la comunidad. Por ejemplo, con .Net MS publicó una EnterpriseLibrary (ahora de código abierto) que ofrece un conjunto bastante bueno de herramientas para escenarios comunes, encuentre algo que se pueda mejorar y ¡listo! ¡Todos se benefician!
glenatron

2
Realmente no veo un desacuerdo con la respuesta aceptada aquí :-). "menos conjuntos, con reglas más simples sobre dónde debería vivir el código" no es una contradicción con la respuesta aceptada. La respuesta también recomienda utilizar solo tantas asambleas diferentes como parezca razonable.
sleske

Cinco años después, la orientación del microservicio también convergió en esta práctica: medium.com/standard-bank/…
Dave Hillier

11

Para pequeños fragmentos de código, digamos una sola clase sin dependencias, tendemos a copiar y pegar el código en los proyectos. Esto suena como una violación de DRY, y admito que puede ser a veces. Pero a largo plazo ha sido mucho mejor que tener algún tipo de proyecto de bienes comunes masivo y con múltiples cabezas por varias razones.

Primero, es más simple tener el código a mano, especialmente al construir y depurar cosas.

En segundo lugar, siempre querrás hacer algunos pequeños ajustes al código común para ese proyecto. Si tiene una copia local de la fuente, puede hacer el ajuste y llamarlo por día. Si hay una biblioteca compartida, entonces podría estar ajustando esa biblioteca y luego asegurándose de no romper todas las otras aplicaciones o crear una pesadilla de versiones.

Entonces, si no es lo suficientemente robusto para su propio espacio de nombres, tendemos a empujarlo a los bits apropiados en el proyecto y llamarlo un día.


55
No estoy de acuerdo con este enfoque. Aprecio los problemas de mantenimiento con la administración de pequeños fragmentos de código, pero diría que se podría crear una biblioteca común a partir de todos ellos, como sugiere @psw. Tener copias duplicadas de código con pequeños ajustes es pedir problemas. Se harán suposiciones, se perderán las correcciones de errores.
Andrew T Finnell

2
-1 (a la respuesta). Ciertamente es más fácil que todos tengan sus propias copias de sus propias versiones de programas. Así es como se desarrolló el software en los años 80. Desde entonces he aprendido que, a largo plazo, esto lleva a un desastre. Es más difícil hacer lo correcto y tener una biblioteca común, ya que las personas tendrán que comunicarse mucho más sobre su trabajo. Bueno, deberían.
Michael Durrant

3
+1: creo que vale la pena mencionar este enfoque, incluso si no es uno que quiera usar con mucha frecuencia. Algunos fragmentos son más como patrones de diseño: los reutilizará, pero de forma ligeramente diferente en todas partes, y tal vez en diferentes idiomas, y tal vez desee cambiarlos. Además, una biblioteca ampliamente reutilizada es inflexible ya que los cambios en su API son muy riesgosos. Finalmente, tener este enfoque como alternativa aumenta la calidad de las bibliotecas compartidas al mantener las cosas experimentales fuera de ellas un poco más.
Eamon Nerbonne

6

La segunda solución que describe no es tan mala. En .NET también hace referencia a un ensamblado del GAC incluso si solo usa una sola clase de él. 'Arrastrar código irrelevante' no es un problema como podría pensar. En este caso, es vital al menos mantener los métodos y clases relacionados organizados de manera limpia en diferentes espacios de nombres. Además, se deben aplicar buenas prácticas para el diseño de API para evitar que esta solución se convierta en un desastre.

Si se trata de fragmentos de código muy pequeños, creo que el siguiente enfoque es un buen complemento para un proyecto común: permitir que se dupliquen en diferentes soluciones. Trátelos como mejores prácticas: documente y comuníquelos al equipo.


1
Excepto que para las bibliotecas no estándar, esto significa que tendrá que enviar un ensamblaje grande solo por un solo uso (o pocos). Esto no es un problema para las cosas estándar, ya que está disponible de todos modos, pero definitivamente evitaría enviar ensamblajes grandes pero en su mayoría no utilizados si puede dividirlo de una buena manera.
meter

6

Solo he trabajado en entornos "empresariales" donde este tipo de cosas ha sido un problema y cada vez ha sido la segunda opción que se ha adoptado. En su mayor parte, funcionó bien porque no ha habido ninguna restricción en la huella de la aplicación.

Sin embargo, después de pasar la última semana con una startup que ejecuta su propio servidor Nuget, me inclino a sugerir esto como una alternativa viable. Por supuesto, los problemas que espero surjan estarán relacionados con la capacidad de descubrir.

Si los proyectos son adecuadamente granulares y los espacios de nombres son razonables, entonces puedo ver que esto se convierta en un enfoque popular en algunos lugares.


¿En qué sentido espera que no sean reconocibles? Utilizamos una cantidad grande y creciente de paquetes nuget de esa manera. El mayor problema que tenemos es con la administración de versiones y dependencias.
pdr

Ah, sí. Esos tambien. Por cuestiones relacionadas con la capacidad de descubrimiento me refiero a que dado un número suficiente de pequeños paquetes con una función específica, tal vez sea más difícil catalogar (y encontrar) cada uno. Por ejemplo, ¿cómo hace saber su equipo qué paquetes contienen varias funciones? (mostrando ignorancia de búsqueda nuget aquí)
Kofi Sarfo

Oh ya veo. Sí, definitivamente puedes poner lo que quieras en la descripción y eso se puede buscar, pero creo que hemos agrupado los paquetes lo suficientemente bien como para que no parezca un problema.
pdr

@sarfeast Sería bueno si pudieras compartir un enlace a cualquier servidor Nuget y contar un poco al respecto.
Hans-Peter Störr

6

Recientemente pensé en esto y lo que se me ocurrió fue una gran biblioteca de métodos comunes como se ha mencionado hasta ahora, pero con un giro. El proyecto de biblioteca le permitiría configurar en tiempo de compilación qué piezas se incluyen como el proyecto BusyBox . Con ese enfoque, puede tener un repositorio de biblioteca de estilo de fregadero de cocina, pero solo tome las herramientas que necesita al compilar.


5

GitHub tiene una herramienta bastante útil para guardar fragmentos de código https://gist.github.com/

Almacena tus fragmentos como repositorios git que puedes mantener en privado o usar para compartir fragmentos con otras personas.


3

Dependiendo del tamaño del equipo / proyecto / empresa, esto será bastante difícil de hacer de manera eficiente, a menos que ya esté integrado en su entorno de alguna manera, y cada solución que encuentre (si la implementa) costará algo de dinero. (Puede protegerlo más, pero no podrá medirlo fácilmente). Tendrás que comprobar si vale la pena el precio. Recuerde también que las soluciones reutilizables tienden a volverse abstractas y, a menudo, se ajustan a muchas situaciones, pero sin ser óptimas.

En cualquier caso, si desea hacer esto para el código producido por más de una persona, al principio necesitará conciencia de todos y cooperación. Esto incluye desarrolladores y gerentes.

Luego, deberá asegurarse de conocer el alcance en el que desea hacer esto. ¿Equipo? ¿Proyecto? ¿Departamento? ¿Empresa? Dependiendo de la respuesta, el tipo de código que colocará en dichas soluciones variará, al igual que la granularidad con la que adapta los dlls. Una vez que te hayas decidido por esto, alguien (preferiblemente con algo de entusiasmo por la idea, ¿tú?) Debería sentarse y comenzar a poner algo de estructura en esto.

Sin embargo, solo crear tales dlls no será suficiente para hacer el truco. Para que sean útiles, deberá anunciarlos (a usuarios y colaboradores) y mantenerlos como cualquier otra pieza de software, lo que generalmente significa que debe poner a alguien a cargo de ellos durante mucho tiempo. También necesitará documentación confiable, que luego también necesitará mantenimiento. Con un poco de suerte y cooperación, puede terminar con algunas mejores prácticas, pero también puede evolucionar fácilmente en un proyecto propio, dependiendo del tamaño y la cantidad de equipos involucrados. Y para eso aún necesitará soporte de administración.


3

Me he encontrado con muchos problemas, y mi solución preferida es publicar el código en un repositorio web github / pubic habilitado. resuelve muchos problemas

  1. Fácil acceso y fácil de compartir. cvs / svn / enterprise-repos significa verificar el proyecto en múltiples espacios de trabajo IDE, y a veces tener que cambiar espacios de trabajo o computadoras solo para referirse a un pequeño fragmento de código.
  2. Suponiendo que estos fragmentos de código no son fragmentos de código propietarios / clasificados y son variaciones del conocimiento disponible públicamente, publicarlos en un repositorio público como Github significa que otros lo verán e incluso podrían contribuir.
  3. publicar algo en el dominio público bajo su nombre tiene la presión adicional de la reputación. verificará y actualizará las cosas, ya que se refleja en sus habilidades como programador.
  4. actualizaciones Lo importante de mantener fragmentos de código en un repositorio es que si un fragmento no se ha utilizado durante mucho tiempo, podría quedar obsoleto (contener apis / libs obsoletos). ejemplo: fragmento de código de Java para leer un archivo. Es posible que haya descubierto la mejor manera de hacer esto en 2009, pero en 2014 sale una nueva API de archivo que lo cambia todo. tu fragmento? todavía estancado en 2009. en un repositorio público, las cosas se actualizarán, ya sea por usted (debido a la viñeta 3), sus compañeros de equipo o algún miembro de la población general de programadores, y en el proceso, incluso podría recibir sugerencias para arreglar algo que podrías haber estado haciendo mal durante mucho tiempo.

Una cosa que recomendaría: no importa dónde guarde sus fragmentos, siempre busque en Google antes de usarlo. Las cosas cambian todo el tiempo. los fragmentos guardados ahorran tiempo, pero también generan complacencia .


2

Tenemos un proyecto separado "utilidades" donde almacenamos todos estos pequeños métodos junto con las pruebas.

Cuando un proyecto necesita alguna utilidad, simplemente agrega el archivo fuente con el método requerido con "agregar como enlace".

Esto significa que no se agregan dependencias de tiempo de ejecución (a menos que el archivo incluido lo necesite).

El sistema ha funcionado bien pero, como todos los demás, necesita diciplin sobre lo que es una utilidad. Requerir una cobertura de prueba alta nos ha funcionado bien y las pruebas también son una buena documentación de uso. El descubrimiento sigue siendo un problema sin resolver para nosotros.

Una complejidad con el proyecto de utilidad es decidir el nivel de visibilidad de los artículos. Una regla general es que los métodos deben ser internos y las estructuras de datos públicas.


2

Mi empresa utiliza servicios web locales intranet. Tenemos algunos servicios web que se configuran como servicios web internos comunes, y cuando otro proyecto necesita acceso a uno de los servicios, envía una solicitud http con una interfaz definida. Dado que está en la intranet, alojada en la misma granja de servidores, estas solicitudes son muy rápidas.

Obviamente, esto solo funciona con aplicaciones de Internet (y solo funciona en milisegundos cuando está en la misma red local), pero tiene algunas ventajas realmente buenas.


0

Recientemente se me ocurrió este servicio: Snip2Code ( http://www.snip2code.com ).

Es una forma interesante de compartir solo sus fragmentos (no del todo bibliotecas) con su equipo. Rompe el punto habitual para crear bibliotecas comunes a las que se debe hacer referencia en otros proyectos, y en mi opinión, esta es una visión valiosa.

Además, hay muchos escenarios en los que el uso de una biblioteca común simplemente no se aplica: consideremos, por ejemplo, algunos patrones de diseño como Singleton, Strategy u Observer. Puede crear bibliotecas para admitir dichos patrones, pero aún así no hay una cobertura del 100%.

La verdadera necesidad es tener una herramienta para compartir prácticas comunes entre el equipo. Traté de usar lo esencial de Github, pero estoy atascado con la búsqueda de ellos (realmente pobre) y con el hecho de que no puedo compartirlos solo entre mi equipo y no con otros ...

(Descargo de responsabilidad: soy uno de los fundadores de Snip2Code, y estaba, junto con mis cofundadores, en su misma mentalidad hace algún tiempo: ¡¡es por eso que decidimos comenzar este proyecto !!)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.