Сегодня мы расскажем о том, как в компании построили командную разработку на платформе MS Dynamics CRM. Эта платформа, как большинство проприетарных систем без исходного кода, несет в себе ряд ограничений и дополнительных сложностей для разработчиков. Настройка системы, создание внутренних сущностей, создание UI – все это реализовано внутренними средствами платформы, при этом внутреннего языка нет, возможности по переносу настроек ограничены выгрузкой во внутреннем, недокументированном формате.

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

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

Рассмотрим, какие есть варианты командой из 10+ разработчиков развивать функционал системы масштаба предприятия построенной на базе MS Dynamics CRM. Под развитием понимаем не только возможность изменять поведение системы – эта задача вполне очевидна и не представляет трудности даже с проприетарной системой MS Dynamics CRM. Нас интересует командная разработка, возможность без потери в скорости и качестве работы людей параллельно изменять поведение системы в части всех компонентов, построение Continuous Integration, реализация автосборки, а в финале механизация Continuous Deployment.

Начнем с экскурса в то, что входит в понятие разработка под MS Dynamics CRM.
Основные части системы на базе MS Dynamics CRM с точки зрения разработчика:

1) Настройки (далее будем называть их Кастомизация)
a. Плагины
b. Справочники
c. Веб-ресурсы
d. Отчеты
2) Вспомогательные объекты БД

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

Плагин – реализуемая на С# логика срабатывающая по какому-либо событию. С точки зрения разработки это собственный класс реализующий IPlugin и собранный в DLL.

Регистрация и настройка триггера в системе осуществляется средствами MS Dynamics CRM и является частью Кастомизации.



Справочники. В MS Dynamics CRM часто используется большое количество справочных данных, зачастую на них жестко завязана бизнес-логика работы системы. Справочниками называют неизменяемые сущности с наборами эталонных данных. У нас это обычные сущности системы, которые не изменяются в процессе работы, но изменяются в процессе разработки. Некорректные данные в справочниках приводят к непредсказуемым последствиям. Важно иметь возможность контролировать консистентность их содержимого. Основным инструментом тут может быть версионирование изменения их содержимого.

Веб-ресурсы – это виртуальные файлы (JScript, CSS, XML, XSL,, HTML, JPG и т.д.) которые могут быть использованы для расширения форм MS Dynamics CRM. Хранятся они не в каталоге веб сервера, а в виде виртуальных файлов в БД MS Dynamics CRM. Каждый веб-ресурс имеет уникальное имя, которое может использоваться в URL-адресе для извлечения соответствующего файла. Ограничивается их использование отдачей браузеру, серверной обработки не предусмотрено. При разработке они загружаются средствами MS Dynamics CRM и становятся частью Кастомизации.

Кастомизация – объединенные в один контейнер настройки разных компонентов системы MS Dynamics CRM. Разработка и настройка функционирования системы осуществляется “программированием мышкой” во внутреннем редакторе системы. Есть возможность создавать Сущность(Entity) и их поля (Field), настраивать Workflow (набор правил запускаемых по требованию или автоматически), создавать формы (Form) для работы пользователя с сущностями системы и представления (Views). Все это вместе принято называть Кастомизацией. Кастомизация может быть экспортирована из организации, где производится ее редактирование и импортироваться в другую организацию в рамках одного экземпляра системы или на другой сервер.

(Организация в MS Dynamics CRM это подобие “песочницы” в рамках системы. На одном сервере может параллельно работать несколько организаций, они независимы друг от друга, но у каждой есть своя база).

Вспомогательные объекты БД. Часто при проектировании системы необходимо иметь свои объекты (tables, views, stored procs, и т.д.) в БД MS Dynamics CRM или рядом развернутой отдельной БД. Это часто делается для хранения и обработки неизвестных MS Dynamics CRM данных, их импорта в БД MS Dynamics CRM средствами API или напрямую в БД (что не приветствуется).

