Общие библиотеки в большой команде

Предположим, у вас есть пять продуктов, и все они используют одну или несколько внутренних библиотек компании, написанную отдельными разработчиками.

Это звучит просто, но на практике я считаю, что его очень сложно поддерживать.

Как вы справляетесь со следующими сценариями:

  • Разработчик непреднамеренно вводит ошибку и разбивает все на производстве.

  • Каждая библиотека должна созревать. Это означает, что API должен развиваться, и как вы развертываете обновленную версию для производства, если каждый разработчик должен обновлять/тестировать свой код, пока они чрезвычайно заняты другими проектами? Это проблема ресурса и времени?

  • Контроль версий, их развертывание и использование. Вы сохранили бы это в одном глобальном местоположении или заставляли бы каждый проект использовать, скажем, svn: externals, чтобы "связать" библиотеку?

Я обнаружил, что очень сложно разработать хорошую стратегию. Моя собственная теория домашних животных такова:

  • В каждой общей библиотеке должен быть супер-тщательный набор тестов, иначе он должен никогда быть обычным, даже если это означает, что кто-то еще дублирует усилия. Дублированный непроверенный код лучше, чем обычный непроверенный код (вы разбиваете только один проект).

  • Каждая общая библиотека должна иметь выделенный сопровождающий (может быть компенсирована действительно хорошим набором тестов в меньшей команде).

  • Каждый проект должен проверить версию библиотеки, которая, как известно, работает с ней. Это означает, что разработчику не нужно отвлекаться на обновление использования API, поскольку общий код обновляется. Каким он будет. Каждая нетривиальная часть кода развивается в течение нескольких месяцев и лет.

Спасибо за ваши мысли об этом!

Ответы

Ответ 1

У вас есть конкурирующий набор целей. Во-первых, библиотека компонентов многократного использования должна быть достаточно открытой, чтобы люди из других проектов могли легко добавить к ней (или представить компоненты к ней). Если для них это слишком сложно, они будут создавать свои собственные библиотеки и игнорировать общий, что приведет к большому дублированию кода и усилиям, потраченным впустую. С другой стороны, вы хотите контролировать развитие библиотеки, чтобы обеспечить ее качество.

Я был в этом положении. Там нет простого ответа. Однако есть некоторые эвристики, которые могут помочь.

  • Рассматривайте библиотеку как внутренний проект. Периодически отпускайте его. Убедитесь, что он имеет четко определенную процедуру выпуска, в комплекте с модульными испытаниями и контролем качества. И, самое главное, часто выпускайте, так что новые материалы в библиотеке часто появляются в продукте.
  • Предоставлять стимулы для людей вносить вклад в библиотеку, а не создавать собственные внутренние библиотеки.
  • Помогите людям внести вклад в библиотеку и сделайте критерии четкими и четко определенными (например, новые классы должны иметь модульные тесты и документацию).
  • Поместите одного или двух разработчиков, отвечающих за библиотеку, и (ВАЖНО!) выделите время для их работы над ним. Библиотека, которая рассматривается как запоздалая мысль, быстро станет запоздалой мыслью.

Короче говоря, смоделируйте разработку и обслуживание вашей внутренней библиотеки после успешного проекта библиотеки с открытым исходным кодом.

Ответ 2

Я не согласен с этим:

Повторяющийся непроверенный код лучше, чем общий непроверенный код (вы нарушаете только один проект).

Если вы все равно создадите ошибки, реализуя одно и то же, тогда вам все придется исправить потенциально разные ошибки в каждом экземпляре "дублированной" библиотеки.

Также кажется, что было бы намного быстрее/дешевле писать библиотеку один раз, и вместо того, чтобы несколько других команд пишут одно и то же, у вас есть ресурсы, выделенные для тестирования.


Теперь, чтобы решить вашу актуальную проблему: я бы подражал тем, что мы делаем с настоящими сторонними библиотеками. Мы используем конкретную версию до тех пор, пока не будем готовы или не должны обновляться. Я не обновляю все только потому, что могу - должна быть причина.

