Ventajas de usar archivos .dll sobre la vinculación de archivos .cs a proyectos (para mis propias clases de ayuda genéricas / métodos de extensión)

38

Tengo un proyecto auxiliar que utilizo en todas las aplicaciones que creo. Contiene algunos métodos de extensión y un montón de clases auxiliares genéricas, controles, etc. Actualizo / extiendo el proyecto auxiliar de vez en cuando. Por lo general, son proyectos pequeños y no relacionados, y yo soy la única persona que trabaja en todos ellos.

Intenté dos enfoques para usarlo

  • Agregar archivos .cs directamente (Agregar como enlace) a cada proyecto donde los uso
  • compilarlo como .dll y agregarlo como referencia

Veo algunos beneficios y desventajas de estos enfoques.
El primero:

  • es más simple, porque las clases auxiliares se compilan en el archivo exe, por lo tanto, a menudo puedo proporcionar fácilmente un solo archivo .exe que funcionará bien. Debido a que agrego como enlace, puedo estar bastante seguro de que cada vez que compile cualquier proyecto que use el asistente, los archivos del asistente serán la última versión.
  • es aún más simple, porque puedo separar los archivos, de modo que mis métodos de extensión que funcionan bien en .NET 4.0 se pueden referenciar por separado de los que requieren .NET 4.5, lo que significa que la aplicación en su conjunto puede ejecutarse en .NET 4.0
  • Permite depurar a través del código, con todos los beneficios de puntos de interrupción, etc., etc.
  • no parece ser la "mejor práctica"

El segundo:

  • parece ser el enfoque correcto, pero:
  • requiere que entregue un archivo .dll separado, que por alguna razón es mucho más difícil para los usuarios (tienden a compartir mis programas sin el .dll, que luego se bloquea al inicio)
  • ya que se compila en un solo .dll, requerirá la versión más alta de .NET; muchos de mis usuarios no tienen .NET 4.5 y solo algunos elementos de mi clase auxiliar lo requieren, lo que significa que puedo obligar a algunas personas para actualizar sus sistemas sin motivo
  • También necesito asegurarme de que cada vez que actualizo alguno de mis programas, también entrego el archivo .dll, aunque no sé si se ha cambiado desde la última versión, o no (podría haberlo sido, pero podría bien podría ser la misma versión). No puedo ver una manera simple de determinar eso, sin hacer un seguimiento de la versión del ensamblaje, que es un trabajo adicional. Por ahora, cuando actualizo mis programas, solo entrego exe actualizado, y me gusta mantenerlo pequeño y de bajo perfil.

Entonces, ¿cuál es el beneficio real de usar el archivo .dll aquí? Tenga en cuenta que soy la única persona que edita el código de todas las aplicaciones y los archivos auxiliares.


Además, para aclarar: las aplicaciones suelen ser muy pequeñas, mientras que el código contenido en las clases auxiliares es completamente genérico para todas ellas (algunas simples comparaciones de cadenas, rutas u operaciones XML, etc.)


En realidad, alguien me hizo darme cuenta ahora que hay una tercera opción. Como tengo el código auxiliar en un proyecto separado, puedo agregar este proyecto a las soluciones de cada una de mis aplicaciones separadas, que funciona como 'Agregar como enlace' para archivos individuales, excepto que solo agrego un solo proyecto ... Pero como notó Doc Brown, esto esencialmente significa que .dll deberá agregarse al proyecto de todos modos ...

Otra cosa que está a favor de no usar los archivos dll es la capacidad de depurar activamente a través de la clase auxiliar ...

Bartosz
fuente
3
Tienes razón, e incluso lo estoy haciendo, ya que ayuda en caso de mayores requisitos de .NET ... Pero no me gusta hacerlo ... Un instalador para la aplicación de 40 kb es un poco exagerado :)
Bartosz
3
Bueno, siempre puedes usar algo como Costura , es una herramienta para fusionar archivos DLL. Puede fusionar todas las dependencias al EXE, manteniendo un solo archivo y permitiéndole usar las bibliotecas necesarias. Esto puede automatizarse en el proceso de compilación, por simplicidad.
Kroltan
2
Cuando agrega un proyecto a una solución, aún tiene que implementar la DLL de este proyecto, con todos los inconvenientes que enumeró anteriormente.
Doc Brown
2
@DocBrown - santa mierda, tienes razón :)
Bartosz
1
Vincular archivos .cs o proyectos puede tener otro inconveniente. Si está utilizando estos archivos compartidos en muchos proyectos, y un proyecto requiere un cambio importante en sus bibliotecas compartidas, ahora necesita refactorizar sus otros proyectos. Hacer referencia a dlls lo aísla de eso si no hay razón para que su código requiera la lógica actualizada. He sido parte de equipos de desarrollo que se han encontrado con este problema cuando los proyectos compartidos involucran cosas como la autenticación personalizada. El cliente quiere probar un cambio para una nueva aplicación, y ahora necesita versionar su biblioteca común de alguna manera. Usar dlls hace eso.
Ellesedil

