Що таке антикорупційний шар і як він використовується?


151

Я намагаюся розібратися, що насправді означає антикорупційний шар. Я знаю, що це спосіб переходу / подолання застарілого коду чи поганих API. Я не розумію, як це працює і що робить його чистим відривом від небажаного шару.

Я здійснив пошук, але не можу знайти простих прикладів чи пояснень, тому шукаю когось, хто це розуміє, і може пояснити це простими прикладами. Відповідь, яка задовольнила б моє запитання, повинна бути простою (не обов'язково короткою) та наводити зрозумілі приклади впровадження та використання.

Дивіться це питання для мого використання.

Відповіді:


147

Уявіть, що вам потрібно використовувати чужий код, розроблений, як показано нижче:

    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. По-друге, ви створюєте спеціальний модуль "шару", який є єдиним доступом, 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");
}

Зауважте, що все-таки дещо заплуталося, Messyале це тепер приховано досить глибоко всередині Reasonable, завдяки чому ваш "основний код" є досить чистим і позбавленим корупції, яка буде принесена туди шляхом прямого використання Messyречей.


Наведений вище приклад ґрунтується на тому, як пояснюється антикорупційний шар у вікі c2:

Якщо вашій програмі потрібно мати справу з базою даних або іншою програмою, модель якої небажана або не застосовується до моделі, яку ви хочете, у вашій власній програмі, використовуйте антикорупційний шар для перекладу на / з цієї моделі та вашої.

Приклад примітки навмисно робиться простим і стислим, щоб пояснення були короткими.

Якщо у вас є більший безлад API, який слід покрити за антикорупційним шаром, застосовується той же підхід: по-перше, переконайтеся, що ваш "основний код" не отримує доступ до пошкоджених матеріалів безпосередньо, а по-друге, викрийте його таким чином, що більше зручна у вашому контексті використання.

Під час "масштабування" шару за спрощеним прикладом, який вище, врахуйте, що зробити API зручним - це не обов'язково тривіальне завдання. Вкладіть зусилля, щоб правильно розробити ваш шар , перевірити його використання за допомогою модульних тестів тощо.

Іншими словами, переконайтеся, що ваш API справді є поліпшенням порівняно з одним, який він приховує, переконайтеся, що ви не просто вводите інший шар корупції.


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

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

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

Насправді, може бути навіть більш продуктивним припустити, що такі моделі, як Адаптер та Фасад, очікують, що базовий код буде добре розроблений. Ви можете подумати про це так: добре розроблений код не повинен бути занадто складним для підключення для конкретного випадку використання. Якщо виявиться, що дизайн вашого адаптера вимагає більше зусиль, ніж очікувалося, це може означати, що базовий код, ну, якимось чином "пошкоджений". У такому випадку ви можете розглянути завдання розділити завдання на окремі фази: спочатку встановіть антикорупційний шар, щоб представити базовий API правильно структурованим способом, а далі, спроектуйте адаптер / фасад на цей захисний шар.


1
Як працює ця шкала, якщо існує ціла структура залежних класів API? Це все-таки більш керований, ніж шар, від якого він захищає решту програми?
knownasilya

1
@Knownasilya, це дуже гарне запитання, відповідь розширений на його адресу
гнат

4
In other words, make sure that your API is indeed an improvement over one it hides, make sure that you don't just introduce another layer of corruption.Весь цей розділ гідний сміливого тегу.
Ліліенталь

19
Антикорупційні шари не мають нічого спільного з поводженням з неякісними API. Йдеться про вирішення понятійних невідповідностей, адаптацію доменів, якими ми могли б скористатися, лише «пошкодивши» наш код тим доменам, якими ми можемо легше користуватися.
Ian Fairman

8
Ян Фейрман правильно це зрозумів, тоді як автор цієї відповіді, безумовно, не став. Якщо ви перейдете до джерела концепції (книги DDD), ви знайдете щонайменше дві речі, які суперечать цій відповіді: 1) створюється антикорупційний шар, щоб уникнути пошкодження нової доменної моделі, яку ми розробляємо з елементами з моделі існуючої зовнішньої системи; Справа не в тому, що інша система «пошкоджена», адже вона може бути ідеально хорошою та продуманою; 2) антикорупційний рівень , як правило, містить кілька класів, часто включаючи Фасади та Адаптери , а також Послуги .
Rogério