Как только я вижу эту причину (исправление ошибок, новая функция и т.д.), я обновляюсь с риском того, что новая библиотека может иметь новые ошибки или нарушать изменения.

Итак, вы - проект библиотеки, по мере необходимости продолжаете разработку, не затрагивая отдельных команд, пока они не будут готовы "обновить".

Вы можете публиковать релизы или peg/branches/tag svn, чтобы помочь со всем этим.

Если все команды имеют доступ к трекеру ошибок, они могут легко увидеть, какие известные проблемы существуют в кандидате на обновление, прежде чем они будут обновлены. Или вы можете сохранить этот список самостоятельно.

@Brian Clapper предоставляет некоторые отличные рекомендации о том, как запустить вашу библиотеку в качестве проекта в его ответе.

Ответ 3

Я работал в аналогичной ситуации с тем, что вы описываете, только у моей компании были десятки программных продуктов. Я работал над командой, которая отвечала за поддержание и обновление основного набора библиотек, которые все остальные использовали.

Мы рассмотрели эти сценарии следующим образом:

  • Проверяйте червь из основных библиотек. Поддержание дублирующего кода - это кошмар. Вы не просто поддерживаете ядро ​​и одну копию. Где-то в вашем источнике управления источником есть несколько копий одного и того же кода. У нас было множество продуктов, так что это означало бы десятки копий. Охоть их и убить.

  • У нас была небольшая команда из 10-12 разработчиков, посвященная поддержке основной библиотеки и ее наборов тестов. Мы также отвечали за то, чтобы вызывать вызовы от других 1100 разработчиков в компании о том, как использовать основную библиотеку, так как вы можете себе представить, мы были очень заняты.

  • Каждый другой проект должен работать с версией основной библиотеки, с которой, как известно, работает. Вы можете использовать ветки управления версиями для тестирования новых выпусков основной библиотеки со старыми продуктами, чтобы убедиться, что вы не нарушаете код, который работает. Если основная команда проводит тщательную проверку, это должно идти очень гладко. Единственный раз, когда это когда-либо осложнялось для нас, было то, когда основной API изменился, или когда мы плотно прикрутили что-то. Даже если вы очень уверены в своем основном тестировании, используйте ветки для тестирования отдельных продуктов.

Ответ 4

Я согласен - это сложно. В нашей небольшой команде (консалтинг, а не в продуктовой компании - это делало это сложнее), у нас был один общий компонент, который выделялся среди других. В этом случае рецепт успеха был:

  • Сделать хорошего разработчика ответственным за разработку компонента
  • Сделайте хорошего разработчика привратником для поддержки компонента
  • Убедитесь, что все обновления (их было несколько) совместимы с обратными
  • Убедитесь, что есть некоторая базовая документация (или простое справочное приложение), объясняющее, как этот компонент должен использоваться
  • Убедитесь, что все разработчики знают, что компонент существует (!) и где он может его найти (вместе с кодом, если они хотят его просмотреть)

Предоставьте разработчикам возможность просматривать код и предлагать лучшие реализации или ректоринг, но окончательные моды проходят через опытного гейткипера. Когда компонент был обновлен, старые приложения не нуждались в обновлении. Если бы мы сделали новый выпуск, мы оценили, хотим ли мы обновиться, и если бы мы это сделали, все, что нам нужно было сделать, это своп библиотек - никакого кода, необходимого для изменения, если мы не хотим использовать некоторые новые функции, доступные при обновлении. Сопротивление неизбежно, но иногда это хороший вид сопротивления, когда он исходит от хороших разработчиков, у которых есть лучшие идеи для нового поколения или реорганизованного компонента.

Ответ 5

Рассматривайте развитие библиотек как любой другой продукт. Каждая библиотека имеет свой собственный репозиторий, собственные версии и номера версий. Скомпилированные и официально протестированные версии библиотеки также хранятся в репозитории. Функции документа и изменения от версии к версии.

