Якщо припустити, що ви не шукаєте глузливих рамок, оскільки їх надто всюдисуще і їх легко знайти , є кілька речей, про які варто звернути увагу:
- Існує "ніколи" нічого, що ви повинні "завжди" робити.
Не завжди найкраще збирати сторонні бібліотеки. Якщо ваша програма по суті залежить від бібліотеки, або якщо вона буквально побудована навколо однієї або двох основних бібліотек, не витрачайте час на її завершення. Якщо бібліотеки змінюються, Вашу програму потрібно буде все-таки змінити .
- Добре використовувати інтеграційні тести.
Особливо це стосується тих меж, які є стабільними, сутнісними для вашої програми або не можуть бути легко висмійовані. Якщо ці умови будуть дотримані, обгортання та глузування будуть складними та виснажливими. У такому випадку я уникаю обох: не загортайте і не знущайтеся; просто написати інтеграційні тести. (Якщо автоматичне тестування є метою.)
- Інструменти та рамки не можуть усунути логічну складність.
В принципі, інструмент можна вирубати лише на котлоагрегаті. Але, не існує автоматизованого алгоритму для складання складного інтерфейсу та його спрощення, не кажучи вже про взяття інтерфейсу X та адаптацію його під свої потреби. (Тільки ви знаєте цей алгоритм!) Тож, хоча, безсумнівно, є інструменти, які можуть генерувати тонкі обгортки, я б припустив, що вони вже не є всюдисущими, тому що, врешті-решт, вам потрібно просто просто розумно кодувати, а отже, вручну, проти інтерфейсу, навіть якщо він схований за обгорткою.
Однак, є тактики, якими ви можете скористатися багатьма мовами, щоб не звертатися безпосередньо до класу. І в деяких випадках ви можете «підробити» інтерфейс або тонку обгортку, яка насправді не існує. Наприклад, у C # я б пройшов один із двох маршрутів:
- Використовуйте фабричне та неявне введення тексту .
Ви можете уникнути зусиль, щоб повністю загорнути складний клас із цим маленьким комбо:
// "factory"
class PdfDocumentFactory {
public static ExternalPDFLibraryDocument Build() {
return new ExternalPDFLibraryDocument();
}
}
// code that uses the factory.
class CoreBusinessEntity {
public void DoImportantThings() {
var doc = PdfDocumentFactory.Build();
// ... i have no idea what your lib does, so, I'm making stuff but.
// but, you can do whatever you want here without explicitly
// referring to the library's actual types.
doc.addHeader("Wee");
doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
return doc.exportBinaryStreamOrSomething();
}
}
Якщо ви можете уникнути зберігання цих об’єктів як членів, або через більш "функціональний" підхід, або зберігаючи їх у словнику (або будь-якому іншому ), цей підхід має перевагу перевірки типу компіляції в часі, без ваших основних суб'єктів господарювання не потрібно точно знати з яким класом вони працюють.
Все, що потрібно, це те, що під час компіляції клас, повернений вашою фабрикою, насправді має на ньому методи, якими користується ваш бізнес-об’єкт.
- Використовуйте динамічне введення тексту .
Це аналогічно використанню неявного введення тексту , але передбачає ще один компроміс: Ви втрачаєте перевірки типу компіляції та отримуєте можливість анонімно додавати зовнішні залежності як учасників класу та вводити свої залежності.
class CoreBusinessEntity {
dynamic Doc;
public void InjectDoc(dynamic Doc) {
Doc = doc;
}
public void DoImortantThings() {
Doc.addHeader("Wee");
Doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
return Doc.exportBinaryStreamOrSomething();
}
}
З обома цими тактиками, коли настає час знущатися ExternalPDFLibraryDocument
, як я вже говорив раніше, вам належить виконати деяку роботу - але це робота, яку вам потрібно було б зробити в будь-якому випадку . І, використовуючи цю конструкцію, ви уникали нудно визначати 100 класів тонких маленьких обгорткових матеріалів. Ви просто використовували бібліотеку, не дивлячись прямо на неї - здебільшого.
Зважаючи на все це, є три основні причини, які я все-таки розглядаю як явне завершення роботи бібліотеки третьої сторони - жодна з яких не натякає на використання інструменту чи рамки:
- Конкретна бібліотека не є суттєвою для програми.
- Обмінятись було б дуже дорого, не загортаючи.
- Мені не подобається сам API.
Якщо я не маю певної ступеня занепокоєння у всіх трьох цих областях, ви не докладете жодних суттєвих зусиль, щоб вирішити це. І якщо ви хвилюєтесь у всіх трьох сферах, тонка автоматична генерація тонкої обгортки насправді не допоможе.
Якщо ви вирішили обернути бібліотеки вгору, найбільш ефективне і ефективне використання вашого часу , щоб побудувати додаток від інтерфейсу ви хочете ; не проти існуючого API.
По-іншому, прислухайтеся до класичної поради: відкладіть кожне рішення, яке ви можете. Спочатку побудуйте «ядро» програми. Код проти інтерфейсів, які з часом будуть робити те, що ви хочете, і згодом буде виконано "периферійними речами", які ще не існують. Потрібно усунути прогалини.
Ці зусилля можуть не відчувати себе економією часу; але якщо вам здається, що вам потрібна обгортка, це найефективніший спосіб зробити це безпечно.
Думай про це так.
Вам потрібно зашифрувати цю бібліотеку в якомусь темному кутку коду - навіть якщо він завернений. Якщо ви знущаєтесь над бібліотекою під час тестування, там неминучі ручні зусилля - навіть якщо вони завернуті. Але це не означає, що вам потрібно безпосередньо підтверджувати цю бібліотеку за назвою протягом усієї вашої програми.
TLDR
Якщо бібліотеку варто обгортати, використовуйте тактику, щоб уникнути поширених, прямих посилань на свою сторонній бібліотеці, але не приймайте ярлики для створення тонких обгортків. Спочатку побудуйте свою бізнес-логіку, подумайте про свої інтерфейси та організуйте свої адаптери органічно за потребою.
І якщо справа доходить до цього, не бійтеся інтеграційних тестів. Вони трохи нечіткі, але вони все ще пропонують докази робочого коду, і їх все ще можна легко зробити, щоб утримати регресії в страху.