Отчеты. MS Dynamics CRM интегрирован с MS SQL и Reporting Services. Отчеты MS Dynamics CRM с точки зрения разработки являются шаблоном оформления и информацией об источниках данных упакованными в файл шаблона отчета.

Выделенные выше компоненты являются основными с точки зрения разработчика, именно их он будет править создавая новую систему на платформе MS Dynamics CRM.
Очевидно, что из выше рассмотренных компонентов “проблемным” является Кастомизация. Это компонент системы, у которого нет “исходного кода” в явном виде.

Обратимся к рекомендациям Microsoft по организации процесса разработки под MS Dynamics CRM. Microsoft предлагает 3 варианта:

• Одна организация: Единое мастер-решение
• Одна организация: Мастер-решение + несколько решений для изменений
• Отдельная организация на каждого разработчика

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

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

Третий подход “Отдельная Организация на каждого разработчика” наиболее близок к классическим требованиям к командной разработке.

Предполагается, что каждый разработчик “живет” в своей отдельной Организации. Для выполнения задач разработчик импортирует последнюю версию Кастомизации (предварительно экспортирует ее с Мастер-Организации) в свою Организацию. Затем вносит необходимые правки по своим задачам в рамках своей Организации. После чего выгружает модифицированное решение из своей Организации, импортирует его в Мастер-Организацию откуда уже формируется финальный пакет спринта\релиза.
Но даже этот подход не решает всех проблем. Разработчики при этом “живут” на одном сервере, что негативно влияет на возможность полноценно отлаживать свои изменения, не ясно как разрешать конфликты.

Что сделали мы

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

Мы дали каждому разработчику выделенный девелоперский контур состоящий из отдельной машины с установленной на нее серверной ОС (да, MS Dynamics CRM, устанавливается только на серверную ОС), MS Dynamics CRM, MS SQL, Reporting Services и необходимыми для разработки продуктами (MS VS, MS Dynamics CRM SDK, Git-клиент, MS SQL Management Studio и т.д.) Т.е. мы пошли чуть дальше предложенного MS варианта по выделению отдельной организации на каждого разработчика, мы выделили отдельный экземпляр MS Dynamics CRM на каждого разработчика. И это объяснимо, т.к. кроме Кастомизации рядом с MS Dynamics CRM работают и другие компоненты, которые также могут изменяться разработчиками. Что в итоге рано или поздно приведет к “толканию локтями” на одном сервере MS Dynamics CRM. Бонусом получаем возможность выдать новому разработчику подготовленный и преднастроенный контур для разработки в течение часа путем клонирования виртуальной мастер-машины.

Теперь у каждого есть всё для локальной разработки. Можно править код плагинов, Кастомизацию, создавать и удалять объекты в БД, собирать и устанавливать локально любые компоненты, отлаживаться эксклюзивно. И, в конце концов, отправлять свои изменения в ветку GIT (здесь и далее упоминается GIT, т.к. мы используем эту систему контроля версий, но все написанное справедливо и для любой другой SCM системы). Как при этом мы будем версионировать изменения? Что необходимо для построения автоматической сборки решения? Возвращаемся к списку основных частей системы, которые изменяются в процессе разработки:

Плагины – с ними проблем нет. Код на C# есть. Возможность комита в GIT, разбора конфликтов есть. Сборка проектов в DLL — это build C# кода. Автоматизация установки собранного плагина — также решаемая задача – реализуется через API MS Dynamics CRM.

Справочники решили хранить также как и код в GIT в виде comma separated файлов. Удобно править при помощи Excel, разбирать проблемы т.к. при этом формат, по сути, остался текстовым. Сделали механизм автоматизированного импорта и экспорта содержимого справочников. API системы гибок, позволяет любые операции с сущностями автоматизировать. Особую сложность представляли связанные справочники, многоуровневые справочники. Пришлось ввести отдельным атрибутом у каждого справочника суррогатный ключ для целей синхронизации и связывания.

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