Затем используйте библиотеки, как если бы вы использовали сторонние библиотеки. В вашем продукте используются только фиксированные версии скомпилированных библиотек. Переходите к новой версии, когда вам действительно нужно, и имейте в виду, что это требует большего тестирования. Добавьте версии, которые вы используете для контроля версий.

Когда вы обнаружите ошибку или требуете новой функции в библиотеке, создается новая версия или под-версия. Использование системы управления версиями, такой как svn, делает это проще. Когда вам нужен исходный код для целей отладки, экспортируйте его и включите в свои проекты, но не меняйте его там, но исправляйте проблемы в репозиториях библиотек.

Таким образом, каждая команда может вносить вклад в библиотеки, не подвергая опасности работу других команд. Переключение версий выполняется намеренно и не случайно.

Ответ 6

Создайте слой Anti-коррупции (DDD) для существующей библиотеки... это не что иное, как фасад... а затем напишите unit-test для этого слоя антикоррупции... Теперь даже если кто-то обновит или обновит библиотеку, которую вы знаете, если что-то сломано, выполнив модульные тесты...

Эти тесты могут также служить документацией по контракту... и не каждый проект, который должен использовать библиотеку, должен писать этот слой с антикоррупцией, если они используют ту же самую точную функциональность.

Ответ 7

" Дублирование - это корень всего зла

Звучит так, как вам нужно:

  • Хранилище артефактов, такое как Ivy, чтобы вы могли совместно использовать библиотеки и версии с различием между версиями, которые являются стабильными API и которые "созревают"
  • Тесты для библиотек
  • Тесты для проектов, использующих их
  • Система непрерывной интеграции, так что, когда вводится несовместимость или ошибка, как проект, так и разработчик исходной библиотеки уведомляются

Ответ 8

Я думаю, что одна общая библиотека лучше, чем 3 дубликаты (и 1 тест определенно лучше, чем 3 непроверенных). Это связано с тем, что, когда вы находите и исправляете проблему, это делает всю область приложения более твердой разработка и обслуживание более эффективны).

Кстати, это одна из причин (помимо внесения вклада сообществу), почему наша компания предоставляет наши .NET общие библиотеки для общественности как открытый источник.

Плюс, там меньше кода для записи. И вы можете назначить одного разработчика для обеспечения надлежащей практики развития в библиотеке и ее использованиях (т.е. Посредством кодовых контрактов, применяемых при модульных тестах в библиотечных приложениях). Этот улучшает качество и снижает затраты на обслуживание.

Мы сохраняем общие библиотеки в качестве двоичных файлов в решении. Это вытекает из логического требования, что любое решение должно быть атомарным и независимым (это исключает ссылки svn: externals).

Совместимость API не является проблемой вообще. Просто позвольте вашему серверу интеграции перестроить и протестировать весь стек продукта (при обновлении всех внутренних ссылок и распространении изменений), и вы всегда будете уверены, что все внутренние API являются прочными. И кто бы ни ломался, API должен либо исправить, либо обновить обычаи.

Ответ 9

Дублирование - это корень всех злых

Я бы сказал, что неконтролируемое правительство является корнем всего зла:)

Я получаю много флэка, даже предлагая, чтобы дублирование было опцией. Я понимаю, почему, но позвольте мне немного усложнить это.

Скажем, у вас довольно большая библиотека, которая на самом деле ничего не делает, в частности - это всего лишь набор утилит. НЕТ тестов для этой библиотеки - вообще. Вам нужна только одна функция. Скажем, что-то, что разбирает расширение файла.

Pop quiz: вы просто пишете что-то такое же маленькое, как это в своем собственном проекте, или вы кусаете пулю и используете бесплатный набор для непроверенных наборов утилит, которые будут нарушать ваше приложение, если кто-то нарушит функцию?

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

