Что такое слой Anti-Corruption и как он используется?

Я пытаюсь понять, что означает слой Anti-Corruption. Я знаю, что это способ перехода /работы с устаревшим кодом или плохими API. Я не понимаю, как это работает и что делает его чистым отрывом от нежелательного слоя.

Я сделал несколько поисков, но я не могу найти простых примеров или объяснений, поэтому я ищу того, кто его понимает, и может объяснить это с помощью простых примеров. Ответ, который удовлетворит мой вопрос, должен быть простым (не обязательно коротким) и обеспечивать понятные примеры реализации и использования.

См. этот вопрос для моего варианта использования.

132 голоса | спросил knownasilya 22 Jpm1000000pmTue, 22 Jan 2013 20:14:41 +040013 2013, 20:14:41

4 ответа


133

Представьте, что вам нужно использовать чужой код, который разработан, как показано ниже:

     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) { /* ... */ }
    }

Теперь представьте себе, что ваш код, который зависит от него, выглядит следующим образом:

 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?
}

... и что вы хотите упростить использование, в частности, чтобы избавиться от повторного использования параметров, которые просто не нужны для вашего приложения.

Хорошо, поэтому вы начинаете создавать слой с антикоррупцией.

  1. Прежде всего, убедитесь, что ваш «основной код» не относится к Messy напрямую. Например, вы организуете управление зависимостями таким образом, чтобы пытаться получить доступ к Messy не удается скомпилировать.

  2. Во-вторых, вы создаете выделенный модуль «layer», который является единственным, кто обращается к Messy и раскрывает его вашему «основному коду» таким образом, который имеет смысл для вас.

Код слоя будет выглядеть следующим образом:

     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); }
    }

В результате ваш «основной код» не путается с Messy, используя Reasonable, а именно:

 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");
}

Обратите внимание, что по-прежнему существует некоторая беспорядочная messing с Messy, но теперь она скрыта достаточно глубоко внутри Reasonable, что делает ваш «основной код» достаточно чистым и свободным от коррупция, которую можно было бы получить путем прямого использования материала Messy.


Вышеприведенный пример основан на том, как Уровень антикоррупции объясняется в c2 wiki:

  

Если вашему приложению необходимо иметь дело с базой данных или другим приложением, модель которого нежелательна или неприменима к модели, которую вы хотите в рамкахваше собственное приложение, используйте AnticorruptionLayer для перевода в /из этой модели и вашей.

Примечание. Пример преднамеренно сделан простым и сжатым, чтобы содержать краткое пояснение.

Если у вас есть более сложный API-интерфейс для покрытия уровня защиты от коррупции, применяется тот же подход: во-первых, убедитесь, что ваш «основной код» не имеет доступа к поврежденному файлу напрямую и во-вторых, выставить его таким образом, который более удобен в контексте использования.

Когда «масштабирование» вашего слоя за упрощенным примером выше, учтите, что сделать ваш API удобным не обязательно тривиальная задача. Инвестируйте усилие до > правильно настройте свой слой , проверьте его предназначенное для использования с модульные тесты и т. д.

Другими словами, убедитесь, что ваш API действительно является улучшением по сравнению с тем, который он скрывает, убедитесь, что вы не просто вводите другой уровень коррупции.


Для полноты, обратите внимание на тонкое, но важное различие между этим и связанными шаблонами Адаптер и Фасад . Как указано по его названию, слой антикоррупции предполагает, что лежащий в основе API имеет вопросы качества (« поврежден ») и намеревается предложить защиту указанных проблем.

Вы можете подумать об этом так: если вы можете оправдать, что разработчик библиотеки будет лучше разоблачить свои функции с помощью Reasonable вместо Messy, это будет означать, работая над антикоррупционным слоем, выполняя свою работу , исправляя ошибки их .

В отличие от этого, Адаптер и Фасад не делают предположений о качестве базового дизайна. Они могут быть применены к API, который хорошо разработан для начала, просто адаптируя его для ваших конкретных потребностей.

На самом деле, даже более продуктивно предположить, что такие шаблоны, как Adapter и Facade , ожидают, что базовый код будет хорошо разработан. Вы можете думать об этом так: хорошо продуманный код не должен быть слишком сложным для настройки для конкретного случая использования. Если окажется, что дизайн вашего адаптера требует больше усилий, чем ожидалось, это может указывать на то, что базовый код, ну, как-то «поврежден». В этом случае вы можете рассмотреть разделение задания на отдельные этапы: во-первых, установите слой антикоррупции, чтобы представить базовый API правильно структурированным способом, а затем спроектируйте свой адаптер /фасад над этим уровнем защиты.

ответил gnat 22 Jpm1000000pmTue, 22 Jan 2013 21:19:13 +040013 2013, 21:19:13
31

Чтобы указать другой источник:

  