Пока это работает так, но есть предположение, что можно в Visual Studio csproj добавить эти файлы как ссылки. Физически при этом они будут находиться в распакованной Кастомизации. Это позволит уйти от дублирования и сопутствующих ему проблем.

Кастомизация – основной источник головной боли для разработчика. Для работы с ней в SDK MS Dynamics CRM обнаружилась полезная утилита — SolutionPackager. Она по сути осуществляет распаковку файла solution-а (Кастомизации) который мы получаем при экспорте решения из MS Dynamics CRM. Если посмотреть на файл решения, это гигантский xml-файл недокументированного формата. На выходе, после обработки его SolutionPackager –ом мы получаем разложенные по файловой структуре xml файлы, они разбиты логически по типам сущностей. Этим же инструментом можно произвести обратное преобразование. Запаковать распакованное решение в единый файл. Работать с маленькими xml файлами разбитыми согласно логике (пусть и не документированной) уже представляется возможным.

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

Процесс внесения правок в Кастомизацию при командной разработке становится следующим:

1) Вытягиваем свежую “распакованную” Кастомизацию из GIT
2) Запаковываем полученную Кастомизацию локально
3) Импортируем ее в локальный MS Dynamics CRM
4) Вносим правки в Кастомизацию в локальном контуре разработчика
5) Вносим правки в другие компоненты (при необходимости), собираем устанавливаем их локально
6) Отлаживаем изменения. Переходим к п.4 и п.5 по необходимости многократно.
7) Экспортируем Кастомизацию с локального сервера.
8) Распаковываем экспортированную кастомизацию в отдельный каталог
9) Вытягиваем свежую “распакованную” Кастомизацию из GIT
10) Осуществляем merge изменений полученных в п.8 с свежей Кастомизацией. Это очень важный шаг, т.к. пока мы вносили свои правки, кто-то мог уже закомитить измененные файлы Кастомизации. Мы не должны эти изменения перетереть.
11) Комитим изменения.
Накладные расходы процесса велики. Мы постарались автоматизировать шаги, не требующие вмешательства человека. Это п.2-3, п.7-9.

При совместной работе над Кастомизацией возможны следующие сценарии:

1. Разработчики вносят изменения в разные сущности. После завершения своих задач каждый выгружает решение и коммитит изменения в GIT. В этом случае конфликтов возникнуть не должно, т.к. при распаковке решения изменения окажутся в разных xml-файлах.
2. Разработчики вносят изменения в одну форму сущности. После завершения своих задач каждый выгружает решение из своей организации, берет последнюю версию решения из GIT и коммитит изменения в GIT.
a. Разработчик А первым завершает задачу, берет последнюю версию решения из GIT (в котором за время выполнения задачи изменений не было), выгружает свое решение и коммитит свои изменения.
b. Разработчик B вторым завершает свою задачу, берет последнюю версию решения из GIT (в котором за это время появились изменения Разработчика А), выгружает свое решение и при коммите своих изменений сталкивается с конфликтом в xml-файле формы.

Возможные пути разрешения конфликта:

i. Разработчик B смотрит в истории изменений формы, какие кастомизации были произведены Разработчиком А. Если изменения простые (например, добавлено поле на форму), то Разработчик B повторяет эти изменения в своей организации, после этого повторно выгружает решение из своей организации и коммитит изменения на форме в режиме overwrite.

ii. Разработчик B смотрит в истории изменений формы, какие кастомизации были произведены Разработчиком А. Если изменения Разработчика А были множественными и сложными для повторения, то Разработчик B повторно импортирует последнюю версию решения из GIT в свою организацию, после чего еще раз производит кастомизации, необходимые для выполнения своей задачи, затем повторно выгружает решение из своей организации и коммитит изменения на форме.

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

iv. Возможен вариант слияния/мержа изменений непосредственно в xml-коде формы (например, если Разработчик А добавил свою секцию на форму, а Разработчик B — свою), но такой метод обозначен MS как unsupported. Также в данном случае Разработчику B после слияния xml-кода придется проверить импортируемость всего решения в свою организацию. Только после этого он может повторно выгрузить решение из своей организации и закоммитить изменения в GIT.

