Лучшие практики для совместного использования крошечных фрагментов кода между проектами


102

Я всегда стараюсь строго следовать принципу СУХОЙ на работе; каждый раз, когда я повторяю код из-за лени, он кусается позже, когда мне нужно сохранить этот код в двух местах.

Но часто я пишу небольшие методы (возможно, 10–15 строк кода), которые необходимо повторно использовать в двух проектах, которые не могут ссылаться друг на друга. Этот метод может быть как-то связан с сетью / строками / MVVM и т. Д., И в целом это полезный метод, не относящийся к проекту, в котором он изначально находится.

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

  1. В итоге мы получаем десятки / сотни крошечных проектов, каждый из которых содержит небольшие классы / методы, которые нам нужно было использовать повторно. Стоит ли создавать совершенно новый .DLLкод для крошечного кода?
  2. В итоге мы получаем один проект с растущей коллекцией не связанных между собой методов и классов. Этот подход - то, что сделала компания, для которой я работал; у них был названный проект, в base.commonкотором были папки для таких вещей, как я упомянул выше: работа в сети, манипуляции со строками, MVVM и т. д. Это было невероятно удобно, но ссылки на него без необходимости тянули с собой весь ненужный код, который вам не нужен.

Итак, мой вопрос:

Как команде разработчиков лучше всего использовать повторяющиеся фрагменты кода между проектами?

Меня особенно интересует, работал ли кто-нибудь в компании, которая имеет политику в этой области, или сталкивался с этой дилеммой лично, как и я.


примечание: мое использование слов «проект», «решение» и «справочник» происходит из опыта разработки в .NET в Visual Studio. Но я уверен, что эта проблема не зависит от языка и платформы.


21
+1, хотя я думаю, что у кого-то, работающего с .NET, есть элемент юмора, обеспокоенный перетаскиванием нерелевантного кода через ссылку на DLL.
JDB

2
@ColeJohnson .NET сама по себе является огромной ссылкой! Вероятно, намного больше, чем я сделал бы сам.
Джордж Пауэлл

2
Я понимаю. Однако JIT-компилятор .NET загружает только необходимые методы в оперативную память (когда они вызываются)
Коул Джонсон,

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

Ответы:


75

Если они действительно являются повторно используемыми методами / классами, вы можете записать их в небольшое количество библиотек «Swiss Army Knife». Мы делаем это довольно часто в моей компании; мы называем их каркасными библиотеками:

  • Framework.Data - Утилиты для работы с запросами к базе данных.
  • Framework.ESB - Стандартные методы взаимодействия с нашей корпоративной сервисной шиной
  • Framework.Logging - Единая система регистрации
  • Framework.Services - Утилиты для взаимодействия с веб-сервисами
  • Framework.Strings - Утилиты для расширенного управления строками / поиска нечетких строк и т. Д.
  • ...

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

Если они на самом деле являются просто фрагментами, а не фактическими методами / классами, которые можно легко использовать повторно, попробуйте просто распределить их как фрагменты кода в IDE (например, фрагменты кода Visual Studio ). Команды, с которыми я работал в прошлом, имели общую библиотеку фрагментов, которая облегчила всем следовать нашим стандартным методам кодирования и с внутренним кодом.


4
+1 Это тоже мой подход. Интересно узнать, как вы решили, куда поместить код, который работает с вещами из двух или более аспектов. Например, IPAddressToString. И позволяете ли вы этим библиотекам использовать друг друга. Например, службы и данные могут извлечь большую выгоду из регистрации ...
Marjan Venema

5
@MarjanVenema Для сквозного кода это зависит от того, какие потребители найдут метод более полезным. Поскольку IPAddressToString, вероятно, потребителям, имеющим дело с сетевыми протоколами, придется использовать это, но потребители, которые много возятся со строками, могут вообще не заботиться об IP-адресах. Это, вероятно, в конечном итоге в сетевой пакет, а не Framework.Strings.
PSWG

