Навіщо розробляти внутрішні бібліотеки для внутрішніх додатків?


10

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

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

Іншими словами: якщо записаний якийсь вихідний код, як ви вирішите, чи слід його збирати у бінарну бібліотеку та пов’язувати з вашою програмою чи просто включати у вихідні файли проекту та збирати регулярно?

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

ps Я тут говорю про розробку c / c ++ для декількох настільних додатків.


Відповіді:


25

Існує чимало причин для створення бібліотек і спільних бібліотек (у .dll або .so файлах) навіть для внутрішнього використання:

  1. Повторне використання в проектах набагато чистіше
  2. Розмежування відповідальності - частина вашого коду може підходити різним розробникам чи командам
  3. Ви можете скористатися вдосконаленнями бібліотек, які створюють інші команди, не знаходячи конкретний код
  4. Швидші часи збирання, якщо бібліотека стабільна, її не потрібно повторно створювати.
  5. Дисковий простір - у проекті ви можете мати лише бібліотеку та заголовки
  6. Якщо ви використовуєте спільні бібліотеки, ви можете заощадити пам'ять лише однією копією, завантаженою в оперативну пам’ять, навіть якщо кілька програм використовують її
  7. Як правило, ви покращуєте документацію та тестування бібліотек
  8. Очищення дизайну та коду - роздуми про структурування речей в бібліотеки повинні спричинити за собою пов'язані групи функціональності в кожній бібліотеці, і ви, як правило, розділяєте загальний код, в бібліотеки , від специфіки програми, у додатку .
  9. Якщо у бібліотеках є власні алгоритми, ви можете обмежувати доступ до джерела, наприклад, не дозволяючи підрядникам чи командам, що отримують джерела, потрапляти до джерела.
  10. Код бібліотеки може бути розміщений під іншою ліцензією на додаток, який він спочатку був написаний у складі, деякі компанії навіть були відомі бібліотекам з відкритим кодом, якими вони пишаються - здобувши великі кудо в спільноті з відкритим кодом, і колись великі вдосконалення сприяли назад.

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


1
Або у варіанті пункту 9 ви можете випустити бібліотеку за іншою ліцензією, ніж основний код програми.
Майкл Боргвардт

@MichaelBorgwardt - гарна точка, що підказує пункт 10 вище.
Стів Барнс

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

11

Деякі інші можливі причини, які можуть стосуватися більш великих, нетривіальних проектів:

  • Часи компіляції: величезні монолітні проекти C ++ з тисячами файлів, тисячі класів, функцій тощо можуть скласти дуже багато часу (що шкодить продуктивності, якщо ви хочете перекомпілювати кожен раз, коли змінюєте кілька рядків коду). Статично пов'язані та динамічно пов'язані бібліотеки складаються незалежно і їх не потрібно перекомпілювати, якщо їх джерело не змінилося.

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

  • Межі між розробниками / командами : Розробники, що будують окремий новий функціонал одночасно, можуть зменшити потенціал конфліктів злиття, якщо можливо, щоб кожен розробник працював у різних модулях.

  • Код, який не повинен бути випущений у пряме середовище : Наприклад, тестові бібліотеки одиниць або "макетні" бібліотеки, які використовуються для тестування розробника, щоб замінити живий компонент системи (апаратне забезпечення, API, віддалені системи, бази даних тощо)

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

  • Додаткові функції / Оптимізація : У великих системах програма може зачекати перед завантаженням певних динамічно пов'язаних модулів у пам'ять під час виконання, якщо вони не є критичними для основної функціональності програми.


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


3
@downvoter - ви могли б пояснити причину знищення? Відгуки на відповіді корисні для покращення якості цього веб-сайту для всіх.
Бен Коттрелл

4

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

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

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


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

@AndrewMurtagh: той факт, що ти так швидко прийняв відповідь МайклаБоргвардта, мене здивувало, тому що те, що він написав, здається, або нерозумінням його чи мого.
Док Браун

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

2

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

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

Написання «бібліотеки» для одного випадку використання може перетворитися на дуже дороге вправу без жодної виплати --- мене це покусало кілька разів.

