Мне трудно понять, почему вы должны разрабатывать внутренние библиотеки, которые будут использоваться исключительно для разработки внутренних приложений. Я ценю, что если я хочу использовать программное обеспечение, написанное кем-то за пределами организации, тогда они могут прислать мне свои заголовочные файлы и файлы .a или .so, и я могу просто связать его с моим проектом (при условии, что они скомпилированы в одной среде) ,
Но почему следует разрабатывать внутреннюю библиотеку, чтобы она была связана с внутренним приложением, когда у меня есть доступ к заголовочным файлам и файлам реализации, и я могу просто включить их в дерево исходных текстов и собрать их все вместе?
Другими словами: если какой-то исходный код написан, как вы решаете, должен ли он быть скомпилирован в двоичную библиотеку и связан с вашим приложением или просто включен в исходные файлы проекта и регулярно компилироваться?
Когда я говорю «включить» файлы в каждый проект, я не имею в виду копировать и вставлять каждый файл в исходное дерево разрабатываемого в настоящее время проекта. Я имею в виду разработку некоторого каталога / библиотеки (отдельной для любого проекта), содержащей общий исходный код, который может быть включен в файлы проекта обычным способом, например #include.
ps Я говорю здесь о разработке c / c ++ для нескольких настольных приложений.
Ответы:
Существует множество причин для создания библиотек и общих библиотек (в файлах .dll или .so) даже для внутреннего использования:
В некоторых компаниях даже существует практика бухгалтерского учета, при которой проекты, создающие библиотеки, получают определенную компенсацию за каждое повторное использование.
источник
Некоторые другие возможные причины, которые могут относиться к более крупным нетривиальным проектам:
Время компиляции: огромные монолитные проекты C ++ с тысячами файлов, тысячами классов, функций и т. Д. Могут очень долго компилироваться (что снижает производительность, если вы хотите перекомпилировать каждый раз, когда вы меняете несколько строк кода). Статически связанные и динамически связанные библиотеки компилируются независимо, и их не нужно перекомпилировать, если их источник не изменился.
Логическое разделение отдельных модулей или подсистем . С большими системами обычно легче управлять, если отдельные области функциональности размещены в отдельных модулях, и разработчики не сталкиваются с поиском в огромных папках / проектах, содержащих тысячи файлов / классов.
Границы между разработчиками / командами : разработчики, создающие отдельные новые функциональные возможности одновременно, могут уменьшить вероятность конфликтов слияния, если возможно, чтобы каждый разработчик работал в разных модулях.
Код, который нельзя выпускать в живую среду : например, библиотеки модульных тестов или «фиктивные» библиотеки, которые используются для тестирования разработчиками для замены компонента работающей системы (аппаратного обеспечения, API, удаленных систем, баз данных и т. Д.)
Флаги компилятора : если вы оказались в очень неудачном положении для интеграции с каким-либо сторонним API, который ожидает странный флаг компилятора, то библиотека может быть «слоем дезактивации», расположенным между сторонним API и остальной частью приложения.
Дополнительные функции / Оптимизация . В больших системах приложение может подождать, прежде чем загружать определенные динамически связанные модули в память во время выполнения, если они не являются критическими для основных функций приложения.
В целом, многие внутренние проекты часто представляют собой небольшие микроприложения, которые не получают выгоды от разделения на отдельные библиотеки. Если вы работаете над крошечным проектом как одинокий разработчик, вам не нужно беспокоиться о разделении вашего кода на библиотеки (пока ...). Не забывайте принцип ЯГНИ .
источник
Ваш оригинальный вопрос мог вызвать недоразумение для большинства других ответов. Поскольку вы намереваетесь не копировать существующий код между проектами, а включать одни и те же исходные файлы из разных проектов в качестве ссылок , любой аргумент «дублирующего кода» становится бессмысленным, как и многие другие представленные аргументы.
Обратите внимание, что это иногда (не всегда) разумный метод . Фактически, когда вы помещаете все исходные файлы, которые вы хотите использовать в разных проектах, в одну отдельную папку include, вы уже создали библиотеку - библиотеку исходного кода, а не двоичную библиотеку. Особенно в C ++, при создании универсальных библиотек с шаблонами, нет ничего необычного в том, чтобы иметь библиотеки с заголовками, которые просто нуждаются в простом включении, и не требуют отдельной подготовки к связыванию.
Поэтому я думаю, что ваш реальный вопрос - когда создавать библиотеки с исходным кодом или когда предпочитать предварительно скомпилированные двоичные библиотеки? В этом более старом ответе на этом сайте я обсуждал некоторые плюсы и минусы библиотек только для заголовков, возможно, это поможет вам. Основное преимущество библиотек с исходным кодом состоит в том, что они не требуют компиляции с теми же флагами времени выполнения и / или совместимыми компиляторами / компоновщиками, что и приложение, которое их использует. Недостатками являются дополнительное время компиляции и требование предоставления доступа к исходному коду (что, очевидно, не является проблемой для типа «внутренних» проектов, которые вы имеете в виду).
источник
Я согласен с другими комментаторами, когда они пишут, что вы не должны дублировать код. В вашем случае, однако, кажется, что вы (или люди, с которыми вы работаете) создаете библиотеки для кода, который не дублируется в другом месте.
В этом случае я предостерегаю от преждевременного обобщения . Часто бывают случаи, когда кажется, что кусок кода можно использовать повторно. Однако, не зная подробных сведений о том, как второй вариант использования будет использовать такой код, очень легко тратить дополнительное время на функции «повторного использования», которые на самом деле не будут полезны в дополнительных случаях, или делать предположения, которые оказываются неверными в второй случай.
Написание «библиотеки» для одного варианта использования может превратиться в очень дорогое занятие без какой-либо отдачи - меня это укусило несколько раз.
Пример стоимости:
Мое общее правило: не превращайте код в библиотеку, если у меня нет как минимум 2 отдельных мест, где требуется код.
источник
Потому что, если вы «просто включаете их в мое дерево исходных текстов », вы дублируете код .
Проблема в том, что вы не получите никаких улучшений (включая критические исправления), сделанных проектом, из которого вы скопировали код, и они не получат никаких преимуществ от ваших улучшений.
Вы можете подумать, что вы можете решить эту проблему, просто регулярно копируя новейшую версию кода в дерево исходных текстов, возможно, даже автоматически, используя подмодуль в git или что-то подобное. Но из-за несовместимых изменений API вы будете постоянно ломать сборку. Библиотека, с другой стороны, имеет «официальный» публичный API, который, как ее разработчики знают, не может быть изменен без советов с клиентами.
Наконец, могут быть технические причины - может ли быть необходимо сохранить часть кода в виде библиотеки, чтобы его можно было загружать по желанию или даже загружать и выгружать по требованию и, таким образом, сокращать использование памяти, когда функциональность не нужна?
источник
Я хотел бы остановиться на расходах, которые ваше решение имеет в долгосрочной перспективе.
Очевидно, что добавление библиотеки в проект сопряжено с некоторыми накладными расходами, все выше, если это первое: рабочие процессы должны быть изменены, иногда даже инфраструктуре и некоторым членам команды это может не понравиться (сначала). Таким образом, преимущества вашего решения очевидны, поскольку теперь оно требует меньших затрат .
Однако по мере роста вашего проекта возрастут и затраты на «псевдо-библиотеку». Предположим, у вас есть «псевдо-библиотека»,
A
которая используется приложением и модульным тестером. Каждый раз, когда вы добавляете cppA
, вы должны добавить его в оба проекта, иначе они не будут ссылаться.Что если ваша «псевдо-библиотека» используется другой «псевдо-библиотекой»
B
? Вы должны добавить свой новый cpp в кучу проектов больше. А еслиB
перейти на использование другой библиотеки? Вам придется удалить cpps изA
всех проектов в зависимости только отB
.Это все будет бесплатно, если будет использоваться настоящая библиотека. Таким образом, вопрос в том, сколько cpps необходимо, чтобы оправдать переход к реальной библиотеке?
Но подождите, есть еще больше залога: разработчику не нравится эта глупая работа по поиску всех проектов, нуждающихся в новом cpp, и он добавляет свой код / классы где-то в уже существующие файлы, что не очень хорошо в долгое время.
Таким образом, использование «псевдо-библиотеки» может стать первым шагом к разрушению монолитного проекта, но вам не следует слишком долго ждать, чтобы сделать ее настоящей библиотекой, чтобы иметь возможность использовать ее преимущества.
источник
Если библиотека когда-либо используется только одним приложением, то вам, скорее всего, она не нужна как отдельная библиотека.
Если библиотека используется 3500 приложений , то вы абсолютно сделать это нужно как отдельную библиотеку.
Что если в библиотеке есть ошибка и вам нужно ее исправить? Или происходят какие-то законодательные или нормативные изменения, которые означают, что вы должны изменить способ работы библиотеки?
Если она находится в отдельной библиотеке, вы можете (потенциально) исправить библиотеку, повторно протестировать ее и повторно развернуть, и каждое приложение получит выгоду от исправления.
Если это только в исходном коде «локально» для каждого приложения, то вам нужно изменить, пересобрать, повторно протестировать и заново развернуть каждое приложение в отдельности . Это гораздо большее (то есть более дорогое) упражнение.
источник