Смущающе я представил «общую» библиотеку, названную таковой, в командной среде пару десятилетий назад. Я тогда не очень понимал динамику того, что может случиться в слабо скоординированной команде всего за несколько месяцев.
Когда я представил его, я подумал, что ясно дал понять, а также задокументировал, что для тех вещей, которые мы все согласны, мы находим полезными ежедневно, что она предназначена для минималистской библиотеки, и что библиотека не должна зависеть ни от чего, кроме стандартная библиотека, чтобы ее можно было легко развернуть в новых проектах. В то время я думал, что это было наше собственное небольшое расширение стандартной библиотеки для вещей, которые мы нашли в нашей конкретной области полезными на ежедневной основе.
И все началось достаточно хорошо. Мы начали с математической библиотеки ( common/math*
) подпрограмм, которые мы все использовали ежедневно, так как мы работали в компьютерной графике, которая часто была тяжелой для линейной алгебры. И так как мы часто взаимодействовали с кодом C, мы договорились о некоторых полезных служебных функциях, подобных find_index
которым, в отличие отstd::find
в C ++ возвращал бы индекс элемента, найденного в последовательности, вместо итератора, который имитировал работу наших функций C - вещи такого рода - немного эклектичный, но минималистичный и достаточно широко используемый, чтобы оставаться знакомым и практичным для всех и мгновенное знакомство является чрезвычайно важным критерием, поскольку я вижу его в попытке сделать что-то «общее» или «стандартное», поскольку, если оно действительно «общее», оно должно иметь такое знакомое качество в результате широкого принятие и ежедневное использование.
Но со временем дизайнерские намерения библиотеки выскользнули из моих пальцев, когда люди начали добавлять вещи, которые они использовали лично, которые, как они думали, могли бы быть полезными для кого-то другого, только для того, чтобы никто другой не использовал их. А позже кто-то начал добавлять функции, которые зависели от OpenGL для общих процедур, связанных с GL. В дальнейшем мы приняли Qt, и люди начали добавлять код, который зависел от Qt, поэтому общая библиотека уже зависела от двух внешних библиотек. В какой-то момент кто-то добавил общие подпрограммы шейдеров, которые зависели от нашей библиотеки шейдеров для конкретного приложения, и в тот момент вы даже не смогли развернуть ее в новом проекте без использования Qt, OGL и нашей библиотеки шейдеров для конкретного приложения и написания нетривиальный скрипт сборки для вашего проекта. Так он превратился в этот эклектичный, взаимозависимый беспорядок.
Но я также обнаружил, обсуждая то, что следует и не следует входить в эту библиотеку, что то, что считается «общим», может легко превратиться в очень субъективную идею, если вы не установите правило очень жесткой линии, что «общее» является что каждый стремится найти полезным на ежедневной основе. Любое ослабление стандартов и быстрое ухудшение от того, что каждый находит полезным каждый день, к чему-то, что один разработчик находит полезным, что может быть полезным для кого-то другого, и в этот момент библиотека очень быстро превращается в эклектичный беспорядок ,
Но, кроме того, когда вы достигнете этой точки, некоторые разработчики могут начать добавлять вещи по той простой причине, что им не нравится язык программирования. Им может не понравиться синтаксис цикла for или вызова функции, после чего библиотека начинает заполняться вещами, которые просто борются с фундаментальным синтаксисом языка, заменяя пару строк простого кода, который на самом деле не является дублирование любой логики до единой краткой строки экзотического кода, знакомого только разработчику, который ввел такое сокращение. Затем такой разработчик может начать добавлять больше функций в общую библиотеку, реализованную с использованием таких сокращений, в этот момент важные разделы общей библиотеки переплетаются с этими экзотическими сокращениями, которые могут показаться красивыми и интуитивно понятными разработчику, который представил его, но уродливым и чуждым и трудным для понимания всеми остальными. И в этот момент я думаю, что вы знаете, что любая надежда на создание чего-то действительно «общего» потеряна, поскольку «общее» и «незнакомое» являются полярно противоположными идеями.
Таким образом, здесь есть все виды червей, по крайней мере, в слабо скоординированной командной среде, с библиотекой с широкими амбициями и обобщенными, как просто «обычно используемые вещи». И хотя основной проблемой, возможно, была слабая координация превыше всего, по крайней мере, несколько библиотек, предназначенных для более специфических целей, таких как библиотека, предназначенная для обеспечения математических процедур и ничего более, вероятно, не будут ухудшаться так значительно с точки зрения ее Проектная чистота и зависимости как «общая» библиотека. Поэтому, оглядываясь назад, я думаю, что было бы гораздо лучше ошибиться в сторону библиотек, которые имеют гораздо более четкие замыслы в дизайне. Я также обнаружил, что на протяжении многих лет узкие по назначению и узкие в применении принципиально разные идеи.
Кроме того, по общему признанию, я, по крайней мере, немного непрактичен, и, может быть, меня слишком волнует эстетика, но то, как я склонен воспринимать свое представление о качестве библиотеки (и, возможно, даже о «красоте»), оценивается скорее по ее слабой связи, чем самое сильное, аналогично тому, что если вы подарили мне самую аппетитную еду в мире, но на той же тарелке положили туда что-то гниющее, которое пахнет очень плохо, я склонен отказаться от всей тарелки. И если вы похожи на меня в этом отношении и делаете что-то, что предлагает всевозможные дополнения как нечто «общее», вы можете обнаружить, что смотрите на эту аналогичную табличку с чем-то гниющим сбоку. Поэтому я также считаю, что хорошо, если библиотека организована, названа и задокументирована таким образом, что со временем приглашать все больше и больше дополнений. И это может даже относиться к вашим личным творениям, так как я, конечно, создал кое-что гнилое тут и там, и оно «портит» намного меньше, если его не добавить в самую большую тарелку. Разделение вещей на маленькие, очень необычные библиотеки также имеет тенденцию к лучшему разделению кода, хотя бы потому, что становится намного менее удобным начинать объединять все.
Дедупликация кода навязывалась мне на протяжении многих лет, но я чувствую, что должен попробовать это на этот раз.
Что я могу предложить в вашем случае, так это начать с легкости дедупликации кода. Я не говорю о том, чтобы копировать и вставлять большие фрагменты плохо протестированного, подверженного ошибкам кода или что-то в этом роде, или дублировать огромное количество нетривиального кода, который с достаточной вероятностью потребует изменений в будущем.
Но особенно если вы настроены на создание «общей» библиотеки, для которой я предполагаю, что вы хотите создать что-то широко применимое, многократно используемое и, возможно, в идеале то, что вы найдете сегодня столь же полезным, как и десятилетие спустя тогда иногда вам может даже понадобиться или хотеть дублирования для достижения этого неуловимого качества. Потому что дублирование может фактически служить механизмом развязки. Это как если вы хотите отделить видеоплеер от MP3-плеера, то вам, по крайней мере, придется дублировать некоторые вещи, такие как батареи и жесткие диски. Они не могут делиться этими вещами, иначе они неразрывно связаны друг с другом и не могут использоваться независимо друг от друга, и в этот момент люди могут больше не интересоваться устройством, если все, что они хотят, - это воспроизводить MP3. Но через некоторое время после того, как вы разделите эти два устройства друг от друга, вы можете обнаружить, что MP3-плеер может получить выгоду от батареи другого дизайна или жесткого диска меньшего размера, чем видеоплеер, и в этот момент вы больше ничего не дублируете; то, что изначально начиналось как дублирование, позволяющее разделить это взаимозависимое устройство на два отдельных независимых устройства, может позже привести к проектам и реализациям, которые больше не являются избыточными.
Стоит рассмотреть вещи с точки зрения того, кто использует библиотеку. Вы действительно хотите использоватьбиблиотека, которая минимизирует дублирование кода? Скорее всего, вы не будете, потому что тот, который действительно, будет зависеть от других библиотек. И эти другие библиотеки могут зависеть от других библиотек, чтобы избежать дублирования их кода и т. Д., Пока вам не понадобится импортировать / связать 50 разных библиотек, чтобы просто получить некоторые базовые функции, такие как загрузка и воспроизведение аудиофайла, и это становится очень громоздким , Между тем, если такая аудио библиотека намеренно выберет дублирование некоторых вещей здесь и там для достижения своей независимости, ее станет намного проще использовать в новых проектах, и есть вероятность, что ее не нужно будет обновлять почти так же часто, как она победила ». Необходимо изменить в результате изменения одной зависимой от него внешней библиотеки, которая может пытаться выполнить гораздо более обобщенную задачу, чем то, что нужно аудиобиблиотеке.
Поэтому иногда стоит сознательно выбрать немного дублировать (сознательно, никогда не из-за лени - фактически из-за усердия), чтобы отделить библиотеку и сделать ее независимой, потому что благодаря этой независимости она достигает более широкого диапазона практической применимости и даже стабильность (нет больше афферентных муфт). Если вы хотите спроектировать максимально многократно используемые библиотеки, которые продлят вас от одного проекта к следующему и на протяжении многих лет, то в дополнение к сужению его объема до минимума, я бы на самом деле предложил немного продублировать здесь. И, естественно, пишите модульные тесты и убедитесь, что они действительно тщательно протестированы и надежны в том, что они делают. Это только для библиотек, которые вы действительно хотите потратить на обобщение до точки, выходящей далеко за рамки одного проекта.