Al igual que el autor de esta pregunta de 2012 y esta de 2013 , tengo una biblioteca de terceros que necesito envolver para probar correctamente mi aplicación. La respuesta principal dice:
Siempre desea envolver tipos y métodos de terceros detrás de una interfaz. Esto puede ser tedioso y doloroso. A veces puedes escribir un generador de código o usar una herramienta para hacer esto.
En mi caso, la biblioteca es para un modelo de objetos y, en consecuencia, tiene una mayor cantidad de clases y métodos que tendrían que ajustarse para que esta estrategia tenga éxito. Más allá de simplemente "tedioso y doloroso", esto se convierte en una barrera difícil para las pruebas.
En los 4 años transcurridos desde esta pregunta, soy consciente de que los marcos de aislamiento han recorrido un largo camino. Mi pregunta es: ¿existe ahora una forma más simple de lograr el efecto de envoltura completa de bibliotecas de terceros? ¿Cómo puedo eliminar el dolor de este proceso y reducir el esfuerzo manual?
Mi pregunta no es un duplicado de las preguntas a las que inicialmente me vinculé, ya que mi pregunta es sobre la reducción del esfuerzo manual de envolver. Esas otras preguntas solo preguntan si la envoltura tiene sentido, no cómo el esfuerzo puede mantenerse pequeño.
fuente
Respuestas:
Suponiendo que no está buscando un marco burlón, ya que son ultra ubicuos y fáciles de encontrar , hay algunas cosas que vale la pena señalar por adelantado:
No siempre es mejor concluir una biblioteca de terceros. Si su aplicación depende intrínsecamente de una biblioteca, o si está literalmente construida alrededor de una o dos bibliotecas principales, no pierda el tiempo terminando. Si las bibliotecas cambian, su aplicación deberá cambiar de todos modos.
Esto es especialmente cierto alrededor de límites que son estables, intrínsecos a su aplicación o que no se pueden burlar fácilmente. Si se cumplen esas condiciones, envolver y burlarse será complicado y tedioso. En ese caso, evitaría ambos: no envuelva y no se burle; solo escribe pruebas de integración. (Si las pruebas automatizadas son un objetivo).
En principio, una herramienta solo puede reducir las repeticiones. Pero no existe un algoritmo automatizado para tomar una interfaz compleja y simplificarla, y mucho menos tomar la interfaz X y adaptarla a sus necesidades. (¡Solo usted conoce ese algoritmo!) Por lo tanto, si bien existen indudablemente herramientas que pueden generar envoltorios delgados, sugeriría que aún no son ubicuas porque, al final, todavía necesita codificar de manera inteligente y, por lo tanto, manualmente. contra la interfaz incluso si está oculto detrás de un contenedor.
Dicho esto, hay tácticas que puedes usar en muchos idiomas para evitar referirte directamente a una clase. Y en algunos casos, puede "fingir" una interfaz o envoltura delgada que en realidad no existe. En C #, por ejemplo, iría a una de dos rutas:
Puede evitar el esfuerzo de envolver completamente una clase compleja con este pequeño combo:
Si puede evitar almacenar estos objetos como miembros, ya sea a través de un enfoque más "funcional" o almacenándolos en un diccionario (o lo que sea ), este enfoque tiene el beneficio de la verificación de tipos en tiempo de compilación sin que sus entidades comerciales centrales necesiten saber exactamente con qué clase están trabajando.
Todo lo que se requiere es que, en el momento de la compilación, la clase devuelta por su fábrica tenga los métodos que está utilizando su objeto comercial.
Esto está en la misma línea que usar el tipeo implícito , pero implica otra compensación: pierde las comprobaciones de tipo de compilación y obtiene la capacidad de agregar anónimamente dependencias externas como miembros de la clase e inyectar sus dependencias.
Con estas dos tácticas, cuando llega el momento de burlarse
ExternalPDFLibraryDocument
, como dije antes, tienes algo de trabajo que hacer, pero es un trabajo que deberías hacer de todos modos . Y, con esta construcción, ha evitado tediosamente definir cientos de clases de envoltorios pequeños y delgados. Simplemente ha utilizado la biblioteca sin mirarla directamente, en su mayor parte.Dicho todo esto, hay tres grandes razones por las que aún consideraría concluir explícitamente una biblioteca de terceros, ninguna de las cuales sugiere un uso de una herramienta o marco:
Si no tengo un nivel de preocupación en las tres áreas, no hagas ningún esfuerzo significativo para terminarlo. Y, si tiene alguna preocupación en las tres áreas, un envoltorio delgado generado automáticamente no será de gran ayuda.
Si ha decidido cerrar una biblioteca, el uso más eficiente y efectivo de su tiempo es construir su aplicación contra la interfaz que desee ; no contra una API existente.
Dicho de otra manera, preste atención al consejo clásico: posponga cada decisión que pueda. Cree primero el "núcleo" de su aplicación. Código contra interfaces que eventualmente harán lo que desea, que eventualmente se cumplirá con "cosas periféricas" que aún no existen. Cerrar las brechas según sea necesario.
Este esfuerzo puede no parecer un ahorro de tiempo; pero si siente que necesita un envoltorio, esta es la forma más eficiente de hacerlo de manera segura.
Piénsalo de esta manera.
Debe codificar contra esta biblioteca en algún rincón oscuro de su código, incluso si está envuelto. Si te burlas de la biblioteca durante las pruebas, hay un esfuerzo manual inevitable allí, incluso si está envuelto. Pero eso no significa que deba reconocer directamente esa biblioteca por su nombre en la mayor parte de su aplicación.
TLDR
Si vale la pena envolver la biblioteca, use tácticas para evitar referencias directas y generalizadas a su biblioteca de terceros, pero no tome atajos para generar envoltorios delgados. Desarrolle su lógica de negocios primero, sea deliberado sobre sus interfaces y haga emerger sus adaptadores orgánicamente, según sea necesario.
Y, si se trata de eso, no tenga miedo de las pruebas de integración. Son un poco más difusos, pero aún ofrecen evidencia de código de trabajo, y todavía se pueden hacer fácilmente para mantener a raya las regresiones.
fuente
No pruebe ese código por unidad. Escriba pruebas de integración en su lugar. En algunos casos, las pruebas unitarias, las burlas, son tediosas y dolorosas. Deshazte de las pruebas unitarias y escribe pruebas de integración que realmente hagan llamadas de proveedores.
Tenga en cuenta que estas pruebas deben ejecutarse después de la implementación como una actividad automatizada posterior a la implementación. No se ejecutan como parte de pruebas unitarias o como parte del proceso de compilación.
A veces, una prueba de integración se ajusta mejor que una prueba unitaria en ciertas partes de su aplicación. Los aros que uno debe seguir para hacer que el código sea "comprobable" a veces puede ser perjudicial.
fuente
Según tengo entendido, esta discusión se centra en las oportunidades para la automatización de la creación de envoltorios en lugar de envolver la idea y la guía de implementación. Trataré de abstraerme de la idea, ya que hay muchas cosas aquí.
Veo que estamos jugando con las tecnologías .NET, por lo tanto, tenemos poderosas capacidades de reflexión en nuestras manos. Puedes considerar:
Creo que dicha automatización puede constituir un punto base, pero no una solución final. Se requerirá la refactorización manual del código ... o, en el peor de los casos, un rediseño, ya que estoy completamente de acuerdo con lo que escribió svidgen:
fuente
Siga estas pautas al crear bibliotecas de contenedor:
fuente