Дублирование больших систем, таких как регистрация клиентов, конечно же, было бы глупо за пределами убеждений. Однако нет ли случаев, когда безопаснее дублировать что-то довольно маленькое в вашем проекте, если альтернатива недостаточно безопасна (нет системы для поддержания общего кода).

Подумайте об этом таким образом - и это происходит все время - несколько подрядчиков, работающих над разными проектами, для той же компании. Они даже не знают друг о друге.

Мой аргумент таков:

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

Вам будет необходимо использовать большие существующие системы, которые просто не могут быть дублированы.

Ответ 10

Дублирование больших систем - например, регистрация клиента - будет немой вне веры,

Вот почему эти системы публикуют внешние интерфейсы.

Если вы определяете библиотеку как общий код между проектами: по моему опыту это почти всегда плохо. Проект должен быть автономным, а обновления для одного проекта не должны влиять на другие проекты.

Даже если вы начнете с библиотек, вы все равно будете дублировать код. Хотите исправить проект 1? Он был выпущен с библиотекой 1.34, поэтому, чтобы исправление было как можно меньше, вы вернетесь в библиотеку 1.34 и исправите это. Но эй... теперь вы сделали точно, что библиотека должна была избегать - вы продублировали код.

Каждый разработчик использует Google, чтобы найти код и скопировать его в свое приложение. Скорее всего, они обнаружили, что Qaru в первую очередь. Представьте себе, что произойдет, если Stackoverflow опубликует библиотеки вместо фрагментов кода, и вы получите представление о проблемах, которые затрагивают многих хороших разработчиков библиотеки.

Библиотеки, как правило, являются общими решениями конкретных проблем. Как правило, общее решение является более сложным, чем сумма двух конкретных решений. Это означает, что вам нужен один хороший программист для решения проблемы, которая могла быть решена двумя идиотами. Звучит как плохая компромисс для меня: D

Ответ 11

Я хотел бы указать проблему в решениях, предложенных выше: обработка библиотеки как внутреннего проекта с помощью собственной схемы управления версиями.

Проблема

Если ваша компания имеет более одного продукта (скажем, две команды - два продукта: A, B), каждый продукт имеет свой собственный график выпуска. Приведем пример: команда A работает над продуктом A v1.6. Их расписание релизов через две недели (предположим, 30 октября). Команда B работает над продуктом B v2.4. Их график выпуска составляет 1,5 месяца - 30 ноября. Предположим, что оба работают на acme-commons-1.2-SNAPSHOT. Оба добавляют изменения в acme-commons, поскольку они в этом нуждаются. За пару дней до 30 октября команда B представит изменение, которое является ошибкой, до acme-commons-1.2-SNAPSHOT. Команда A переходит в режим стресса, так как обнаруживает ошибку за 1 день до замораживания кода.

Этот сценарий показывает, что рассматривать общую библиотеку в качестве сторонней библиотеки практически невозможно. Тривиальное, но проблематичное решение - для каждой команды иметь свою собственную версию версии, которую они собираются изменить. Например, продукт A v1.2 создаст ветку (и версию) для acme-commons с именем "1.2-A-1.6". Команда B также создаст филиал в акме-сообществах под названием "1.2-B-2.4". Их развитие никогда не столкнется, и они будут свободны от стресса, как только они проведут тестирование своего продукта.

Конечно, кому-то придется объединить свои изменения обратно в исходную ветвь (скажем, мастер или 1.2).

Проблемы, которые я нашел с этим решением:

  • Отражательная инфляция - древовидная структура будет очень пухлой, и будет сложнее понять поток изменений/слияний.
  • Слишком рано вернуться к 1.2, вероятно, никогда не произойдет. Если команда или разработчик не посвящена этой библиотеке, шансы, что команда A или команда B скомбинируют свой код обратно в 1.2, являются тонкими. Они всегда будут сосредоточены на своих задачах, создавая и используя свое собственное пространство. Распределение разработчика/команды дорого, поэтому не всегда является жизнеспособным решением.

Я все еще пытаюсь понять это, поэтому любые мысли по этому поводу приветствуются