Пример ветвления по абстракции для приложения ASP.NET MVC 3, где абстракция - разные страны
Я работаю над приложением ASP.NET MVC 3, где для каждой страны созданы ветки в управлении версиями. Это затрудняет синхронизацию изменений между филиалами, и проблема будет увеличиваться по мере увеличения числа стран. Я читал о ветвлении с помощью абстракции, но никогда не использовал его, поэтому я пытаюсь понять, как это будет реализовано в достаточно сложном проекте.
Кто-нибудь может объяснить, как ветвление по абстракции может быть сделано для приложения ASP.NET MVC, где абстракция - это страна, а приложение - дело n-уровневого типа со слоями обслуживания и данных?
Вот некоторые вещи, которые я не могу придумать:
- Абстрагируй взгляд вещи. Например, файлы aspx/cshtml, javascript, css и т. Д.
- Абстрагирующие контроллеры
- Как вы справляетесь с дополнительной сложностью наличия всех ваших кодов для каждой страны в одной отрасли? (Обратите внимание, под одной ветвью я подразумеваю ветку по умолчанию, mainline, как вы хотите ее назвать)
- Как вы управляете переключателями функций для каждой страны? Например, потенциально у вас может быть много функций для каждой страны, которые не были готовы к выпуску, и управление переключателем)
- Как вы выбираете соответствующую страну при развертывании?
- Как вы запускаете юнит-тесты для конкретной страны?
ОБНОВИТЬ
Я не просто говорю об изменениях языка. Большая часть логики уровня обслуживания для каждой страны одинакова, но в определенных ключевых областях она различна, также как и для уровня данных. Также вид содержимого и макет могут отличаться, JavaScript может отличаться, и логика контроллера может отличаться.
3 ответа
Почему вы используете ветки для обработки локализации? имхо это безумие
Есть несколько способов сделать локализацию без единой кодовой базы на язык.
Например. Создавая собственный движок представлений поверх существующего, вы можете загружать представления из внешних сборок. Или вы можете создать одно представление для каждого языка.
Вы также можете использовать строковые таблицы в своих представлениях, чтобы сделать их локализованными.
Абстрагируй взгляд вещи. Например, файлы aspx/cshtml, javascript, css и т. Д.
Javascripts: у меня есть один javascript со всей моей логикой, который использует переменные вместо строк для отображения сообщений. Таким образом, я могу загрузить другой javascript перед логическим скриптом (например, myplugin.sv.js
до myplugin.js
чтобы получить шведский язык.
Наиболее распространенный способ для файлов aspx/cshtml - использовать в них строковые таблицы.
Локализовать css? Зачем?
Абстрагирующие контроллеры
да? Зачем? Используйте здесь также строковые таблицы.
Как вы справляетесь с дополнительной сложностью наличия всех ваших кодов для каждой страны в одной отрасли?
Не используйте ветки.
Как вы управляете переключателями функций для каждой абстракции?
да?
Как вы выбираете соответствующую страну при развертывании?
Используйте один и тот же сайт для всех языков. Либо использовать IP-адрес, Accept-Language
Заголовок http или предпочтение языка для выбора языка. Язык определяется настройкой Thread.CurrentThread.CurrentCulture
а также Thread.CurrentThread.CurrentUICulture
Как вы запускаете юнит-тесты для конкретной страны?
Не. Логика должна быть одинаковой.
Обновление в ответ на ваш комментарий
Я написал довольно много систем, в которых контент динамически загружается в приложение / службу. Я никогда не использовал разные базы кода, даже если разные клиенты используют разные функции в мультитенантных системах (SaaS).
Прежде всего, вам нужно принять две вещи:
а) Весь контент загружается постоянно (не о переводах, а о функциях). б) Используйте надлежащие / стандартные методы локализации, но нет необходимости переводить все функции на все языки.
Вы просто контролируете, какой контент загружать, и используете стандартные методы для получения переведенных функций. Управление осуществляется путем проверки текущего языка (Thread.CurrentThread.CurrentCulture.Name
) или любой домашний контроль.
Задайте новые вопросы, чтобы получить больше деталей.
Обновление 2
Я бы не стал полагаться на IoC для предоставления специфических для языка функций, но использовал бы рефлексию и FeatureProvider
класс, чтобы сделать это для меня.
Например, предположим, что у вас есть функция под названием ISalaryCalculator
который учитывает все местные налоговые правила и т. д. тогда я бы создал что-то вроде этого:
// 1053 is the LCID (read about LCID / LocaleId in MSDN)
[ForLanguage(1053)]
public SwedishSalaryCalculator : ISalaryCalculator
{
}
И есть FeatureProvider, чтобы загрузить его:
public class FeatureProvider
{
List<Assembly> _featureAssemblies;
public T GetLocalFeature<T>()
{
var featureType = typeof(T);
foreach (var assembly in _featureAssemblies)
{
foreach (var type in assembly.GetTypes().Where(t => featureType.IsAssignableFrom(t))
{
var attribute = type.GetCustomAttributes(typeof(ForLanguageAttribute)).First();
if (attribute.LocaleId == Thread.CurrentThread.CurrentCulture.LCID)
return (T)Activator.CreateInstance(type);
}
}
return null;
}
}
И чтобы получить функцию (для текущего языка):
var calculator = _featureManager.GetLocalFeature<ISalaryCalculator>();
var salaryAfterTaxes = calculator.GetSalaryAfterTax(400000);
В простом сценарии (CMS/ не слишком много или общая бизнес-логика) вы имеете дело только с контентом на разных языках и:
- Макет (слева направо и справа налево) - у вас будет два CSS-файла
- Локализованный (переведенный) контент
Макет CSS может находиться в отдельных файлах и извлекаться в зависимости от культуры учетной записи пользователя или настроек региона сайта.
Локализация может находиться в разных сборках - по одной для каждой культуры или в отдельных файлах таблиц строк (как уже упоминалось).
В более сложном сценарии, когда вы разрабатываете приложение для чувствительных культур и регионов, где:
- Вы должны быть осторожны с отображаемым контентом - например, изображение может быть очень оскорбительным в одной стране, но вполне приемлемым в другой.
- Различная бизнес-логика (например, финансовое приложение и т. Д.)
Большинство проблем с контентом вы можете решить с помощью CSS, но даже если вам нужны сильно настроенные представления, как уже упоминалось, вы можете создать механизм просмотра, который извлекает файл представления на основе текущей культуры (например, Index.en-Us.cshtml, Index.ru.cshtml и т. Д.)
Для различных бизнес-правил вы должны иметь хороший дизайн и архитектуру, использующую инверсию управления (например, внедрение зависимости) и такие шаблоны, как стратегия, состояние, метод шаблона и т. Д. Учитывая, что у вас это есть, вы сможете создать Контейнерный проект / сборка IoC для каждой культуры во время выполнения, и ваш пользовательский интерфейс не будет знать о разнице, поскольку он будет просто потреблять некоторые службы, определенные этими интерфейсами.
Немного сложнее, если ваши ViewModels значительно различаются между культурами, но если они есть, вы, возможно, захотите разделить View + Controller на культуру в разных сборках и снова использовать IoC для настройки маршрутизации при инициализации во время выполнения.
Очевидно, что развертывание сайтов с несколькими культурами сложнее, чем несуразные, и независимо от того, каким путем вы идете (экземпляр сайта для культуры или один экземпляр сайта для всех культур), вы, вероятно, захотите инвестировать в какой-то инструментарий, чтобы иметь возможность писать сценарии для нескольких культур. развертывание.
И последнее - в отношении модульных тестов - если у вас уже есть хорошее проектное тестирование на основе IoC для каждой культуры, вопрос использования и настройки правильного контейнера зависимостей перед запуском набора модульных тестов.
При такой настройке команды разработчиков должны работать в относительно автономной среде, поскольку ваш проект будет логически и физически разделен для поддержки нескольких групп, работающих над отдельными его частями одновременно. Это также не должно иметь значения, будь то ветки или ствол / голова. Конечно, если в нескольких проектах все в порядке, и людям постоянно приходится сливаться - вы в очень плохом состоянии и ваше будущее не светлое.
Заключительные слова: речь идет не о ветвлении, а о дизайне, архитектуре, разбиении (решения, проекты и сборки) и, наконец, что не менее важно, об автоматизации (сборка и тестирование).
Это немного не по теме, но я считаю, что вы движетесь в более сложном направлении, чем нужно. Локализация встроена в ASP.NET, и инфраструктура MVC также может этим воспользоваться.
Короче говоря, вы делаете рекс для каждого языка, который хотите поддерживать. Затем вы используете Resources.Global.YourLocalizedStringPropertyName
в ваших взглядах.
Этот пост является длинной историей. Скотт Хансельман изучает локализацию JavaScript и другие тонкости. Это определенно стоит прочитать и, вероятно, сэкономит вам невероятное количество работы, чтобы использовать встроенную функциональность вместо того, чтобы создавать ее самостоятельно: