Чи є загальна бібліотека гарною ідеєю?


16

Я завжди думав, що "спільна бібліотека" - це гарна ідея. Під цим я маю на увазі бібліотеку, яка містить загальну функціональність, яка часто потрібна декільком різним програмам. Це призводить до меншого дублювання коду / надмірності.

Нещодавно я прочитав статтю (зараз не можу знайти), що сказав, що це насправді погана ідея, і я пішов далеко, щоб сказати, що це "анти-шаблон"

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

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

Пишучи це, я починаю думати, що цей підхід "загальної ліби" є результатом роботи на архітектурі? Можливо, мій дизайн потребує більше роздумів?

Зацікавлені почути думки.


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

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

Більшість розробників С, які я знаю, мають колекцію утиліт, які вони називають своїм "інструментальним". Зазвичай він не збирається в єдину бібліотеку, що включається. Це більше "вибирай".
Марк Беннінгфілд

2
Хтось кличе Apache і виправляє це безумство. Apache commons
Laiv

Відповіді:


21

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

Я бачив це в дії, коли я став відповідальним за перші порти цілого коду цілого бізнес-підрозділу (в основному для мене нового) для 64-розрядних систем і провів повний ремонт нашої збірки та упаковки, багато з чого робилося. вручну, а іноді і не дуже добре. * Ми прагнули створити те, що ми відправляємо із стопки додатків, де клієнт сказав: "Мені б хотілося, що система робить A, B, D і F, плюс речі M і N, що ви ще не робите, і трохи інший клей інтегруючи їх усіх " Спільне все це - це бібліотека з ящиками для сміття, яка протягом кількох десятиліть ** накопичувала всі речі, які люди вважали за потрібні для повторного використання. Щоб коротко розповісти, частина коду в бібліотеці не була '. Ми витрачали багато цінного часу на створення та підтримку цих залежностей лише для того, щоб встановити загальну бібліотеку, а не тому, що ми насправді їм потрібні.

Мораль полягає в тому, що до бібліотек потрібно ставитися як до класів, а не перевантажувати їх занадто багато обов'язків. Не ставте парсер JSON в одну бібліотеку з функціями лінійної алгебри, навіть якщо кожна програма, яку ви пишете, використовує обидві.

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

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


* У процесі роботи я виявив бінарний файл, який був переданий навколо, і не був перекомпільований з нуля протягом шести років.

** З кодом десятиліття нічого поганого немає. У нас був ряд критичних алгоритмів, які були настільки добре доведені, що ми були дурнями, щоб переписати їх виключно в інтересах сучасності.


1
Моє правило - якщо ви збираєтесь назвати свою бібліотеку чимось на кшталт "загального", ви прямуєте до неприємностей.
Карл Білефельдт

9

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

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

І це почалося досить добре. Ми почали з математичної бібліотеки ( common/math*) процедур, яку ми всі використовували щодня, оскільки ми працювали в комп'ютерній графіці, яка часто була важкою для лінійної алгебри. А оскільки ми часто взаємоділи з кодом С, ми погодилися на деякі корисні функції утиліти, такі як find_index, на відміну відstd::findв C ++ повертає індекс до елемента, знайденого в послідовності замість ітератора, який наслідував, як працюють наші функції C - речі такого роду - трохи еклектичні, але мінімалістичні і досить широко використовуються, щоб залишатися знайомими і практичними для всіх і миттєве знайомство є надзвичайно важливим критерієм, оскільки я бачу це у спробі зробити все, що є "загальним" або "стандартним", оскільки якщо воно справді є "загальним", воно повинно мати таку звичну якість про нього як результат його широкого прийняття та щоденне використання.

Але з часом дизайнерські наміри бібліотеки вислизнули з моїх пальців, коли люди почали додавати речі, які вони використовували особисто, які, як вони думали, можуть бути корисними комусь іншому, лише знайти того, хто більше не використовує її. А пізніше хтось почав додавати функції, які залежали від OpenGL для звичайних GL-процедур. Далі ми прийняли Qt, і люди почали додавати код, який залежав від Qt, тому вже загальна бібліотека залежала від двох зовнішніх бібліотек. У якийсь момент хтось додав загальні підпрограми шейдерів, які залежали від нашої бібліотеки шейдерних програм, і в цей момент ви навіть не змогли розгорнути його в новому проекті, не ввівши Qt, OGL та нашу бібліотеку шейдерів та написання конкретних програм. нетривіальний сценарій збірки для вашого проекту. Так воно перетворилося на цей еклектичний, взаємозалежний безлад.

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

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

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

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

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

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

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

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

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


3

Існує три різні категорії функцій, які ви можете розглянути, як розмістити в бібліотеках:

  1. Речі, які варто повторно використовувати для всіх.
  2. Речі варто лише повторно використовувати для вашої організації.
  3. Речі не варто повторно використовувати.

Перша категорія - це те, для чого повинна існувати стандартна бібліотека , але чомусь ніхто не обходив її виготовлення (чи хтось? Ви ретельно шукали?). У такому випадку подумайте про те, щоб зробити вашу бібліотеку відкритим кодом. Спільний доступ до вашої роботи не лише допомагає іншим, але й допомагає вам, оскільки ви будете отримувати звіти про помилки та виправлення від інших користувачів. Якщо ви сумніваєтесь, що хтось зробить свій внесок у вашу бібліотеку, ви можете мати справу з функціоналом, який насправді є категоріями 2 або 3.

Друга категорія - це речі, які вам потрібно знову і знову, але ніхто інший у світі цього не потребує. Наприклад, реалізація неясного мережевого протоколу для зв’язку з вашою розробленою в будинку системою резервного копіювання. У такому випадку може бути доцільним розмістити цей матеріал у внутрішній бібліотеці, щоб підвищити швидкість розвитку нових програм. Просто переконайтеся, що на нього не надто впливає повзучість функцій, і він починає містити речі, які насправді вписуються в категорії 1 або 3. Крім того, порада Blrfl щодо модуляризації дуже хороша: не створюйте однієї монолітної бібліотеки Conor Corp. Створіть кілька окремих бібліотек для окремих функцій.

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


1

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

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


these libraries just replicate functionality from standard librariesце не зовсім погано, у javascript ви додали бібліотеки, які вже реалізують існуючі речі, щоб додати підтримку на старих js-двигунах, у вас також є андроїд-файли підтримки для старих sdk тощо.
svarog

@svarog: Ви думаєте про "поліфіли", які імітують функціональність у нових стандартах для старих двигунів, які не підтримують її спочатку? Я не бачу причин писати це самостійно, оскільки для цих цілей є відомі бібліотеки з відкритим кодом.
ЖакБ

0

Більшість бібліотек, які діляться між командами, викликають більше проблем, ніж вони вирішують. "Дорога до пекла вимощена добрими намірами".

Виняток становлять бібліотеки, які задовольняють більшість наведених нижче:

  • Забезпечити безпечне довгострокове фінансування
  • Майте спеціальну команду / спільноту підтримки
  • Запропонуйте клопа
  • Мають широке тестове покриття
  • Мають єдину, чітко визначену мету
  • Не мати самих залежностей (як при складанні, так і під час виконання), крім стандартних або квазістандартних бібліотек
  • Майте чітке розмежування між громадськими і внутрішніми підприємствами
  • Майте канал і процес зв'язку для всіх / багатьох користувачів, щоб узгодити нові функції та версії

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

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