Какой самый эффективный способ обмена кодом между приложениями .NET?

15

В нашей работе у нас есть несколько различных приложений .net, которые имеют много основных функций. Мы создали эти приложения, используя чистую n-уровневую архитектуру, но мы достигли того момента, когда поняли, что повторно реализовали одни и те же функции несколько раз. Очевидно, что это нарушает СУХОЙ, и мы хотели бы исправить это. Мы уже успешно используем Nuget для общего связующего кода (подключение IoC, ведение журнала, настройки), но мы также хотели бы разделить наши данные и бизнес-уровни между всеми нашими приложениями. Идея состоит в том, что пользовательский интерфейс будет иметь дело только с теми частями бизнес-уровня, которые ему действительно необходимы.

Сначала это кажется простой задачей, но продолжающееся развитие может привести к некоторым подводным камням, и мы не уверены, как действовать дальше. Допустим, мы создаем единый бизнес-уровень, чтобы управлять ими всеми. Для краткости я назову это «Фонд». Мы портируем наши приложения на использование Foundation, и все работает отлично. Основа распространяется на светлые слои пользовательского интерфейса через Nuget, и мы хорошо выглядим. Но затем мы начинаем добавлять функции в наши приложения, и у нас возникают проблемы.

Допустим, мы работаем над проектом A и добавляем новую функцию, которая требует изменений в Foundation. Мы вносим изменения в фундамент (Foundation-A) и помещаем их в ленту новостей как нестабильный пакет. Project A получает последнюю версию пакета nuget, и все хорошо. Тем временем другой разработчик работает над проектом B. Он получает последнюю версию Foundation из системы контроля версий, но берет ее из стабильной ветви, чтобы в ней не было изменений в Project A. Он вносит изменения и создает Foundation-B. И все хорошо. Но затем мы обнаруживаем, что функциональные возможности реализации Foundation-A и Foundation-B действительно могут совместно использовать код, поэтому мы объединяем их. Между тем, Foundation-C находится там со своими собственными изменениями. В конце концов, Foundation-B готов к производству, поэтому мы его выдвигаем. Но тогда нам нужно обновить производство A, B,

Кажется, что это может сработать, но мы беспокоимся о работе с различными схемами базы данных и сохранении синхронизации между различными ветвями репозитория Foundation, а также репозиториями Project A, B и C. Кажется, что это, вероятно, потребует много ручной работы, что открывает возможность для ошибок. Я хотел бы, чтобы это было максимально автоматизировано.

Вот стек, который мы используем: C #, TFS с непрерывной интеграцией, Nuget. Наши приложения - это различные типы приложений ASP.NET. Мы готовы взглянуть на разные SCM, если это облегчит задачу.

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

мистифицировать
источник
Кроме того, если это не очень хороший форум для такого обсуждения, может кто-нибудь предложить лучший?
Джош

Ответы:

9

Мы вносим изменения в фундамент (Foundation-A) и помещаем их в ленту новостей как нестабильный пакет.

Вот где начинается твоя проблема ... Не делай этого.

Любые изменения в Foundation v1.0 по своей сути должны быть полезны для всех потребителей Foundation, в противном случае он не принадлежит Foundation. Поэтому при создании пакета nuget делайте это как официальную стабильную версию Foundation (т.е. v1.1) или не делайте этого вообще.

Проект B должен построить свои базовые усовершенствования, как обычно, но (в хорошем способе управления исходным кодом) должен объединиться в изменениях ствола (v1.1), прежде чем передать стабильную основу (v1.2) в nuget.

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

Я согласен с @Giedrius ; мне кажется, что это скорее проблема управления исходным кодом / ветвления в том смысле, что если правильно выполнить ветвление / объединение Foundation, проблемы управления пакетами становятся спорными.