@MarjanVenema Мы стараемся избегать взаимозависимостей. Наши сервисы и структуры данных написаны таким образом, что они не выполняют самостоятельную регистрацию, но облегчают потребителю написание правильного регистрационного кода. Библиотеки фреймворка могут ссылаться друг на друга, но только по расширению - например Framework.Logging.Gibraltar, это конкретное дополнение к системе ведения журналов.
PSWG

5
+1 Вы можете взять эти библиотеки фреймворков и развернуть их во внутреннем репозитории NuGet (так же просто, как в сетевой папке), и у вас есть хороший способ управлять им.
Стивен Эверс

2
@ SteveEvers Сейчас я работаю над настройкой. : P
pswg

21

Я не согласен с принятым ответом по многим причинам.

По моему опыту, когда я вижу «разные» библиотеки, такие как принятый ответ, они являются оправданием, чтобы заново изобрести колесо (или не изобретено здесь (NIH) ) - гораздо больший грех, чем нарушение Dont Repeat Yourself (DRY) .

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

Подход многочисленных библиотек общего назначения является плохим примером. Это приводит к тонкой детализации сборки и слишком много сборок плохо. Недавно я сократил внутреннюю с 24 библиотек до 6 библиотек. Это улучшило время компиляции с нескольких минут до ~ 20 секунд. Visual Studio также медленнее загружается и меньше реагирует на большее количество сборок. Наличие слишком большого количества библиотек также приводит к путанице относительно того, где должен жить код; предпочитаю меньше, более простые правила.

Почему материал в .Net Framework недостаточно хорош? Фреймворк довольно большой; много раз я видел код, который повторно реализует вещи, которые уже существуют там. Действительно убедитесь, что ваши фреймворки заполняют пробелы в .Net Framework и не существуют просто по эстетическим причинам (например, «Мне не нравится .Net Framework здесь» или, возможно, какая-то преждевременная оптимизация )

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

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

Мои рекомендации:

  • Не делитесь этим кодом.
  • Создайте новую библиотеку, если она имеет единую цель: не используйте шаблон дизайна шарика грязи .
  • Повторно используйте существующие сторонние библиотеки, где это возможно.
  • Предпочитаю меньше сборок, с более простыми правилами относительно того, где должен жить код.

1
Дополнительное преимущество использования библиотек с открытым исходным кодом, где они доступны - если вы предложите некоторые улучшения, вы можете поделиться ими с сообществом! Например, с .Net MS опубликовал EnterpriseLibrary (в настоящее время с открытым исходным кодом), который предоставляет довольно хороший набор инструментов для распространенных сценариев, найти что-то там, что может быть улучшено и эй Presto! Всем выгодно!
Гленатрон

2
Я действительно не вижу несогласия с принятым ответом здесь :-). «меньшее количество сборок с более простыми правилами относительно того, где должен жить код» не противоречит принятому ответу. Ответ также призывает использовать только столько разных сборок, сколько кажется разумным.
Слёске

Пять лет спустя руководство Microservice также сошлось в этой практике: medium.com/standard-bank/…
Дэйв Хиллиер,

11

Для небольших фрагментов кода - скажем, одного класса без зависимостей - мы склонны просто копировать и вставлять код в проекты. Это звучит как нарушение СУХОГО, и я признаю, что это может быть время от времени. Но в долгосрочной перспективе это было намного лучше, чем иметь какой-то масштабный проект с несколькими головами по нескольким причинам.

Во-первых, проще иметь код под рукой, особенно при сборке и отладке.

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

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


5
Я не согласен с таким подходом. Я ценю проблемы обслуживания с управлением небольшими частями кода, но я бы сказал, что из всех них может быть создана общая библиотека, как предлагает @psw. Наличие дублирующих копий кода с небольшими изменениями в нем вызывает проблемы. Будут сделаны предположения, пропущены исправления ошибок.
Эндрю Т Финнелл

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

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

6