41

Щоб цитувати ще одне джерело:

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

Ерік Еванс, Дизайн, керований доменом, 16-та друк, сторінка 365

Найголовніше - це використання різних термінів в кожній стороні антикорупційного шару. Я колись працював над системою транспортної логістики. Тури потрібно було спланувати. Вам довелося обладнати транспортний засіб у депо, заїхати на різні місця клієнтів та обслуговувати їх та відвідати інші місця, як-от зупинка танка. Але з вищого рівня це стосувалося планування завдань. Тому мало сенс відокремити більш загальні умови планування завдань від дуже конкретних логістичних умов транспортування.

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


6
Це дуже важливо! ACL - це не просто використовувати з кодом Мессі, а як засіб для зв'язку між обмеженими контекстами. Він перекладається з одного контексту в інший, так що дані в кожному контексті відображають мову та те, як цей контекст думає і говорить про ці дані.
Дідьє А.

29

Перехідник

Якщо у вас є несумісні інтерфейси, які виконують подібну логіку, адаптуйте один до іншого, щоб ви могли використовувати реалізацію одного з речами, які очікують іншого.

Приклад:

У вас є об'єкт, який хоче автомобіль, але у вас є лише клас 4WheelVehicle, тому ви створюєте CarBuiltUsing4WheelVehicle і використовуєте його як свій автомобіль.

Фасад

Коли у вас складний / заплутаний / гігантський API і ви хочете зробити його простішим / зрозумілішим / меншим. Ви створите Фасад, щоб приховати складність / плутанину / доповнення і лише відкрити новий простий / зрозумілий / малий API.

Приклад:

Ви використовуєте бібліотеку, яка має 100 методів, і для виконання певного завдання вам потрібно зробити купу ініціалізації, підключення, відкриття / закриття речей, щоб нарешті мати можливість робити те, що хотіли, і все, що ви хотіли, - це 1 особливість всі 50 бібліотеки можуть зробити, тому ви створюєте Фасад, який має лише метод для тієї 1 функції, яка вам потрібна, і яка робить усі ініціалізації, очищення тощо.

Антикорупційний рівень

Якщо у вас є система, яка не входить у ваш домен, але для вашого бізнесу потрібна робота з цим іншим доменом. Ви не хочете вводити цей інший домен у свій власний, тому його пошкоджуєте, тому ви переведете поняття свого домену в цей інший домен і навпаки.

Приклад:

Одна система переглядає користувача, який має ім'я та список рядків, по одному для кожної транзакції. Ви розглядаєте Профілі як окремі класи з назвою, а Транзакції - як окремі класи, що мають рядок, а Клієнт - як профіль та колекцію транзакцій.

Таким чином, ви створюєте рівень ACL, який дозволить переводити між Вашим Клієнтом та Замовником іншої системи. Таким чином, вам ніколи не доведеться використовувати Клієнта іншої системи, вам просто потрібно сказати ACL: "дайте мені Клієнта з профілем X, а ACL повідомляє іншій системі дати йому Клієнта з ім'ям X.name і повернеться ви Клієнт із профілем X.

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

Усі три відносно схожі, тому що всі вони є непрямими. Але вони стосуються різних структур, класів / об'єктів проти API та модулів / підсистем. Ви можете їх об'єднати, якщо вам потрібно. Підсистема має складний API, тому ви створюєте для неї FACADE, вона використовує іншу модель, тому для кожного представлення даних, що не відповідає вашій моделі, ви переведете ці дані назад у те, як ви їх моделюєте. Нарешті, можливо, інтерфейси також несумісні, тому ви використовуєте ADAPTERS для адаптації від одного до іншого.


12

Тут багато відповідей говорять про те, що ACL - це не просто "загортання брудного коду. Я б пішов далі і сказав, що вони взагалі не про це, і якщо це робити, то це побічна вигода.

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

Зосередження уваги на безладді вводить в оману і не вникає в те, що йдеться про DDD. ACL стосуються вирішення концептуальної невідповідності, а не поганої якості.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.