Для примера, самым неприятным случаем является параллельное добавление на одну форму разными разработчиками Control-а одного типа. Разработчик А добавляет поле “Изменено” на форму “Встреча” (см. рис)



Разработчик Б туда же в это время добавляет поле “Дата создания” (см. рис).



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



Вспомогательные объекты БД – версионирование изменений структуры БД – это тема отдельной большой статьи. Способы решения этой задачи зависят от входных условий. В рамках одной организации для разных систем, команд, разных СУБД эта задача решается по-разному. В случае с версионированием изменений в БД MS Dynamics CRM и вспомогательных БД мы пошли по пути использования отдельного Database проекта в MSVS с последующей генерацией .dacpac файла. Data-Tier Application Framework получая на вход .dacpac файл с описанием целевой структуры БД способен привести БД любой предыдущей версии к целевой структуре.



Главным для нас было то, что был найден вариант версионирования с автоматизированным приведением структуры БД к необходимому состоянию для любых изменений DDL, кода clr сборок, свойств БД и скриптов PreDeployment и PostDeployment.

Кроме того, Database проект позволяет синхронизацию с рабочей БД осуществлять в двух режимах:

? синхронизированный с БД: все объекты из БД переносятся в проект. Процесс обновления представляет собой полную синхронизацию, где проект первичен;
? инкрементальный. В процессе обновления БД обновляются/изменяются только те объекты, которые присутствуют в проекте, не затрагивая остальные. В инкрементальном подходе первична БД. В этом случае нет обновления проекта из БД.

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

Отчеты, также как и справочники, версионируются в GIT. Автоматизация их установки в MSRS достаточно просто реализуется средствами Report Server Web Service Endpoints. Пример кода реализующего загрузку шаблонов отчетов приведен ниже.



Комплекс этих подходов и механизмов автоматизации операций позволил нам в итоге внедрить Continuous Integration при развитии системы не предназначенной для этого. Что позволило отлавливать ошибки разработки на этапе сборки и ежедневного разворачивания проекта не только в коде C#, но и в кастомизации и всех остальных компонентах MS Dynamics CRM.

Финальным шагом автоматизации процесса разработки стало рождение инсталлятора устанавливающего все компоненты системы (а их значительно больше, чем описано выше, т.к. в дополнение к компонентам MS Dynamics CRM у нас в системе есть еще вспомогательные сайты, сервисы, службы) на развернутый контур. Полная установка, включающая в себя Кастомизацию, изменения в БД, отчеты, 4 сайта, 2 службы в среднем проходит за 1 час (тестовый контур). При этом львиная доля времени уходит на импорт Кастомизации в MS Dynamics CRM.

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

Кроме того, инсталлятор работает в 2 режимах: wizard с возможностью диалогового ввода всех параметров и необходимых к установке компонентов. Этот режим для ручного разворачивания, установки на Production когда требуется ручной ввод паролей от Prod аккаунтов сотрудниками службы поддержки.





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



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

Вот вкратце получившийся у нас способ организации командной работы для MS Dynamics CRM. Безусловно, что-то можно было сделать иначе, какие-то задачи более эффективно решить, где-то совсем по-другому пути пойти. И сейчас еще есть не решенные вопросы — правка веб-ресурсов, трудности merge xml исходников Кастомизации, непрогнозируемые изменения xml файлов в недрах MS Dynamics CRM и другие. И, тем не менее, сложившийся подход работает, позволяет нам большой распределенной командой разработки эффективно развивать, систему с каждым днем все меньше отвлекаться на решение организационных трудностей и “околоразработческих” проблем. Поиск рекомендаций и готовых, апробированных подходов организации процесса разработки для MS Dynamics CRM 2 года назад не дал заметных результатов.

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

Александр Городилов, начальник Управления развития фронтофисных систем
Поделиться с друзьями
-->

Комментарии (0)