Второе решение, которое вы описываете, не так уж плохо. В .NET вы также ссылаетесь на сборку из GAC, даже если вы используете только один ее класс. «Перетаскивание неуместного кода» - это не проблема, как вы думаете. В этом случае жизненно важно, по крайней мере, поддерживать чистоту организации связанных методов и классов в разных пространствах имен. Кроме того, следует применять передовые методы для разработки API, чтобы это решение не стало беспорядочным.

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


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

6

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

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

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


В каком смысле вы ожидаете, что они не будут обнаружены? Таким образом, мы используем большое и растущее число пакетов nuget. Самая большая проблема, которую мы имеем, связана с управлением версиями и зависимостями.
фунтовые

О да. Те тоже. Под проблемами, связанными с возможностью обнаружения, я имею в виду, что при наличии достаточного количества небольших пакетов с определенной функцией, возможно, становится сложнее каталогизировать (и находить) каждый из них. Например, как ваша команда узнает, какие пакеты содержат различные функции? (показывает невежественное поисковое невежество здесь)
Kofi Sarfo

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

@sarfeast Было бы неплохо, если бы вы могли поделиться ссылкой на какой-либо сервер Nuget и рассказать об этом немного.
Ханс-Петер Стёрр,

6

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


5

GitHub имеет довольно полезный инструмент для сохранения фрагментов кода https://gist.github.com/

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


3

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

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

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

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


3

Я часто сталкиваюсь с проблемой, и мое предпочтительное решение - разместить код в репозитории с поддержкой github / pubic. это решает много проблем -

  1. легкий доступ и легко поделиться. cvs / svn / enterprise-repos означает извлечение проекта в несколько рабочих пространств IDE, а иногда и необходимость переключения рабочих пространств или компьютеров только для ссылки на небольшой фрагмент кода.
  2. если предположить, что эти фрагменты кода не являются частными / классифицированными частями кода и являются вариациями общедоступных знаний, размещение их в общедоступном репозитории, таком как github, означает, что другие будут смотреть на него и даже могут внести свой вклад.
  3. размещение чего-либо в открытом доступе под вашим именем создает дополнительную репутацию. вы будете дважды проверять и обновлять вещи, так как это отражается на ваших способностях программиста.
  4. Обновления. Суть сохранения фрагментов кода в репозитории заключается в том, что если фрагмент не использовался долгое время, он может устареть (содержать устаревшие apis / libs). пример - фрагмент кода Java для чтения файла. вы могли бы найти лучший способ сделать это в 2009 году, но в 2014 году выходит новый файл API, который все меняет. твой фрагмент? все еще застрял в 2009 году. в публичном репо все будет обновляться, либо вами (потому что пункт 3), вашими товарищами по команде или кем-то из общего числа программистов, и в процессе вы можете даже получить предложения по исправлению чего-то, что Вы, возможно, делали неправильно в течение долгого времени.

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


2

У нас есть отдельный проект «Утилиты», где мы храним все эти небольшие методы вместе с тестами.

Когда проекту нужна какая-то утилита, он просто добавляет исходный файл с требуемым методом «добавить как ссылку».

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

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

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


2

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

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


0

Я недавно придумал этот сервис: Snip2Code ( http://www.snip2code.com ).

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

Более того, существует множество сценариев, когда использование общей библиотеки просто не применимо: давайте рассмотрим, например, некоторые шаблоны проектирования, такие как Singleton, Strategy или Observer. Вы можете создавать библиотеки для поддержки таких шаблонов, но при этом нет 100% покрытия.

Реальная потребность в том, чтобы иметь инструмент для обмена общими практиками в команде. Я пытался использовать суть Github, но я застрял с их поиском (очень плохо) и с тем фактом, что я не могу поделиться ими только с моей командой, а не с другими ...

(Отказ от ответственности: я один из основателей Snip2Code, и я - вместе с моими соучредителями - некоторое время назад придерживался того же мнения: именно поэтому мы решили начать этот проект !!)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.