Вопрос

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

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

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

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

Это было полезно?

Решение

Я являюсь автором цитаты из вопроса, которая пришла от предыдущий ответ.

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

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

В дальнейшем пояснении моего комментария позвольте мне сначала сказать, что существуют "безопасные" способы использования svn:external-подобная функция, как и в случае с любым другим инструментом или функцией.Тем не менее, я отношусь к этому как к антипаттерн потому что эта функция с гораздо большей вероятностью будет использована не по назначению.По моему опыту, им всегда пользовались не по назначению, и я считаю маловероятным, что когда-либо смогу использовать его таким безопасным способом и никогда не порекомендую такое использование.Пожалуйста, также обратите внимание, что я НЕ хочу принижать команду Subversion - мне нравится Subversion, хотя я планирую перейти на Bazaar.

Основная проблема с этой функцией заключается в том, что она поощряет и обычно используется для прямой ссылки исходного кода одной сборки ("проекта") на исходный код другой или для привязки проекта к двоичному файлу (DLL, JAR и т.д.), От которого он зависит.Ни одно из этих применений не является разумным, и они представляют собой антипаттерн.

Как я уже говорил в своем другом ответе, я считаю, что важным принципом при сборке программного обеспечения является то, что каждый проект создает ровно ОДИН двоичный или первичный результат.Это можно рассматривать как применение принципа разделение интересов к процессу сборки.Это особенно верно в отношении одного проекта, непосредственно ссылающегося на источник другого, что также является нарушением принципа инкапсуляция.Другой формой такого рода нарушения является попытка создать иерархию сборки для построения целой системы или подсистемы путем рекурсивного вызова вспомогательных сборок.Maven настоятельно поощряет / применяет такое поведение, что является одной из многих причин, по которым я его не рекомендую.

Наконец, я нахожу, что существуют различные практические вопросы, которые делают эту функцию нежелательной.Для одного, svn:external обладает некоторыми интересными поведенческими характеристиками (но подробности пока ускользают от меня).С другой стороны, я всегда нахожу, что мне нужно, чтобы такие зависимости были явно видны моему проекту (процессу сборки), а не скрыты как некоторые метаданные системы управления версиями.

Итак, каков "безопасный" способ использования этой функции?Я бы счел, что это когда он временно используется только одним человеком, например, как способ "настроить" рабочую среду.Я мог видеть, где программист может создать свою собственную папку в репозитории (или по одной для каждого программиста), где он будет настраивать svn:external ссылки на различные другие части репозитория, над которыми они в настоящее время работают.Затем проверка этой папки создаст рабочую копию всех их текущих проектов.Когда проект добавлен или завершен, svn:external определения могут быть скорректированы, а рабочая копия соответствующим образом обновлена.Однако я предпочитаю подход, который не привязан к конкретной системе управления версиями, например, делать это с помощью скрипта, который вызывает проверки.

Для справки, в последний раз я столкнулся с этой проблемой летом 2008 года у клиента-консультанта, который использовал svn:external в массовом масштабе ВСЕ было сшито для создания единой основной рабочей копии.Их скрипты сборки на основе Ant & Jython (для WebLogic) были созданы поверх этой основной рабочей копии.Конечный результат:НИЧТО не могло быть построено автономно, существовали буквально десятки подпроектов, но ни один из них не был безопасен для проверки / работы сам по себе.Поэтому любая работа в этой системе сначала требовала проверки / обновления более 2 ГБ файлов (они также помещали двоичные файлы в репозиторий).Добиваться чего-либо было бесполезным упражнением, и я ушел после трехмесячных попыток (там также присутствовало много других антипаттернов).

Редактировать:Подробнее о рекурсивных сборках -

На протяжении многих лет (особенно в последнее десятилетие) я создавал масштабные системы для компаний из списка Fortune 500 и крупных правительственных учреждений, включающие многие десятки подпроектов, расположенных в иерархиях каталогов на многих уровнях.Я использовал проекты / решения Microsoft Visual Studio для организации систем на базе .NET, Ant или Maven 2 для систем на базе Java, и я начал использовать distutils и setuptools (easyinstall) для систем на базе Python.Эти системы также включают в себя огромные базы данных, как правило, в Oracle или Microsoft SQL Server.

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

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

На практике это означает, что должно быть по крайней мере два уровня сценариев сборки.Самый нижний уровень - это сценарии сборки проекта, которые создают каждый результат / артефакт.Каждый такой скрипт находится в корневом каталоге дерева исходных текстов своего проекта (действительно, этот скрипт ОПРЕДЕЛЯЕТ дерево исходных текстов своего проекта), эти скрипты ничего не знают о системе управления версиями, они ожидают запуска из командной строки, они ссылаются на все в проекте относительно сценария сборки и ссылаются на свои внешние зависимости (инструменты или двоичные артефакты, никаких других исходных проектов) На основе нескольких настраиваемых параметров (переменные среды, файлы конфигурации и т.д.).

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

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

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

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

