Як я можу зменшити зусилля вручну для обгортання сторонніх бібліотек більшою об'єктною моделлю?


16

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

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

У моєму випадку бібліотека призначена для об'єктної моделі, і, отже, є більша кількість класів і методів, які потрібно було б перетворити, щоб ця стратегія була успішною. Окрім просто "нудного і болісного", це стає важким бар'єром для тестування.

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


Моє запитання не є дублікатом запитань, з якими я спочатку пов'язував, оскільки моє питання стосується зменшення зусиль, що стосуються обгортання вручну. Ці інші запитання задаються лише тим, чи обертання має сенс, а не як зусилля можна зберегти невеликими.


Якою мовою програмування та про яку бібліотеку ви говорите?
Док Браун

@DocBrown C # та бібліотека маніпулювання PDF.
Том Райт

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

Дякую @DocBrown - сподіваюся, що там будуть цікаві перспективи.
Том Райт

1
Коли ми не отримаємо кращих відповідей протягом наступних 48 годин, я роздягнусь із цим.
Doc Brown

Відповіді:


4

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

  1. Існує "ніколи" нічого, що ви повинні "завжди" робити.
    Не завжди найкраще збирати сторонні бібліотеки. Якщо ваша програма по суті залежить від бібліотеки, або якщо вона буквально побудована навколо однієї або двох основних бібліотек, не витрачайте час на її завершення. Якщо бібліотеки змінюються, Вашу програму потрібно буде все-таки змінити .
  2. Добре використовувати інтеграційні тести.
    Особливо це стосується тих меж, які є стабільними, сутнісними для вашої програми або не можуть бути легко висмійовані. Якщо ці умови будуть дотримані, обгортання та глузування будуть складними та виснажливими. У такому випадку я уникаю обох: не загортайте і не знущайтеся; просто написати інтеграційні тести. (Якщо автоматичне тестування є метою.)
  3. Інструменти та рамки не можуть усунути логічну складність.
    В принципі, інструмент можна вирубати лише на котлоагрегаті. Але, не існує автоматизованого алгоритму для складання складного інтерфейсу та його спрощення, не кажучи вже про взяття інтерфейсу X та адаптацію його під свої потреби. (Тільки ви знаєте цей алгоритм!) Тож, хоча, безсумнівно, є інструменти, які можуть генерувати тонкі обгортки, я б припустив, що вони вже не є всюдисущими, тому що, врешті-решт, вам потрібно просто просто розумно кодувати, а отже, вручну, проти інтерфейсу, навіть якщо він схований за обгорткою.

Однак, є тактики, якими ви можете скористатися багатьма мовами, щоб не звертатися безпосередньо до класу. І в деяких випадках ви можете «підробити» інтерфейс або тонку обгортку, яка насправді не існує. Наприклад, у C # я б пройшов один із двох маршрутів:

  1. Використовуйте фабричне та неявне введення тексту .

Ви можете уникнути зусиль, щоб повністю загорнути складний клас із цим маленьким комбо:

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

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

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

  1. Використовуйте динамічне введення тексту .

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

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 класів тонких маленьких обгорткових матеріалів. Ви просто використовували бібліотеку, не дивлячись прямо на неї - здебільшого.

Зважаючи на все це, є три основні причини, які я все-таки розглядаю як явне завершення роботи бібліотеки третьої сторони - жодна з яких не натякає на використання інструменту чи рамки:

  1. Конкретна бібліотека не є суттєвою для програми.
  2. Обмінятись було б дуже дорого, не загортаючи.
  3. Мені не подобається сам API.

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

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

По-іншому, прислухайтеся до класичної поради: відкладіть кожне рішення, яке ви можете. Спочатку побудуйте «ядро» програми. Код проти інтерфейсів, які з часом будуть робити те, що ви хочете, і згодом буде виконано "периферійними речами", які ще не існують. Потрібно усунути прогалини.

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

Думай про це так.

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

TLDR

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

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


2
Це ще одна публікація, що не відповідає на запитання - явно було не "коли завертати", а "як зменшити зусилля вручну".
Док Браун

