О проекте Medplus

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

Проект создан на передовых и высоколиквидных технологиях, таких как Angular5+, Django, Python, PostgreSQL.

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

Упор на эти технологии, с одной стороны, позволяет относительно легко решать кадровый вопрос, а с другой стороны, делает проект привлекательным для инвестиций ввиду высокой ликвидности этих технологий. При этом достигается наилучший баланс между стоимостью сопровождения и поиском совершенства. А такая технология как Angular5+, кроме всего прочего, обладает еще и обучающим эффектом, и позволяет программисту Middle-квалификации (при наличии у него способности читать документацию) писать код сопоставимый по качеству с кодом программиста Senior-квалификации с многолетним стажем. Кстати, Angular второго поколения качественно отличается в лучшую сторону от своего предшественника первого поколения.

Использование Django Framework было изначально предопределено заказчиком, для которого критически важными были высокая ликвидность технологии на рынке, легкость поиска разработчиков, популярность, высокая скорость прототипирования и темпов разработки, низкий порог вхождения, развитость сообщества, обилие готовых расширений и, разумеется, личное предпочтение. Теме Django Framework у меня посвящена отдельная статья, поэтому останавливаться подробно на этом вопросе не буду, скажу только что нам удалось использовать все превосходства этого фреймворка. Микросервисная архитектура - это один из тех моментов, где отступление от качественного расслоения системы (в сторону увеличения сопряжения) не оказывает существенного влияния на качество архитектуры, но при этом позволяет в значительной мере использовать мета-программирование для автоматизации декларирования вышестоящих слоев (Serializer, Page Controller), обеспечивая высокие темпы разработки бэкенда. Это та ниша, для которой Django (точнее, Django REST Framework) подходит лучше всего.

Известно, что среднестатистический проект, спроектированный по каскадной методологии, либо по методологии Agile без использования технических практик (голый Scrum), обычно имеет экспоненциальный рост стоимости сопровождения проекта по мере увеличения объема его кодовой базы. Такие проекты в среднем за 3-4 года могут достигнуть своего порога нерентабельности, и дальше, либо прекращают дальнейшее развитие, либо прибегают к радикальным мерам во спасение (замена тех.руководства, замена тех.коллектива полностью, переписывание проекта с нуля, эмиссия акций, массовые сокращения штата и т.п.):

The cost of change rising exponentially over time. The image from the book "Extreme Programming" by Kent Beck.

Для достижения наилучших экономических показателей, при создании проекта, в качестве технических практик Agile, использовались лучшие архитектурные практики (SOA, DDD, SOLID, GRASP, PoEAA, Design Patterns) и опыт всемирно-известных авторитетов в области программной архитектуры, таких как Kent Beck, Ward Cunningham, Martin Fowler, Robert C. Martin, Steve McConnell, Eric Evans, Erich Gamma и др. Сильно вдаваться в подробности не буду, так как на эту тему была написана отдельная статья: “How to quickly develop high-quality code. Team work.”.

Скажу только, что все это позволило запустить MVP проекта за рекордно-малое количество человеко-часов. Изначально оговоренная вилка времени в 4-6 месяцев на запуск MVP была выполнена несмотря на недоукомплектованность штата разработчиками и в значительной мере увеличенную изначально сложность функциональности проекта. При этом мы достигли практически нулевой багфикс и дебаг, никаких сверхурочных, здоровую моральную атмосферу и никаких WTF. Мы взяли максимальную планку, и у нас получилось. 15 июня 2018 года MVP проекта был открыт на Production-server. Это пока только MVP, а не завершенный проект, но он вполне жизнеспособный.

При этом проект не раз изменял свои изначальные условия и требования по мере появления более зрелого понимания его развития в результате ранней обратной связи от представителей бизнеса, что является одной из сильных сторон Extreme Programing. Вносить эти изменения в код удавалось сравнительно недорого за счет поддержания низкого уровня сопряжения (принцип Low Coupling and High Cohesion), покрытия критически-важных частей системы интеграционными тестами, использования метапрограммирования при тестировании, которое позволяет декларативно создавать тысячи тестовых интеграционных кейсов (так, например, при тестировании content-workflow требуется такое количество тестов, на написание которых вручную разработчику потребовалось бы несколько человеко-месяцев), и использования самой успешной методологии гибкой (Agile) разработки Extreme Programming (XP), созданной всемирно-известным архитектором программного обеспечения Kent Beck.

Ключевой принцип Extreme Programing сводится к управлению бизнес-рисками и экономикой проекта. Его отличительная черта - сохранение стоимости развития программы низкой по мере роста объема кодовой базы. Достигается это рядом организационных мер и архитектурных решений.

The cost of change may not rise dramatically over time. The image from the book "Extreme Programming" by Kent Beck.

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