Respuestas:

13

Ya viste la mayoría de los pros y los contras. Usar archivos cs como referencias es, de hecho, más ligero y, a menudo, más fácil de administrar. Sin embargo, recomiendo utilizar este enfoque exclusivamente cuando sus csarchivos son totalmente autónomos y no tienen requisitos especiales de compilación.

Usar archivos DLL separados

  • hará explícitas las dependencias a otras utilidades o bibliotecas (por lo tanto, siempre que no tenga tales dependencias, funcionará bien)

  • le permitirá definir configuraciones de compilación específicas (por ejemplo, si una clase solo funciona en configuración x86, o necesita al menos .NET 4.0, la configuración de compilación del ensamblado hace explícito este requisito).

Entonces, especialmente si tiene muchos componentes autónomos de una sola clase, está bien usar referencias a archivos, pero si tiene componentes que hacen referencia a otros componentes o requisitos de compilación específicos, recomendaría usar DLL.

Para mitigar los problemas con la administración de muchas DLL separadas, puede crear un paquete de instalación o utilizar ILMerge , que puede incrustar un conjunto de ensamblajes en un solo ejecutable. En nuestro entorno, tratamos el problema de manera diferente, utilizando un script de implementación para cada aplicación. Este script se asegura de que todas las DLL necesarias siempre se entreguen a producción cuando se publique una nueva versión de la aplicación.

Doc Brown
fuente
Ok, muchas gracias, así que entiendo correctamente que, siempre que mis clases auxiliares no hagan referencia a ningún otro dlls externo (contenga solo código estándar .NET), no es una abominación simplemente vincularlos.
Bartosz
@Bartosz: no hay DLL de ejercicio, y cada clase auxiliar idealmente no debería usar ninguna otra clase auxiliar, o solo otras clases auxiliares que estén almacenadas en el mismo archivo. Para ser sincero, hasta cierto punto puede gestionar la situación en la que la clase auxiliar A necesita que la clase auxiliar B se almacene en un archivo separado, pero este enfoque no escala bien.
Doc Brown
1
@PeterK. - sí, y lo hice :)
Bartosz
1
@whatsisname: no es que esto no pueda funcionar. Sin embargo, para mí no suena como una solución que simplifique las cosas, más como una que puede causar problemas inesperados ;-)
Doc Brown
1
@Ozkan: en nuestro entorno, es solo la implementación de xcopy en algún recurso compartido de red (con algunos pasos adicionales para hacer una copia de seguridad de la versión anterior y asegurarse de que nadie use el programa actualmente, lo que se logra al intentar cambiar el nombre de la carpeta de implementación primero). Sabe qué dlls implementar porque codificamos la lista de la DLL requerida en el script, sin magia detrás. Esta solución no es perfecta, pero funciona para nosotros en la mayoría de los casos, excepto para programas que son utilizados por docenas de usuarios.
Doc Brown
11

Las DLL son útiles cuando una aplicación es grande y hay partes que requieren actualizaciones, pero no toda la aplicación. Entonces, si está escribiendo MS Word, es útil tener el código de corrección ortográfica en un archivo DLL que se pueda actualizar sin tener que actualizar la totalidad de MS Word. Si lo que está escribiendo es una pequeña aplicación de utilidad (o una serie de aplicaciones independientes que utilizan el mismo código) no hay mucha diferencia si el código está incrustado en la aplicación o no.

dcguest
fuente
2

Lo has resumido más o menos en tu pregunta, solo tengo un par de puntos para agregar.

Mono Options es un gran ejemplo de un paquete NuGet que usa muy bien el primer enfoque.

Alternativamente, si decide usar dlls, puede usar herramientas como Costura para incrustar esa referencia en su ejecutable como un recurso incrustado. Para usarlo solo agregue el Costura.Fodypaquete:

