¿Qué es una capa anticorrupción y cómo se usa?

137

Estoy tratando de averiguar qué significa realmente la capa Anticorrupción. Sé que es una forma de transición / trabajo alrededor de códigos heredados o APIs incorrectas. Lo que no entiendo es cómo funciona y qué lo hace una separación limpia de la capa indeseable.

He hecho algunas búsquedas, pero no puedo encontrar ejemplos o explicaciones simples, así que busco a alguien que lo entienda y pueda explicarlo con ejemplos simples. Una respuesta que satisfaga mi pregunta debería ser simple (no necesariamente breve) y proporcionar ejemplos comprensibles de implementación y uso.

Consulte esta pregunta , para mi caso de uso.

    
pregunta knownasilya 22.01.2013 - 17:14
fuente

4 respuestas

137

Imagina que tienes que usar el código de otra persona que está diseñado como se muestra a continuación:

    class Messy {
        String concat(String param, String str) { /* ... */ }
        boolean contains(String param, String s) { /* ... */ }
        boolean isEmpty(String param) { /* ... */ }
        boolean matches(String param, String regex) { /* ... */ }
        boolean startsWith(String param, String prefix) { /* ... */ }
    }

Ahora imagine que descubre que su código que depende de él se parece a lo siguiente:

String process(String param) {
    Messy messy = new Messy();
    if (messy.contains(param, "whatever")) {
        return messy.concat(param, "-contains");
    }
    if (messy.isEmpty(param)) {
        return messy.concat(param, "-empty");
    }
    if (messy.matches(param, "[whatever]")) {
        return messy.concat(param, "-matches");
    }
    if (messy.startsWith(param, "whatever")) {
        return messy.concat(param, "-startsWith");
    }
    return messy.concat(param, "-whatever");
    // WTF do I really need to repeat bloody "param" 9 times above?
}

... y que desea que sea más fácil de usar, en particular, para deshacerse del uso repetitivo de parámetros que simplemente no son necesarios para su aplicación.

Bien, entonces comienzas a construir una capa anticorrupción.

  1. Lo primero es asegurarse de que su "código principal" no se refiera a Messy directamente. Por ejemplo, organiza administración de dependencias de tal manera que al intentar acceder a Messy no se compila.

  2. En segundo lugar, crea un módulo dedicado de "capa" que es el único que accede a Messy y lo expone a su "código principal" de una manera que tenga más sentido para usted.

El código de la capa sería similar al siguiente:

    class Reasonable { // anti-corruption layer
        String param;
        Messy messy = new Messy();
        Reasonable(String param) {
            this.param = param;
        }
        String concat(String str) { return messy.concat(param, str); }
        boolean contains(String s) { return messy.contains(param, s); }
        boolean isEmpty() { return messy.isEmpty(param); }
        boolean matches(String regex) { return messy.matches(param, regex); }
        boolean startsWith(String prefix) { return messy.startsWith(param, prefix); }
    }

Como resultado, su "código principal" no se mete con Messy , en su lugar usa Reasonable , aproximadamente de la siguiente manera:

String process(String param) {
    Reasonable reasonable = new Reasonable(param);
    // single use of "param" above and voila, you're free
    if (reasonable.contains("whatever")) {
        return reasonable.concat("-contains");
    }
    if (reasonable.isEmpty()) {
        return reasonable.concat("-empty");
    }
    if (reasonable.matches("[whatever]")) {
        return reasonable.concat("-matches");
    }
    if (reasonable.startsWith("whatever")) {
        return reasonable.concat("-startsWith");
    }
    return reasonable.concat("-whatever");
}

Tenga en cuenta que todavía hay un poco de lío con Messy , pero ahora está oculto razonablemente dentro de Reasonable , lo que hace que su "código principal" esté razonablemente limpio y libre de daños que podrían producirse mediante el uso directo de Messy stuff.

El ejemplo anterior se basa en cómo se explica Capa Anticorrupción en c2 wiki:

  

Si su aplicación necesita tratar con una base de datos u otra aplicación cuyo modelo no es deseable o no es aplicable al modelo que desea dentro de su propia aplicación, use un AnticorruptionLayer para traducir a / desde ese modelo y el suyo.

El ejemplo de la nota se hace intencionalmente simple y se condensa para mantener una breve explicación.

Si tiene un gran lío de API para cubrir detrás de la capa anticorrupción, se aplica el mismo enfoque: primero, asegúrese de que su "código principal" no acceda a material dañado directamente y segundo, expóngalo de una manera que sea más conveniente en su contexto de uso.

Al "escalar" su capa más allá del ejemplo simplificado anterior, tenga en cuenta que hacer que su API sea conveniente no es necesariamente una tarea trivial. Invierta un a diseñe su capa de la manera correcta , verifique su uso previsto con pruebas unitarias etc.

En otras palabras, asegúrese de que su API sea de hecho una mejora sobre una que oculta, asegúrese de no introducir otra capa de corrupción.

En aras de la integridad, observe la diferencia sutil pero importante entre esto y los patrones relacionados Adaptador y Facade . Como lo indica su nombre, la capa anticorrupción supone que la API subyacente tiene problemas de calidad (está" dañado ") y tiene la intención de ofrecer una protección de los problemas mencionados.

Puede pensarlo de esta manera: si puede justificar que sería mejor que el diseñador de la biblioteca exponga su funcionalidad con Reasonable en lugar de Messy , esto significaría que está trabajando en la capa anticorrupción, haciendo su trabajo , corrigiendo sus errores de diseño.

A diferencia de eso, Adapter y Facade no hacen suposiciones sobre la calidad del diseño subyacente. Estos podrían aplicarse a la API que está bien diseñada para comenzar, simplemente adaptándola a sus necesidades específicas.