Приклад витрат:

  1. Час / енергія, витрачена на розгляд "загальних" випадків використання
  2. Час, витрачений на передання "бібліотеки" на "клієнта" (власний код)
  3. Майбутній тиск, щоб використовувати "бібліотеку", навіть якщо вона повністю не відповідає наступному випадку використання

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


2
Я бачив майже ті самі причини, які використовували деякі розробники, тому що їх код знаходиться в одному вихідному файлі з рядком 20k. У поєднанні з вигадливими іменами та поганими коментарями у вас незабаром з'явиться код, що його швидше переписати, ніж підтримувати.
Стів Барнс

Відмінний момент: я, безумовно, не заперечую проти написання ретельного, читабельного коду. Окремі файли, добре названі методи / класи та структура пакунків - всі важливі компоненти ремонту. Моя думка полягає лише в тому, що витрати на написання та розповсюдження бібліотеки стрімко виникають, коли для "бібліотеки" існує лише один випадок використання.
Сем

1
І навпаки, я не стверджую, що вам обов’язково потрібно запакувати та розповсюджувати бібліотеку у кожному випадку, тільки те, що писати та структурувати так, ніби ваш код одного дня може стати бібліотекою, зазвичай варто докласти трохи зусиль і часто виплачує дивіденди, навіть якщо код ніколи не стає поширюється як бібліотека.
Стів Барнс

1

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

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

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

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

Нарешті, можуть бути технічні причини - чи може бути необхідним зберігати частину коду як бібліотеки, щоб він міг завантажуватися необов'язково або навіть завантажуватися та вивантажуватися на вимогу, і, таким чином, зменшувати використання пам’яті, коли економічність не потрібна?


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

@AndrewMurtagh: Так, саме так я б сказав. Хоча можуть бути і технічні причини; Я не такий знайомий з розвитком C / C ++ - можливо, зберігання частини коду як бібліотеки є необхідним, щоб його можна було завантажувати за бажанням або навіть завантажувати та вивантажувати на вимогу, і, таким чином, зменшувати використання пам’яті, коли економічність не потрібна?
Майкл Боргвардт

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

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

Подумайте також про технічне обслуговування. 1) Губку можна підтримувати незалежно і паралельно. 2) Чи легко замінити код. 3) Невелика кодова база легша в управлінні для малих команд і легша для розуміння для всіх. 4) якщо час на ринок є критичним, ви віддасте перевагу швидшому нарощуванню. Код у libs - це код, який ви не збираєте знову і знову в конвеєрі (IMO). 5) Це надійний код для багаторазового використання ... Ви зробили це ;-)
Laiv

1

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

Зрозуміло, що додавання бібліотеки до проекту має певні накладні витрати, все вище, якщо це перше: робочі процеси повинні бути змінені, іноді навіть інфраструктура і деяким членам команди це може сподобатися (спочатку). Тож переваги вашого рішення очевидні, оскільки це наразі зменшує витрати .

Однак, коли ваш проект зростає, витрати на "псевдобібліотеку" будуть. Припустимо, у вас є "псевдобібліотека", Aяка використовується програмою та тестером одиниць. Кожного разу, коли ви додаєте cpp до A, ви повинні додавати його до обох проектів, інакше вони не зв’язуватимуться.

Що робити, якщо ваша "псевдобібліотека" використовується іншою "псевдобібліотекою" B? Вам доведеться додавати новий cpp у купу проектів більше. А якщо Bперейти на використання іншої бібліотеки? Вам доведеться видалити cpps з Aусіх проектів залежно лише від цього B.

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

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

Тож використання «псевдобібліотеки» може стати першим кроком для розбиття монолітного проекту, але не слід занадто довго чекати, щоб зробити справжню бібліотеку, щоб мати можливість використовувати її переваги.


0

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

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

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

Що робити, якщо в бібліотеці є помилка, і вам потрібно її виправити? Або відбудеться якась статутна чи нормативна зміна, що означає, що ви повинні змінити спосіб роботи бібліотеки?

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

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

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