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:
- 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
.DLL
solo por un poquito de código? - 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.common
que 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.
fuente
Respuestas:
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 empresarialesFramework.Logging
- Sistema de registro unificadoFramework.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.Data
y solo unos pocos lo necesitaránFramework.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.
fuente
IPAddressToString
es 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 hacerloFramework.Strings
.Framework.Logging.Gibraltar
es un complemento particular para el sistema de registro.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:
fuente
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.
fuente
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.
fuente
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.
fuente
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.
fuente
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.
fuente
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.
fuente
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
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 .
fuente
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.
fuente
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.
fuente
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 !!)
fuente