En realidad, incluso podría ser más productivo suponer que los patrones como Adapter y Facade esperan que el código subyacente esté bien diseñado. Puede pensarlo de esta manera: un código bien diseñado no debería ser demasiado difícil de modificar para un caso de uso particular. Si resulta que el diseño de su adaptador requiere más esfuerzo del esperado, esto podría indicar que el código subyacente está, de alguna manera, "dañado". En ese caso, puede considerar dividir el trabajo en fases separadas: primero, establezca una capa anticorrupción para presentar la API subyacente de manera estructurada y, a continuación, diseñe su adaptador / fachada sobre esa capa de protección.

    
respondido por el gnat 22.01.2013 - 18:19
fuente
32

Para citar otra fuente:

  

Cree una capa de aislamiento para proporcionar a los clientes funcionalidad en   Términos de su propio modelo de dominio. La capa habla con el otro sistema.   a través de su interfaz existente, requiriendo poca o ninguna modificación a   el otro sistema Internamente, la capa se traduce en ambas direcciones.   según sea necesario entre los dos modelos.

Eric Evans, Domain Driven Design, 16a impresión, página 365

Lo más importante es que se usan términos diferentes en cada lado de la capa anticorrupción. Una vez estuve trabajando en un sistema de logística de transporte. Las rondas debían ser planeadas. Tuvo que equipar el vehículo en un depósito, conducir a diferentes sitios de clientes, darles servicio y visitar otros lugares, como una parada de tanques. Pero desde el nivel superior, todo se trataba de la planificación de tareas. Así que tenía sentido separar los términos de planificación de tareas más generales de los términos logísticos de transporte muy específicos.

Por lo tanto, un aislamiento de capas anticorrupción no solo consiste en protegerlo de un código desordenado, es separar diferentes dominios y asegurarse de que permanezcan separados en el futuro.

    
respondido por el SpaceTrucker 26.01.2013 - 16:52
fuente
27

Adapter

Cuando tienes interfaces incompatibles, que realizan una lógica similar, para adaptar una a la otra, para que puedas usar implementaciones de una con cosas que esperan la otra.

Example:

Tienes un objeto que quiere un Coche, pero solo tienes una clase 4WheelVehicle, así que creas un CarBuiltUsing4WheelVehicle y lo usas como tu Coche.

Facade

Cuando tienes una API compleja / confusa / gigantesca y quieres hacerla más simple / clara / más pequeña. Creará una fachada para ocultar la complejidad / confusión / extras y solo expondrá una nueva API simple / clara / pequeña.

Example:

Está utilizando una biblioteca que tiene 100 métodos, y para realizar ciertas tareas necesita hacer un montón de inicialización, conexión, apertura / cierre de cosas, para finalmente poder hacer lo que quería, y todo lo que quería es 1 característica de todas las 50 que puede hacer la biblioteca, por lo que crea una fachada que solo tiene un método para esa característica que necesita y que realiza todas las tareas de inicialización, limpieza, etc. por usted.

Capa anticorrupción

Cuando tienes un sistema que está fuera de tu dominio, sin embargo, las necesidades de tu negocio requieren que trabajes con ese otro dominio. No desea introducir este otro dominio en su propio dominio, por lo tanto, corromperlo, por lo que traducirá el concepto de su dominio a este otro dominio y viceversa.

Example:

Un sistema ve al cliente que tiene un nombre y una lista de cadenas, una para cada transacción. Usted ve los Perfiles como clases independientes que tienen un nombre, y Transacciones como clases independientes que tienen una cadena, y el Cliente tiene un Perfil y una colección de Transacciones.

Así que creas una capa de ACL que te permitirá traducir entre tu Cliente y el Cliente del otro sistema. De esta manera, nunca tiene que usar el Cliente del otro sistema, simplemente debe decirle a la ACL: "entrégueme al Cliente con el Perfil X, y la ACL le dice al otro sistema que le dé un Nombre de Cliente X, y devuelve Eres un cliente con perfil X.

====================

Los tres son relativamente similares, porque todos son patrones de direccionamiento indirecto. Pero abordan diferentes estructuras, clases / objetos versus APIs versus módulos / subsistemas. Puedes tenerlos todos combinados si lo necesitas. El subsistema tiene una API compleja, por lo que construye una FACHADA para ella, utiliza un modelo diferente, por lo que para cada representación de datos que no se ajuste a su modelo, debería traducir esos datos nuevamente a la forma en que los modela. Finalmente, tal vez las interfaces también sean incompatibles, por lo que utilizarías ADAPTADORES para adaptarte de uno a otro.

    
respondido por el Didier A. 14.11.2014 - 04:08
fuente
10

Muchas respuestas aquí dicen que las ACL "no son solo" sobre el ajuste de código desordenado. Iría más allá y diría que no se trata de eso en absoluto, y si lo hacen, eso es un beneficio secundario.

Una capa anticorrupción consiste en asignar un dominio a otro para que los servicios que usan el segundo dominio no tengan que estar "dañados" por los conceptos del primero. Las ACL son para los modelos de dominio lo que los adaptadores son para las clases, simplemente sucede en un nivel diferente. Podría decirse que el adaptador es el patrón de diseño más importante, lo uso todo el tiempo, pero juzgar a la clase envuelta como desordenada o no es irrelevante. Es lo que es, solo necesito que tenga una interfaz diferente.

Enfocarse en el desorden es engañoso y pierde el sentido de lo que trata el DDD. Las ACL se tratan de lidiar con desajustes conceptuales, no de mala calidad.

    
respondido por el Ian Fairman 10.06.2016 - 12:09
fuente

Lea otras preguntas en las etiquetas