Создайте изолирующий слой, чтобы обеспечить клиентам функциональность в   терминов их собственной модели домена. Слой разговаривает с другой системой   через существующий интерфейс, требующий незначительной модификации или без   другая система. Внутренне слой переводится в обоих направлениях   по мере необходимости между двумя моделями.

Эрик Эванс, дизайн, управляемый доменом, 16-е издание, стр. 365

Самое главное, что на каждой стороне слоя анти-коррупции используются разные термины. Я когда-то работал над системой транспортной логистики. Раунды должны были быть запланированы. Вам нужно было оборудовать автомобиль на складе, ездить на разные сайты клиентов и обслуживать их и посещать другие места, например, танк-стоп. Но с более высокого уровня все это касалось планирования задач. Поэтому имеет смысл отделить более общие условия планирования задачи от очень специфических транспортных логистических терминов.

Таким образом, изоляция уровней защиты от коррупции заключается не только в защите вас от грязного кода, а в том, чтобы разделить разные домены и убедиться, что они останутся в будущем.

ответил SpaceTrucker 26 Jpm1000000pmSat, 26 Jan 2013 19:52:04 +040013 2013, 19:52:04
27

Адаптер

Если у вас есть несовместимые интерфейсы, которые выполняют аналогичную логику, чтобы адаптировать их друг к другу, чтобы вы могли использовать реализации одного с вещами, которые ожидают другого.

Пример:

У вас есть объект, который хочет автомобиль, но у вас есть только класс 4WheelVehicle, поэтому вы создаете CarBuiltUsing4WheelVehicle и используете это как свой автомобиль.

Фасад

Если у вас сложный /запутанный /гигантский API, и вы хотите сделать его более простым /понятным /меньшим. Вы создадите Facade, чтобы скрыть сложность /путаницу /дополнительные функции и просто выставить новый простой /понятный /небольшой API.

Пример:

Вы используете библиотеку, которая имеет 100 методов, и для выполнения определенной задачи вам нужно выполнить кучу инициализации, подключения, открытия /закрытия вещей, чтобы, наконец, сделать то, что вы хотели, и все, что вы хотели, 1 из всех 50, которые может сделать библиотека, поэтому вы создаете Facade, который имеет только метод для этой 1 функции, которая вам нужна, и которая выполняет все инициализацию, очистку и т. Д. Для вас.

Уровень защиты от коррупции

Если у вас есть система, находящаяся вне вашего домена, но для вашего бизнеса вам необходимо работать с этим другим доменом. Вы не хотите вводить этот другой домен в свой собственный, поэтому его разлагаете, поэтому вы переведете концепцию своего домена в этот другой домен и наоборот.

Пример:

Одна система просматривает custumer с именем и списком строк, по одному для каждой транзакции. Вы просматриваете профили как самостоятельные классы, имеющие имя, а транзакции - как самостоятельные классы, имеющие строку, а клиент - как профиль и коллекцию транзакций.

Итак, вы создаете слой ACL, который позволит перевести между вашим Клиентом и клиентом другой системы. Таким образом, вам никогда не придется использовать клиента другой системы, вам просто нужно сообщить ACL: «Дайте мне Клиента с профилем X, и ACL сообщает другой системе предоставить ему Клиента с именем X.name и возвращает вы являетесь Клиентом с профилем X.

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

Все три являются относительно похожими, потому что все они имеют обратные структуры. Но они обращаются к различным структурам, классам /объектам и API по сравнению с модулями /подсистемами. Вы могли бы объединить их, если вам нужно. Подсистема имеет сложный API, поэтому вы создаете для него FACADE, она использует другую модель, поэтому для каждого представления данных, которое не соответствует вашей модели, вы переводите эти данные обратно в то, как вы его моделируете. Наконец, возможно, интерфейсы также несовместимы, поэтому вы должны использовать ADAPTERS для адаптации от одного к другому.

ответил Didier A. 14 52014vEurope/Moscow11bEurope/MoscowFri, 14 Nov 2014 06:08:03 +0300 2014, 06:08:03
9

Многие ответы здесь говорят о том, что ACL - это «не просто» об упаковке грязного кода. Я пойду дальше и скажу, что они совсем не об этом, и если они это сделают, это побочный эффект.

Уровень защиты от коррупции - это сопоставление одного домена с другим, поэтому сервисы, которые используют второй домен, не должны быть «повреждены» концепциями из первого. ACL - это модели доменов, какие адаптеры относятся к классам, это просто происходит на другом уровне. Адаптер, возможно, является самым важным шаблоном дизайна - я использую его все время, но судить о том, что упакованный класс является беспорядочным или нет, не имеет значения. Это то, что есть, мне просто нужно иметь другой интерфейс.

Фокусировка на беспорядочности вводит в заблуждение и пропускает смысл того, что такое DDD. ACL имеют дело с концептуальными несоответствиями, а не с низким качеством.

ответил Ian Fairman 10 J0000006Europe/Moscow 2016, 13:09:33

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132