1
Вибачте, але я думаю, що ви пропустили основний момент питання. Я не бачу, як ваші пропозиції можуть зменшити будь-які ручні зусилля, пов'язані із загортанням. Припустимо, що в lib на карту є складна об'єктна модель як API, яка містить кілька десятків класів і сотні методів. Його API чудовий, як і для звичайного використання, але як його обробити для одиничного тестування з меншим болем / зусиллям?
Док Браун

1
TLDR; якщо ви хочете бонусних балів, скажіть нам щось, про що ми ще не знаємо ;-)
Doc Brown

1
@DocBrown Я не пропустив суть. Але, я думаю, ви пропустили пункт моєї відповіді. Інвестуючи правильні зусилля, ви заощадите багато роботи. Є тестові наслідки - але це лише побічний ефект. З допомогою інструменту для автомагіческій генерувати тонку оболонку навколо бібліотеки по- , як і раніше залишає вас будувати свою основну бібліотеку навколо чужій API і будівництво знущається - що це багато зусиль , що не може уникнути , якщо ви наполегливі при виході з бібліотеки ауту ваших тестів.
svidgen

1
@DocBrown Це абсурд. "Чи має цей клас проблем клас інструментів чи підходів?" Так. Звичайно, так і є. Захисне кодування і не стає догматичним щодо одиничних тестів ... як каже моя відповідь. Якщо ви зробили є автомагіческій генерується тонку оболонку, яке значення буде це забезпечити!? ... Це не дозволить вам вводити залежності для тестування, ви все одно повинні робити це вручну. І це не дозволить вам заміняти бібліотеку, тому що ви все ще кодуєте проти API бібліотеки ... це просто непряме зараз.
svidgen

9

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

Зауважте, ці тести слід запустити після розгортання як автоматизовану діяльність після розгортання. Вони не виконуються як частина тестування одиниць або частина процесу збирання.

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


2
Перше, що я подумав, коли читав вашу відповідь, був "нереальним для PDF, оскільки порівняння файлів на двійковому рівні не говорить про те, що змінилося, або якщо зміни є проблематичними". Потім я знайшов цю старішу публікацію SO , яка вказує, що вона може працювати (так +1)
Док Браун

@DocBrown інструмент у посиланні SO не порівнює PDF-файли на двійковому рівні. Він порівнює структуру та зміст сторінок. Внутрішня структура Pdf: safaribooksonline.com/library/view/pdf-explained/9781449321581/…
linuxunil

1
@linuxunil: так, я знаю, як писав, спершу подумав ... але потім знайшов рішення, згадане вище.
Doc Brown

о .. я бачу .. можливо, "це насправді може спрацювати" у фіналі вашої відповіді мене заплутало.
linuxunil

1

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

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

  1. Такий інструмент, як .NET Wrapper Class Generator . Я не використовував цей інструмент, і я знаю, що він працює на застарілому стеку технологій, але, можливо, для вашого випадку він би підходив. Звичайно, якість коду, підтримка інверсії залежності та розділення інтерфейсів слід досліджувати окремо. Можливо, є інші подібні інструменти, але я багато не шукав.
  2. Написання власного інструменту, який здійснюватиме пошук у посилальній збірці для публічних методів / інтерфейсів та робить відображення та генерацію коду. Внесок до громади був би більш ніж вітальним!
  3. Якщо .NET не є випадком ... можливо, подивіться тут .

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

Створіть свою програму відповідно до потрібного інтерфейсу; не проти сторонніх API.


Гаразд, принаймні ідея, як можна вирішити проблему . Але виходячи з власного досвіду цього випадку використання, я припускаю?
Док Браун

Питання засноване на моєму власному досвіді щодо інженерії програмного забезпечення (обгортка, рефлексія, ді)! Щодо інструментів - я не користувався цим, як зазначено у відмінці.
tom3k

0

Дотримуйтесь цих вказівок під час створення бібліотек обгортки:

  • розкрийте лише невелику підмножину сторонньої бібліотеки, яка вам потрібна зараз (і розгорніть за потребою)
  • тримайте обгортку якомога тонкішою (жодна логіка не належить).

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