Общие библиотеки в большой команде - PullRequest
15 голосов
/ 10 января 2009

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

Звучит просто, но на практике я обнаружил, что очень трудно поддерживать.

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

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

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

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

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

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

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

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

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

Ответы [ 11 ]

13 голосов
/ 10 января 2009

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

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

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

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

5 голосов
/ 10 января 2009

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

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

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

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


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

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

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

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

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

@ Брайан Клэппер дает несколько прекрасных рекомендаций о том, как запустить вашу библиотеку как проект, в его ответе .

2 голосов
/ 10 января 2009

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

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

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

2 голосов
/ 10 января 2009

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

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

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

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

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

1 голос
/ 10 января 2009

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

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

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

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

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

1 голос
/ 10 января 2009

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

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

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

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

0 голосов
/ 01 октября 2010

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

Проблема

Если в вашей компании более одного продукта (скажем, две команды - два продукта: 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 также создаст ветку в acme-commons под названием «1.2-B-2.4». Их развитие никогда не столкнется, и они будут свободны от стресса, как только они протестируют свой продукт.

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

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

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

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

0 голосов
/ 15 января 2009

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

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

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

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

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

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

0 голосов
/ 10 января 2009

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

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

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

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

Популярная викторина: вы просто пишете что-то маленькое в своем собственном проекте, или вы кусаете пулю и используете бесплатный для всех набор утилит, который НЕ БУДЕТ сломать ваше приложение, если кто-то нарушит функцию?

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...