Наконец, создание огромной иерархии проектов может быть просто слишком затратным по производительности.Например, весной 2007 года я попытался создать скромную иерархию исходных текстов (Java плюс Oracle), которую я построил с помощью Ant, что в конечном итоге не удалось, потому что сборка всегда прерывалась с помощью Java OutOfMemoryException .Это было на рабочей станции с 2 ГБ оперативной памяти и 3,5 ГБ пространства подкачки, для которой я настроил JVM так, чтобы она могла использовать всю доступную память.Приложение / система были относительно тривиальными с точки зрения объема кода, но рекурсивные вызовы сборки в конечном итоге исчерпали память, независимо от того, сколько памяти я им выделил.Конечно, выполнение этого также заняло целую вечность (обычно это занимало 30-60 минут, прежде чем оно прерывалось).Я очень хорошо умею настраивать, но в конечном счете я просто превысил возможности инструментов (в данном случае Java / Ant).

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

Редактировать:Подробнее об антипаттернах

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

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

Однако иногда кажется особенно оправданным такое растягивание, как, например, в данном случае.Некоторые инструменты, по-видимому, "подводят" пользователя к определенным методам их применения, вплоть до того, что некоторые утверждают, что инструменты формируют мысль (слегка перефразировано).В основном именно в этом духе я предлагаю следующее svn:external является антипаттерном.

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

Правильное управление зависимостями между проектами предполагает устранение этой динамики наряду с базовой проблемой, а инструменты и методы ведут по другому пути.Примером, который следует рассмотреть, является Плющ, который помогает аналогично Maven, но без многих недостатков.Я исследую Ivy в сочетании с Ant в качестве моего краткосрочного решения проблемы сборки Java.В долгосрочной перспективе я планирую включить основные концепции и функции в инструмент с открытым исходным кодом, который облегчает создание мультиплатформенного решения.

Другие советы

Я не думаю, что это вообще антипаттерн. Я сделал несколько быстрых поисков в Google и ничего не нашел ... никто не жалуется, что использование svn: externals вредно или вредно. Конечно, есть некоторые предостережения, о которых вы должны знать ... и это не то, что вы должны просто сильно влить во все свои репозитории ... но что касается первоначальной цитаты, это всего лишь его личное (и субъективное) мнение , Он никогда не обсуждал svn: externals, кроме как осуждать их как анти-паттерн Такие радикальные заявления без какой-либо поддержки или, по крайней мере, рассуждений о том, как человек пришел, чтобы сделать заявление, всегда подозрительны.

Тем не менее, есть некоторые проблемы с использованием внешних устройств. Как ответил Майк, они могут быть очень полезны для указания на стабильные ветви выпущенного программного обеспечения ... особенно программного обеспечения, которым вы уже управляете. Мы используем их внутренне в ряде проектов для служебных библиотек и тому подобного. У нас есть небольшая группа, которая совершенствует и работает на базе библиотеки утилит, но этот базовый код используется несколькими проектами. Мы не хотим, чтобы различные команды просто проверяли код служебного проекта, и мы не хотим иметь дело с миллионом веток, поэтому для нас svn: externals работает очень хорошо. Для некоторых людей они могут не быть ответом. Однако я бы категорически не согласился с утверждением & Quot; Пожалуйста, не используйте ... & Quot; и что эти инструменты представляют собой анти-шаблон.

Основной риск при использовании svn: externals заключается в том, что указанный репозиторий будет изменен таким образом, что это нарушит ваш код или создаст уязвимость безопасности. Если внешний репозиторий также находится под вашим контролем, это может быть приемлемым.

Лично я использую svn: externals только для указания на " stable " ветки хранилища, которым я владею.

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

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

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

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

Выдержка из svn book :

  

Внешнее определение - это сопоставление локального каталога с URL ** & # 8212 и, возможно, с определенной версией & # 8212; ** ресурса с контролем версий.

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

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

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

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

Утверждение, что a - это b , не делает a a b , если вы не скажете почему это так.

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

Внешние ссылки Subversion можно использовать и злоупотреблять ими, а сама функция - это не что иное, как функция . Нельзя сказать, что это шаблон или антипаттерн .

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

Да, вы можете использовать его неправильно, не указав конкретно, какая версия этой ссылки вам нужна. Это доставит вам проблемы? Скорее всего!

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top