Я всегда думал, что «общая библиотека» была хорошей идеей. Под этим я подразумеваю библиотеку, которая содержит общую функциональность, которая часто требуется нескольким различным приложениям. Это приводит к меньшему дублированию кода / избыточности.
Я недавно прочитал статью (сейчас не могу найти), в которой говорится, что это на самом деле плохая идея, и зашел так далеко, что сказал, что это «анти-паттерн»
Пока у этого подхода есть свои плюсы. Управление версиями и управление изменениями означает регрессионный тест для набора приложений, использующих эту библиотеку.
Я немного застрял в своем новом проекте (Golang). Дедупликация кода навязывалась мне на протяжении многих лет, но я чувствую, что должен попробовать это на этот раз.
Когда я пишу это, я начинаю думать, что этот подход "общего lib" является результатом скимминга на архитектуре? Возможно, мой дизайн нуждается в большем количестве размышлений?
Интересно услышать мысли.
Ответы:
Библиотеки и повторное использование абсолютно хорошая вещь. У них есть один гигантский недостаток, который заключается в том, что, если не тщательно управлять им, они станут эквивалентом ящика на вашей кухне, который содержит все шансы и результаты, которые никуда не денутся.
Я увидел это в действии, когда стал ответственным за первые порты кода целого бизнес-подразделения (в основном нового для меня) для 64-битных систем и полностью пересмотрел нашу сборку и упаковку, многие из которых делались вручную, а иногда и не очень хорошо. * Мы стремились создать то, что мы поставили, из стека приложений, где клиент сказал бы: «Мне нужна система, которая выполняет A, B, D и F, плюс вещи M и N, что вы еще не сделали, и немного другой клей, объединяющий их всех. " Общим для всего этого была библиотека мусорных ящиков, в которой за пару десятилетий ** накопилось все то, что люди считали пригодным для повторного использования. Короче говоря, часть кода в библиотеке не была, Мы тратили много драгоценного времени на создание и поддержание этих зависимостей только для того, чтобы установить общую библиотеку, а не потому, что они нам действительно нужны.
Мораль в том, что к библиотекам нужно относиться как к классам и не перегружать их слишком большим количеством обязанностей. Не помещайте ваш анализатор JSON в одну библиотеку с функциями линейной алгебры, даже если каждая написанная вами программа использует обе.
Хранение их в тайне имеет много преимуществ, самое большое из которых заключается в том, что он заставляет ваших разработчиков и упаковщиков придумывать подробный отчет о том, что на самом деле нужно их продуктам, вместо того, чтобы просто включать ящик для мусора и багаж, который идет с ним. Когда вы настраиваете систему с использованием собранных пакетов, детальные зависимости гарантируют, что будут установлены только необходимые компоненты. Даже если вы пренебрегаете своим хранилищем и продолжаете компилировать старые, жестокие вещи, ничто из того, что больше не используется, не попадает в то, что вы отправляете.
Конечно, есть исключения,
libc
которые сводят множество функций в одну библиотеку. Это один из случаев, когда преимущества такого подхода можно обосновать, а не слепо прислушиваться к фанатам, которые настаивают на том, что любой другой путь, кроме X , всегда является плохой практикой.* В процессе я обнаружил двоичный файл, который был передан и не был перекомпилирован с нуля в течение шести лет.
** Нет ничего плохого в десятилетнем коде. У нас было несколько критических алгоритмов, которые были настолько хорошо доказаны, что мы были бы дураками, чтобы переписать их исключительно в интересах современности.
источник
Смущающе я представил «общую» библиотеку, названную таковой, в командной среде пару десятилетий назад. Я тогда не очень понимал динамику того, что может случиться в слабо скоординированной команде всего за несколько месяцев.
Когда я представил его, я подумал, что ясно дал понять, а также задокументировал, что для тех вещей, которые мы все согласны, мы находим полезными ежедневно, что она предназначена для минималистской библиотеки, и что библиотека не должна зависеть ни от чего, кроме стандартная библиотека, чтобы ее можно было легко развернуть в новых проектах. В то время я думал, что это было наше собственное небольшое расширение стандартной библиотеки для вещей, которые мы нашли в нашей конкретной области полезными на ежедневной основе.
И все началось достаточно хорошо. Мы начали с математической библиотеки (
common/math*
) подпрограмм, которые мы все использовали ежедневно, так как мы работали в компьютерной графике, которая часто была тяжелой для линейной алгебры. И так как мы часто взаимодействовали с кодом C, мы договорились о некоторых полезных служебных функциях, подобныхfind_index
которым, в отличие отstd::find
в C ++ возвращал бы индекс элемента, найденного в последовательности, вместо итератора, который имитировал работу наших функций C - вещи такого рода - немного эклектичный, но минималистичный и достаточно широко используемый, чтобы оставаться знакомым и практичным для всех и мгновенное знакомство является чрезвычайно важным критерием, поскольку я вижу его в попытке сделать что-то «общее» или «стандартное», поскольку, если оно действительно «общее», оно должно иметь такое знакомое качество в результате широкого принятие и ежедневное использование.Но со временем дизайнерские намерения библиотеки выскользнули из моих пальцев, когда люди начали добавлять вещи, которые они использовали лично, которые, как они думали, могли бы быть полезными для кого-то другого, только для того, чтобы никто другой не использовал их. А позже кто-то начал добавлять функции, которые зависели от OpenGL для общих процедур, связанных с GL. В дальнейшем мы приняли Qt, и люди начали добавлять код, который зависел от Qt, поэтому общая библиотека уже зависела от двух внешних библиотек. В какой-то момент кто-то добавил общие подпрограммы шейдеров, которые зависели от нашей библиотеки шейдеров для конкретного приложения, и в тот момент вы даже не смогли развернуть ее в новом проекте без использования Qt, OGL и нашей библиотеки шейдеров для конкретного приложения и написания нетривиальный скрипт сборки для вашего проекта. Так он превратился в этот эклектичный, взаимозависимый беспорядок.
Но я также обнаружил, обсуждая то, что следует и не следует входить в эту библиотеку, что то, что считается «общим», может легко превратиться в очень субъективную идею, если вы не установите правило очень жесткой линии, что «общее» является что каждый стремится найти полезным на ежедневной основе. Любое ослабление стандартов и быстрое ухудшение от того, что каждый находит полезным каждый день, к чему-то, что один разработчик находит полезным, что может быть полезным для кого-то другого, и в этот момент библиотека очень быстро превращается в эклектичный беспорядок ,
Но, кроме того, когда вы достигнете этой точки, некоторые разработчики могут начать добавлять вещи по той простой причине, что им не нравится язык программирования. Им может не понравиться синтаксис цикла for или вызова функции, после чего библиотека начинает заполняться вещами, которые просто борются с фундаментальным синтаксисом языка, заменяя пару строк простого кода, который на самом деле не является дублирование любой логики до единой краткой строки экзотического кода, знакомого только разработчику, который ввел такое сокращение. Затем такой разработчик может начать добавлять больше функций в общую библиотеку, реализованную с использованием таких сокращений, в этот момент важные разделы общей библиотеки переплетаются с этими экзотическими сокращениями, которые могут показаться красивыми и интуитивно понятными разработчику, который представил его, но уродливым и чуждым и трудным для понимания всеми остальными. И в этот момент я думаю, что вы знаете, что любая надежда на создание чего-то действительно «общего» потеряна, поскольку «общее» и «незнакомое» являются полярно противоположными идеями.
Таким образом, здесь есть все виды червей, по крайней мере, в слабо скоординированной командной среде, с библиотекой с широкими амбициями и обобщенными, как просто «обычно используемые вещи». И хотя основной проблемой, возможно, была слабая координация превыше всего, по крайней мере, несколько библиотек, предназначенных для более специфических целей, таких как библиотека, предназначенная для обеспечения математических процедур и ничего более, вероятно, не будут ухудшаться так значительно с точки зрения ее Проектная чистота и зависимости как «общая» библиотека. Поэтому, оглядываясь назад, я думаю, что было бы гораздо лучше ошибиться в сторону библиотек, которые имеют гораздо более четкие замыслы в дизайне. Я также обнаружил, что на протяжении многих лет узкие по назначению и узкие в применении принципиально разные идеи.
Кроме того, по общему признанию, я, по крайней мере, немного непрактичен, и, может быть, меня слишком волнует эстетика, но то, как я склонен воспринимать свое представление о качестве библиотеки (и, возможно, даже о «красоте»), оценивается скорее по ее слабой связи, чем самое сильное, аналогично тому, что если вы подарили мне самую аппетитную еду в мире, но на той же тарелке положили туда что-то гниющее, которое пахнет очень плохо, я склонен отказаться от всей тарелки. И если вы похожи на меня в этом отношении и делаете что-то, что предлагает всевозможные дополнения как нечто «общее», вы можете обнаружить, что смотрите на эту аналогичную табличку с чем-то гниющим сбоку. Поэтому я также считаю, что хорошо, если библиотека организована, названа и задокументирована таким образом, что со временем приглашать все больше и больше дополнений. И это может даже относиться к вашим личным творениям, так как я, конечно, создал кое-что гнилое тут и там, и оно «портит» намного меньше, если его не добавить в самую большую тарелку. Разделение вещей на маленькие, очень необычные библиотеки также имеет тенденцию к лучшему разделению кода, хотя бы потому, что становится намного менее удобным начинать объединять все.
Что я могу предложить в вашем случае, так это начать с легкости дедупликации кода. Я не говорю о том, чтобы копировать и вставлять большие фрагменты плохо протестированного, подверженного ошибкам кода или что-то в этом роде, или дублировать огромное количество нетривиального кода, который с достаточной вероятностью потребует изменений в будущем.
Но особенно если вы настроены на создание «общей» библиотеки, для которой я предполагаю, что вы хотите создать что-то широко применимое, многократно используемое и, возможно, в идеале то, что вы найдете сегодня столь же полезным, как и десятилетие спустя тогда иногда вам может даже понадобиться или хотеть дублирования для достижения этого неуловимого качества. Потому что дублирование может фактически служить механизмом развязки. Это как если вы хотите отделить видеоплеер от MP3-плеера, то вам, по крайней мере, придется дублировать некоторые вещи, такие как батареи и жесткие диски. Они не могут делиться этими вещами, иначе они неразрывно связаны друг с другом и не могут использоваться независимо друг от друга, и в этот момент люди могут больше не интересоваться устройством, если все, что они хотят, - это воспроизводить MP3. Но через некоторое время после того, как вы разделите эти два устройства друг от друга, вы можете обнаружить, что MP3-плеер может получить выгоду от батареи другого дизайна или жесткого диска меньшего размера, чем видеоплеер, и в этот момент вы больше ничего не дублируете; то, что изначально начиналось как дублирование, позволяющее разделить это взаимозависимое устройство на два отдельных независимых устройства, может позже привести к проектам и реализациям, которые больше не являются избыточными.
Стоит рассмотреть вещи с точки зрения того, кто использует библиотеку. Вы действительно хотите использоватьбиблиотека, которая минимизирует дублирование кода? Скорее всего, вы не будете, потому что тот, который действительно, будет зависеть от других библиотек. И эти другие библиотеки могут зависеть от других библиотек, чтобы избежать дублирования их кода и т. Д., Пока вам не понадобится импортировать / связать 50 разных библиотек, чтобы просто получить некоторые базовые функции, такие как загрузка и воспроизведение аудиофайла, и это становится очень громоздким , Между тем, если такая аудио библиотека намеренно выберет дублирование некоторых вещей здесь и там для достижения своей независимости, ее станет намного проще использовать в новых проектах, и есть вероятность, что ее не нужно будет обновлять почти так же часто, как она победила ». Необходимо изменить в результате изменения одной зависимой от него внешней библиотеки, которая может пытаться выполнить гораздо более обобщенную задачу, чем то, что нужно аудиобиблиотеке.
Поэтому иногда стоит сознательно выбрать немного дублировать (сознательно, никогда не из-за лени - фактически из-за усердия), чтобы отделить библиотеку и сделать ее независимой, потому что благодаря этой независимости она достигает более широкого диапазона практической применимости и даже стабильность (нет больше афферентных муфт). Если вы хотите спроектировать максимально многократно используемые библиотеки, которые продлят вас от одного проекта к следующему и на протяжении многих лет, то в дополнение к сужению его объема до минимума, я бы на самом деле предложил немного продублировать здесь. И, естественно, пишите модульные тесты и убедитесь, что они действительно тщательно протестированы и надежны в том, что они делают. Это только для библиотек, которые вы действительно хотите потратить на обобщение до точки, выходящей далеко за рамки одного проекта.
источник
Существует три различных категории функций, которые вы можете рассмотреть встраивание в библиотеки:
Первая категория - это то, для чего должна существовать стандартная библиотека , но по какой-то причине никто не смог ее создать (или сделал кто-то? Вы тщательно искали?). В этом случае рассмотрите возможность сделать вашу библиотеку открытым исходным кодом. Совместное использование вашей работы не только помогает другим, но и помогает вам, потому что вы будете получать сообщения об ошибках и исправления от других пользователей. Если вы сомневаетесь, что кто-то может внести свой вклад в вашу библиотеку, тогда вы можете иметь дело с функциональностью, которая фактически относится к категории 2 или 3.
Вторая категория - это вещи, которые вам нужны снова и снова, но никто в мире не нуждается в этом. Например, реализация скрытого сетевого протокола для связи с вашей собственной серверной системой. В этом случае, возможно, имеет смысл поместить этот материал во внутреннюю библиотеку, чтобы повысить скорость разработки новых приложений. Просто убедитесь, что на него не слишком сильно влияет ползучесть функций, и он начинает содержать материал, который фактически вписывается в категории 1 или 3. Кроме того, совет Blrfl относительно модульности очень хорош: не создавайте одну монолитную библиотеку Conor Corp. Создайте несколько отдельных библиотек для отдельных функций.
Третья категория - это функциональность, которая настолько проста в реализации, что перенос ее в библиотеку не стоит, или если вы не уверены, что она вам когда-нибудь понадобится именно в такой форме в другом приложении. Эта функциональность должна оставаться частью приложения, для которого она разработана. В случае сомнений, он, вероятно, относится к этой категории.
источник
Почти все языки имеют общую / стандартную библиотеку, поэтому это широко признано хорошей идеей. Использование сторонних библиотек для различных задач, а не повторное изобретение колеса также обычно считается хорошей идеей, хотя в каждом конкретном случае следует оценивать соотношение цена / качество и качество библиотеки.
Затем есть библиотеки «общих утилит», используемые отдельным разработчиком или учреждением в других, не связанных между собой проектах. Это такая библиотека, которую можно считать антишаблоном. В случае, который я видел, эти библиотеки просто копируют функциональность из стандартных библиотек или более известных сторонних библиотек нестандартным и плохо документированным способом.
источник
these libraries just replicate functionality from standard libraries
это не совсем плохо, в javascript вы добавили библиотеки, которые уже реализуют существующие вещи для добавления поддержки старых движков js, у вас также есть библиотеки поддержки Android для старых sdk и т.д ..Большинство библиотек, которыми обмениваются команды, создают больше проблем, чем решают. «Дорога в ад вымощена благими намерениями».
Исключением являются библиотеки, которые удовлетворяют большинству из перечисленного ниже:
В типичных (не запускаемых) компаниях практически нет вышеперечисленных условий для библиотек, совместно используемых группами. Это потому, что большинству команд компании платят за доставку продуктов, а не библиотек. У некоторых компаний есть успешные стратегии совместного использования, такие как Google monorepo, но это связано с очень большими инвестициями в создание и тестирование инфраструктуры.
источник