Некоторые решения в проекте оказались уникальными, например, в связи с активным использованием понятия агрегата, нам потребовалась система аудита модели реализующая Slowly Changing Dimensions (SCD) - Type 4. Готового решения для Django Framework найти не удалось, и пришлось реализовывать его своими силами. Разработанная система версионирования контента не снижает производительности выборки реальных данных, и, вместе с этим, позволяет версионировать не только состояние объекта, но и его связи, т.е. структуры (агрегаты) взаимосвязанных объектов, даже если какой-то из объектов был удален. Грубо говоря, такой версионинг добавляет новое измерение к данным, и позволяет делать выборки данных и восстанавливать состояние композиции объектов на любой момент времени.

Проект сочетает в себе два архитектурных стиля: компонентный и микросервисный. Компоненты спроектированы по принципам Domain-Driven Design, и каждый его Bounded Context может работать как в самостоятельном процессе (в виде микросервиса), так и в общем процессе приложения (в виде подключаемого компонента). Соответственно, каждый Сервисный Слой компонентов спроектирован под обе реализации, одна из которых выполняется в виде клиента для работы с Сервисом Удаленного Вызова. Это позволяет использовать “Evolutionary Design” и расщеплять монолит на микросервисы по мере назревания в этом реальной необходимости, избегая “Premature Decomposition” и высвобождая время разработчиков на этапе создания MVP. Это так же удешевляет процесс дистилляции моделей:

“When starting out, however, keep a new system on the more monolithic side; getting service boundaries wrong can be costly, so waiting for things to stabilize as you get to grips with a new domain is sensible.” - “Building Microservices. Designing Fine-Grained Systems” by Sam Newman

Благодаря микросервисной архитектуре, в проекте крайне-низкий уровень внутренних зависимостей, что позволяет безболезненно перенести один из компонентов системы (например, контент) на принципиально иной вид хранилища данных (например, MongoDB). А также позволяет использовать отдельный сервис пользователей, который способен обслуживать несколько проектов одновременно. Для разделения сессии между сервисами использован JSON-Web-Token. Как уже упоминалось ранее, на стороне сервера компоненты общаются исключительно посредством публичных Сервисных Слоев, которые, при необходимости, могут быть легко подменены на клиентскую реализацию Сервисов Удаленного Вызова. Взаимодействие сервисов на стороне браузера организовано с помощью передовой технологии реактивного программирования RxJS. Этот подход является следующей ступенью развития асинхронного программирования, которая пришла на смену ставшему уже стандартным Promise, и позволяет реагировать не только на завершение события, но и на изменение состояния его результата, что позволяет легко создавать сложные пользовательские интерфейсы.

Использование RxJS в сочетании с DDD на стороне браузера позволило заметно упростить работу с данными на стороне браузера, и избавиться от необходимости использования таких сложных инструментов как ORM или реализаций паттернов Event Sourcing/CQRS (известных больше как redux/flux, которые больше подходят для распределенных вычислений, нежели для построения UI (где понятние Сущности (Entity) играет весомую роль)).

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

Благодаря использованию Django-Rest-Framework, создание новых REST-API Endpoints обходится в считанные человеко-часы, и, в общей сложности, backend-разработка занимает не более четверти совокупных затрат на разработку. Так же эта библиотека автоматически генерирует REST-API документацию в формате OpenAPI, предоставляя frontend-разработчикам всю необходимую информацию и даже тестовый web-интерфейс. Кроме того, эта библиотека облегчает создание тестовых стабов для фронтенда и интегрируется со swagger.

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

Процесс разработки построен по принципам Continuous Integration, реализация которых также используют облачные технологии. Continuous Integration в сочетании с Test-Driven Development гарантирует что программа в любой момент готова к релизу. А Test-Driven Development повышает качество кодовой базы, поскольку разработчику легче проектировать методы с низким уровнем сопряжения, нежели ломать голову над тем, как протестировать дырявый и запутанный класс, имеющий множество брешей в инкапсуляции.

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

С точки зрения Agile, в проекте удалось избежать практически всех известных ошибок. Тем не менее, запустить MVP можно было бы на месяц раньше, если по другому приоритезировать задачи. Некоторые задачи на момент запуска MVP оказались невостребованными. И причин тому было две:

1. Мы не сразу начали работать по Extreme Programing, а какое-то время вначале работали по Kanban. В результате лишились того важного “чувства темпа”, как у разработчиков, так и у представителей бизнеса, которое позволяет “чувствовать план” и правильно расставлять приоритеты. В итоге - просто “увлеклись” решением задач долгосрочной перспективы.

2. Недооценка одной из главных целей Extreme Programming - управление бизнес-рисками. Никто не предполагал возникновение тех бизнес-рисков, которые в итоге возникли перед самым запуском MVP.

К счастью, выводы были сделаны своевременно, и вся разработка перешла на чистый Extreme Programming.

На этом проекте я в очередной раз убедился в том, что Martin Fowler был тысячу раз прав, когда говорил:

“To make agile work, you need solid technical practices. A lot of agile education under-emphasizes these, but if you skimp on this you won’t gain the productivity and responsiveness benefits that agile development can give you (stranding you at level 1 of the agile fluency model.) This is one of the reasons that I still think that Extreme Programming is the most valuable of the named agile methods as a core and starting point.” (“Agile Software Development” by Martin Fowler)

Updated on Jun 17, 2018

Comments

comments powered by Disqus