Эрик Кинг
источник
Да, это имеет смысл. Проблема в практическом применении. Когда вы делаете обновления для Foundation для v1.1, вы хотите использовать эти изменения в Project B при разработке. Если вы делитесь этим кодом с помощью Nuget, то вы можете выбрать следующие варианты: 1) Опубликовать новый пакет Nuget или 2) Вручную скопировать вокруг DLL. Ни один из них не кажется хорошим выбором.
Джош
Некоторое из этого может быть смягчено наличием эффективного набора тестов, но по-прежнему будет происходить взад и вперед по мере добавления функций.
Джош
@Josh Да, обновления для Foundation должны быть полными и тестируемыми, независимо от того, как Project B собирается их использовать (поскольку они собираются в общую библиотеку), поэтому «публикация нового пакета nuget» - это естественный путь. Не импортируйте и не используйте Foundation v.Next в Project B, пока он не станет стабильным в nuget. Это требует немного дисциплины, но это намного лучше, чем беспорядок, если делать это иначе.
Эрик Кинг,
1
Я полностью понимаю, что вы говорите, но я не думаю, что это очень реалистично. По мере разработки функции, даже если вы полностью протестировали всю бизнес-логику и уровень доступа к данным, произойдет модификация, прежде чем она будет запущена в производство. Возможно, вы понимаете, что вам нужно добавить другое свойство в бизнес-логику, или владелец продукта возвращается с изменениями или разъяснениями. Возможно, некоторые из ваших упрощающих предположений были неверными. Это вещи, которые случаются постоянно. Если вы ограничены блокировкой освобожденной базовой логики, она кажется очень ограниченной.
Джош
2
Поскольку мы занимались этим несколько месяцев, на этом мы и остановились. Я думаю, что я был слишком обеспокоен формальным процессом. Как только мы начали работать над этим, все пошло очень гладко. Спасибо за ваш вклад.
Джош
4

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

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

Роберт Харви
источник
Может быть, я не так ясно, как я мог быть в моем вопросе. Это о том, что будет дальше. Вы сделали все это, и теперь вам нужно эффективно делиться своим кодом между различными проектами. Кто-то говорит «просто используйте Nuget для этого», и это звучит замечательно, пока вы не разберетесь в деталях и не столкнетесь с проблемами - например, как синхронизировать различные изменения из разных веток и приложений.
Джош
Ну, я согласен с Эриком Кингом. Базовый код должен выдвигаться как стабильная версия, а не как нестабильная. Ключевым моментом является поддержание стабильного API: если вы знаете, что сигнатуры ваших базовых методов не изменятся, вы можете безопасно передать эти методы в Foundation и позже провести их рефакторинг, ничего не нарушая.
Роберт Харви
4

Повторное использование кода

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

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

  2. Общий исходный код. Код, который требуется более чем в одном месте, записывается один раз и помещается в исходный файл в общую структуру каталогов. Все проекты, которым нужен этот код, затем включают этот файл в качестве одного из своих исходных файлов. Это обеспечивает повторное использование кода, а преимущества однократной записи используют многие. Тем не мение. Его недостатком является то, что становится возможным иметь различные части проекта, скомпилированные с разными версиями этого кода - что может привести к некоторым тонким дефектам, которые может быть очень сложно обнаружить и идентифицировать с помощью обеспечения качества.

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

Управление NuGET

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

Майкл Шоу
источник
1

Я думаю, что проблема не в nuget / контроле исходного кода / ветвлении, а в том, что проскальзывает в склеивающий код.

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

http://ayende.com/blog/3986/let-us-burn-all-those-pesky-util-common-libraries http://blog.jordanterrell.com/post/CommonUtility-Libraries-Dead.aspx

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

Гиедрюс
источник
Я не говорю об управлении клеевым кодом. У нас уже есть решение для этого, и оно работает хорошо. Я говорю об обмене бизнес-логикой. Например, наши приложения имеют дело с управлением организациями и людьми. Итак, нам нужно создать человека, и существует множество бизнес-правил, связанных с тем, как должен быть создан человек. Вместо того, чтобы создавать его несколько раз, мы хотим иметь один пакет, который обрабатывает все от создания объекта до его сохранения, которое мы разделяем между различными проектами. что нужно создавать людям.
Джош
0

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

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

Euphoric
источник