Implementando una capa de ocultación de complejidad


8

Como parte de las dependencias que tiene el proyecto en el que estoy trabajando, utilizamos varios servicios básicos. Estos servicios, a los que no podemos hacer grandes cambios, son un gran desastre. Dependiendo del método que invoquemos, necesitamos convertir nuestros parámetros (y valores de retorno) a diferentes codificaciones, configuraciones regionales y zonas horarias.

Como generamos estos parámetros en varios lugares en nuestro propio código, realizamos estas conversiones en varios lugares. Algunas veces donde los generamos, antes de pasarlos a nuestro lado; algunas veces justo antes de invocar el método en el servicio principal. Entonces, el desorden se está extendiendo por todo nuestro código, y quiero introducir una capa para aislarlo.

Mi pregunta es cuál es el mejor enfoque para eso. Inicialmente pensé en crear un servicio / método correspondiente a cada servicio / método que necesitamos usar. Estos métodos simplemente realizarían la conversión, delegarían a los servicios centrales y realizarían la conversión del valor de retorno. Pero esto parece de alguna manera difícil de manejar.

Entonces pensé en usar anotaciones, pero no estoy completamente seguro de cómo usarlas. Y como lo entiendo, idealmente necesitaría anotar el método invocado. Por ejemplo, podría anotar los parámetros con @converToUtc, y hacer la conversión en la implementación de la anotación. ¿Es esto correcto? Por supuesto, esto es difícil porque no es nuestro código y romperá el código actualmente usando esos métodos en proyectos distintos al nuestro.

¿Cuál es el mejor enfoque para esta situación?


66
Un término común para esto es la capa anticorrupción si desea buscarla.
Esben Skov Pedersen

Respuestas:


6

Lo que intenta hacer es implementar el patrón de fachada . Básicamente, desea poner una cara más simple en el código central. Probablemente desee crear un conjunto de clases que proporcionen un mapeo 1: 1 para cada clase principal, luego use las clases de fachada en lugar de las clases principales. Si los servicios principales son solo un montón de métodos en una gran clase monolítica, entonces podría considerar desglosarlos por dominio funcional (por ejemplo, autenticación, acceso a datos, función comercial, etc.) y tener una fachada diferente para cada dominio. Su fachada debe presentar una interfaz que tenga sentido para su código y manejar todos los mapas y la conversión de datos necesarios para comunicarse con los servicios principales.


6

El problema que enfrenta es una instancia de un problema general que enfrentamos con frecuencia en Ingeniería de software: moldear las herramientas para llevarlas a nuestro dominio de problemas específicos mediante capas de abstracción / conversión.

Tienes una aplicación que resuelve un problema. Las entidades que contiene, gestiona e interactúa son entidades que pertenecen al dominio del problema. Todos se expresan en términos que son útiles para resolver el problema en cuestión, y son "amigables" ya que le permiten concentrarse en resolver el problema en lugar de perder tiempo y contaminar su código con conversiones que no tienen nada que ver con problema en mano

Mientras tengas todo el código, todo estará bien; pero cuando incluye herramientas de terceros (bibliotecas) en la imagen, estas herramientas probablemente no se hayan escrito para funcionar dentro de su dominio problemático, por lo que requieren conversiones que a menudo son molestas, engorrosas y propensas a errores.

Lo que suele suceder es que los inconvenientes son menores y simplemente hacemos frente a las herramientas que se nos proporcionan. Pero cuando los inconvenientes son importantes, tanto que hacen que nuestra vida diaria sea considerablemente más difícil o que el resultado final sea más frágil y más propenso a errores, a veces introducimos capas de abstracción / conversión entre nuestro código y las herramientas que utilizamos .

Estas capas de abstracción / conversión ofrecen servicios a nuestro código que se expresan en términos de nuestro dominio problemático y delegan a las herramientas de terceros, realizando todas las conversiones necesarias en el camino. Al hacerlo, estas capas tienden a abstraer lo más posible de las peculiaridades de las herramientas que utilizamos, de modo que, en teoría, podemos reemplazar una herramienta con una herramienta diferente modificando solo las capas de abstracción / conversión, sin Necesitamos modificar nuestra lógica central.

Con respecto a las anotaciones, no veo cómo pueden ayudar aquí. En primer lugar, si no posee el código fuente de las interfaces de destino, no podrá agregarles anotaciones. Pero incluso si de alguna manera pudiera agregar anotaciones a las interfaces de destino, para que las anotaciones funcionen tendría que incrustar una capa intermedia entre su código y las interfaces de destino, que intercepta las llamadas, examina las anotaciones de los métodos de destino y realiza el conversiones necesarias Quizás, podría usar el Spring Framework o algo así como el Interceptor de Castle Proxy Mecanismo para incrustar mágicamente esta capa intermedia entre su código y las bibliotecas, pero me parece que podría escribir fácilmente la capa intermedia de una manera tradicional, teniendo un conocimiento íntimo de las interfaces de destino, realizando las conversiones de forma codificada , de manera sencilla, y también abstrayendo las interfaces de las bibliotecas para satisfacer sus necesidades.


0

En primer lugar, usted (o su equipo) debe acordar un formato "estándar" que utilizará en su propio código. Por ejemplo:

  • Codificación: UTF-8
  • Configuración regional: en_UK
  • Zona horaria: UTC

Solo después, podría escribir una capa que adapte los valores a los formatos solicitados de sus dependencias (no creo que sea difícil de manejar).

Como dijo Mike Nakis, tampoco veo ningún beneficio en usar anotaciones para resolver este problema.

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.