Install-Package Costura.Fody
Justin
fuente
En realidad, hay una cosa más: con el proyecto incrustado o los archivos agregados como enlace, también puede depurar activamente el código a través del archivo auxiliar ...
Bartosz
1
@Bartosz Creo que todavía puede depurar "hasta el final" sin el "archivo auxiliar", siempre que tenga el archivo pdb correcto.
Zack
¡Probé lo de Costura y realmente me gusta!
Bartosz
2

Si un dll es más beneficioso o no depende de varios factores:

  1. El tamaño del código (cuando se compila).
  2. ¿Cuántos ex lo usan?
  3. Con qué frecuencia tiene la intención de actualizar el código.
  4. Si los exes están destinados a mantenerse juntos o no, por separado.

El propósito de una biblioteca compartida es tomar código común a múltiples ejecutables y centralizarlo para que todos los ejecutables compartan una copia. El objetivo es ahorrar espacio y facilitar la actualización del código.

Si la cantidad de código en su clase auxiliar es muy pequeña, puede que no valga la pena moverlo a un archivo dll, ya que la sobrecarga del código que se encuentra en un archivo dll puede contrarrestar el beneficio de ahorro de espacio de tenerlo centralizado.

Además, si solo está haciendo unos pocos ejecutables, el tamaño del código en cada ejecutable puede ser lo suficientemente pequeño como para no ser un problema. Sin embargo, cuantos más ejecutables tenga usando el mismo código, más beneficioso sería mover el código a un archivo dll.

Como ejemplo simplificado, digamos que su clase auxiliar compila a 128 bytes en un archivo exe, pero cuando se mueve a un dll, el dll es de 512 bytes. Si solo tiene 3 ejecutables, estaría ahorrando espacio al incluir el código en los ejecutables. Sin embargo, si tuviera 5 ejecutables, estaría en el punto en el que sería mejor tener un dll porque el espacio combinado ocupado por 5 copias del código (5 * 128 = 640 bytes) es mayor que el espacio ocupado teniendo el código en un dll (512 bytes).

Ahora digamos, por ejemplo, que encuentra un error en su código auxiliar. Si compiló todos sus ejecutables con el código incorporado, debe volver a compilar cada ejecutable y luego redistribuir las versiones recompiladas. Si compila el código en un dll, solo tendrá que volver a compilar y redistribuir el dll, y el error se solucionará automáticamente para todos los ejecutables que lo utilizan.

Por último, para que un programa encuentre un dll tiene que saber dónde buscarlo. Si mantiene todos sus ejecutables juntos, puede colocar el dll en el mismo directorio y todos lo encontrarán de inmediato. Si intencionalmente los mantiene separados, se hace más difícil coordinarlos para usar el mismo dll.

Pharap
fuente
1

Su tercera opción es la más apropiada (agréguela como un proyecto separado de "biblioteca de clases" a la solución). Esto combina los beneficios de todos los enfoques:

  • Su "proyecto de ayuda" siempre está actualizado en todos los proyectos diferentes.
  • Puede hacer referencia al código del proyecto cuando desee ver rápidamente los cambios.
  • Puede compilarlo para la versión correcta de .NET cada vez.
  • Puede incrustar una DLL en un exe de todos modos, así que no se preocupe, puede tener eso como parte de su compilación.

Hacemos esto todo el tiempo y no puedo hacer nada más que recomendar este enfoque.

Otra cuarta alternativa que no ha mencionado es colocarla en un repositorio NuGet privado que le permita versionarla correctamente y hacer referencia a ella sin el proyecto adicional en cada solución.

Benjamin Gruenbaum
fuente
2
Hm, me parece que cuando lo agrego como un proyecto a la solución y luego hago referencia a este proyecto en otros proyectos, todavía se crea como un archivo .dll separado en lugar de estar incrustado ... ¿Hay algo que deba especificar?
Bartosz
1

Como desarrollador, siempre me gusta incluir la referencia de la solución de la utilidad a mi aplicación, ya que me permite depurar el código (¡y detectar posibles errores en la utilidad también!) Además de cualquier cambio realizado en la utilidad se incluye automáticamente en la aplicación.

Entonces, en realidad, la decisión depende de cuán madura sea la utilidad . Si no está seguro acerca de los errores de la Utilidad, siempre debe incluir el archivo .cs de esa utilidad para averiguar los errores. Pero si está seguro de que la Utilidad es lo suficientemente madura y no devolverá el resultado con ningún error. no hay margen de mejora en la Utilidad, puede continuar e incluir el archivo DLL.

saruchi arora
fuente