1 added
1 removed
Original
2026-01-01
Modified
2026-02-21
1
<p><a>#статьи</a></p>
1
<p><a>#статьи</a></p>
2
<ul><li>7 дек 2023</li>
2
<ul><li>7 дек 2023</li>
3
<li>0</li>
3
<li>0</li>
4
</ul><h2>Как спроектировать архитектуру приложения с нуля</h2>
4
</ul><h2>Как спроектировать архитектуру приложения с нуля</h2>
5
<p>Пошаговое руководство для начинающих тимлидов и архитекторов.</p>
5
<p>Пошаговое руководство для начинающих тимлидов и архитекторов.</p>
6
<p>Иллюстрация: Оля Ежак для Skillbox Media</p>
6
<p>Иллюстрация: Оля Ежак для Skillbox Media</p>
7
<p>Опытные разработчики знают, что любую систему - приложение или сервис - сначала необходимо спроектировать и описать. И только потом можно открывать редактор кода и переходить к реализации.</p>
7
<p>Опытные разработчики знают, что любую систему - приложение или сервис - сначала необходимо спроектировать и описать. И только потом можно открывать редактор кода и переходить к реализации.</p>
8
<p>Но далеко не все делают именно так. Наоборот, многие команды сразу приступают к разработке на привычном технологическом стеке, имея лишь слабый набросок того, как должен выглядеть продукт.</p>
8
<p>Но далеко не все делают именно так. Наоборот, многие команды сразу приступают к разработке на привычном технологическом стеке, имея лишь слабый набросок того, как должен выглядеть продукт.</p>
9
<p><strong>Автор</strong></p>
9
<p><strong>Автор</strong></p>
10
<p>Эксперт Skillbox по бэкенд-разработке. Более 10 лет в разработке, из которых последние пять лет в финтехе. Senior backend-разработчик с несколькими пет-проектами. Пишет на PHP, Go и немного на Java.</p>
10
<p>Эксперт Skillbox по бэкенд-разработке. Более 10 лет в разработке, из которых последние пять лет в финтехе. Senior backend-разработчик с несколькими пет-проектами. Пишет на PHP, Go и немного на Java.</p>
11
<p>Может возникнуть вполне резонный вопрос: а зачем вообще тратить время на продумывание и подробное описание архитектуры?</p>
11
<p>Может возникнуть вполне резонный вопрос: а зачем вообще тратить время на продумывание и подробное описание архитектуры?</p>
12
<p>Если пропустить этот шаг, то вы рискуете столкнуться с двумя крайне неприятными последствиями: результат вашей работы не будет соответствовать ожиданиям заказчика и, вполне вероятно, в будущем вам придётся потратить много сил на рефакторинг.</p>
12
<p>Если пропустить этот шаг, то вы рискуете столкнуться с двумя крайне неприятными последствиями: результат вашей работы не будет соответствовать ожиданиям заказчика и, вполне вероятно, в будущем вам придётся потратить много сил на рефакторинг.</p>
13
<p>Образ приложения в голове разработчика может не совпадать с представлениями продуктового менеджера или владельца продукта. Может выясниться, что ваше решение не закрывает ключевые потребности пользователей, или закрывает не так, как надо, или не соответствует инфраструктуре компании. В результате придётся вносить множество изменений, а может, и вовсе переделывать проект.</p>
13
<p>Образ приложения в голове разработчика может не совпадать с представлениями продуктового менеджера или владельца продукта. Может выясниться, что ваше решение не закрывает ключевые потребности пользователей, или закрывает не так, как надо, или не соответствует инфраструктуре компании. В результате придётся вносить множество изменений, а может, и вовсе переделывать проект.</p>
14
<p>Когда человек строит сложные системы в голове, то часто упускает из виду существенные детали и связи между компонентами. Они могут не выдерживать нагрузок, плохо масштабироваться. Скорее всего, проблемы вскроются ещё на этапе тестирования и код придётся рефакторить до или сразу после сдачи проекта.</p>
14
<p>Когда человек строит сложные системы в голове, то часто упускает из виду существенные детали и связи между компонентами. Они могут не выдерживать нагрузок, плохо масштабироваться. Скорее всего, проблемы вскроются ещё на этапе тестирования и код придётся рефакторить до или сразу после сдачи проекта.</p>
15
<p>Поэтому всегда описывайте структуру приложения, его компоненты и взаимодействие между ними в отдельном документе. Такое описание нужно согласовывать с коллегами и заказчиками - это позволяет синхронизировать видение проекта и убедиться в том, что ничего важного не было упущено.</p>
15
<p>Поэтому всегда описывайте структуру приложения, его компоненты и взаимодействие между ними в отдельном документе. Такое описание нужно согласовывать с коллегами и заказчиками - это позволяет синхронизировать видение проекта и убедиться в том, что ничего важного не было упущено.</p>
16
<p>В этой статье мы составим и опишем логику работы приложения, которое будет работать внутри существующей микросервисной архитектуры. Пройдём все этапы проектирования: от сбора требований до интеграции нового проекта с другими продуктами в компании.</p>
16
<p>В этой статье мы составим и опишем логику работы приложения, которое будет работать внутри существующей микросервисной архитектуры. Пройдём все этапы проектирования: от сбора требований до интеграции нового проекта с другими продуктами в компании.</p>
17
<p><strong>Дисклеймер!</strong></p>
17
<p><strong>Дисклеймер!</strong></p>
18
<p>В этой статье я не показываю пример правильной архитектуры. Цель публикации - описать процесс мышления разработчика, который создаёт проект с нуля, и объяснить, как выстраивать процессы, чтобы получить продукт, устраивающий заказчика.</p>
18
<p>В этой статье я не показываю пример правильной архитектуры. Цель публикации - описать процесс мышления разработчика, который создаёт проект с нуля, и объяснить, как выстраивать процессы, чтобы получить продукт, устраивающий заказчика.</p>
19
<p>Первым делом необходимо собрать полную информацию о разрабатываемом продукте. Для этого потребуется человек, который больше остальных в него погружён. Обычно это продуктовый менеджер или<a>владелец продукта</a>.</p>
19
<p>Первым делом необходимо собрать полную информацию о разрабатываемом продукте. Для этого потребуется человек, который больше остальных в него погружён. Обычно это продуктовый менеджер или<a>владелец продукта</a>.</p>
20
<p>Собираем детальное описание продукта с точки зрения бизнеса:</p>
20
<p>Собираем детальное описание продукта с точки зрения бизнеса:</p>
21
<ul><li>какие бизнес-цели мы ставим перед сервисом. Например, увеличение доли компании на существующем рынке;</li>
21
<ul><li>какие бизнес-цели мы ставим перед сервисом. Например, увеличение доли компании на существующем рынке;</li>
22
<li>какие потребности бизнеса он закрывает. Например, продукт может быть направлен на максимизацию прибыли, а может - на повышение лояльности клиентов;</li>
22
<li>какие потребности бизнеса он закрывает. Например, продукт может быть направлен на максимизацию прибыли, а может - на повышение лояльности клиентов;</li>
23
<li>какие требования к продукту есть у пользователей;</li>
23
<li>какие требования к продукту есть у пользователей;</li>
24
<li>какие функциональные требования и ограничения существуют со стороны компании;</li>
24
<li>какие функциональные требования и ограничения существуют со стороны компании;</li>
25
<li>какие зависимости от других систем стоит учесть.</li>
25
<li>какие зависимости от других систем стоит учесть.</li>
26
</ul><p>Будьте готовы к тому, что заказчик не сразу ответит на все вопросы, а ответы, скорее всего, будут поверхностными. Поэтому не стесняйтесь задавать уточняющие вопросы, а при необходимости договаривайтесь на новую встречу, дав собеседнику время на подготовку.</p>
26
</ul><p>Будьте готовы к тому, что заказчик не сразу ответит на все вопросы, а ответы, скорее всего, будут поверхностными. Поэтому не стесняйтесь задавать уточняющие вопросы, а при необходимости договаривайтесь на новую встречу, дав собеседнику время на подготовку.</p>
27
<p>Ваша задача на этом этапе - получить максимально возможное количество информации о продукте и собрать её в один структурированный документ. Он нам ещё пригодится на следующих этапах.</p>
27
<p>Ваша задача на этом этапе - получить максимально возможное количество информации о продукте и собрать её в один структурированный документ. Он нам ещё пригодится на следующих этапах.</p>
28
<p>После того как вся доступная информация будет собрана, необходимо продумать нефункциональные требования. К ним относят аспекты работы приложения, которые напрямую не влияют на бизнес-показатели, но касаются пользователей и тех, кто будет поддерживать систему.</p>
28
<p>После того как вся доступная информация будет собрана, необходимо продумать нефункциональные требования. К ним относят аспекты работы приложения, которые напрямую не влияют на бизнес-показатели, но касаются пользователей и тех, кто будет поддерживать систему.</p>
29
<p>Нам нужно будет подумать о следующих факторах:</p>
29
<p>Нам нужно будет подумать о следующих факторах:</p>
30
<ul><li>доступность;</li>
30
<ul><li>доступность;</li>
31
<li>изменяемость;</li>
31
<li>изменяемость;</li>
32
<li>производительность;</li>
32
<li>производительность;</li>
33
<li>безопасность;</li>
33
<li>безопасность;</li>
34
<li>тестируемость;</li>
34
<li>тестируемость;</li>
35
<li>удобство использования;</li>
35
<li>удобство использования;</li>
36
<li>расширяемость;</li>
36
<li>расширяемость;</li>
37
<li>поддерживаемость;</li>
37
<li>поддерживаемость;</li>
38
<li>взаимодействие с другими системами.</li>
38
<li>взаимодействие с другими системами.</li>
39
</ul><p>Разберём подробно каждый пункт.</p>
39
</ul><p>Разберём подробно каждый пункт.</p>
40
<p><strong>Доступность</strong>- это период времени, в течение которого система функционирует без сбоев. Идеальное значение - 99,99%. Все стремятся к этой цифре. Ведь если компания не хочет терять пользователей, приложение должно работать в режиме 24/7.</p>
40
<p><strong>Доступность</strong>- это период времени, в течение которого система функционирует без сбоев. Идеальное значение - 99,99%. Все стремятся к этой цифре. Ведь если компания не хочет терять пользователей, приложение должно работать в режиме 24/7.</p>
41
<p><strong>Изменяемость</strong>определяет то, насколько легко мы сможем вносить корректировки в продукт или его часть, не влияя при этом на остальную функциональность. Другими словами, систему надо проектировать таким образом, чтобы модификация той или иной части кода не затронула других частей системы.</p>
41
<p><strong>Изменяемость</strong>определяет то, насколько легко мы сможем вносить корректировки в продукт или его часть, не влияя при этом на остальную функциональность. Другими словами, систему надо проектировать таким образом, чтобы модификация той или иной части кода не затронула других частей системы.</p>
42
<p><strong>Производительность</strong> - одна из самых понятных характеристик, которая показывает, какую нагрузку может выдержать система и не уйти в отказ. Ориентируйтесь не на среднестатистические, а на предельные показатели нагрузки. Чтобы получить значение, которое способна выдерживать ваша инфраструктура, нужно к этим экстремальным показателям прибавить ещё примерно 20%.</p>
42
<p><strong>Производительность</strong> - одна из самых понятных характеристик, которая показывает, какую нагрузку может выдержать система и не уйти в отказ. Ориентируйтесь не на среднестатистические, а на предельные показатели нагрузки. Чтобы получить значение, которое способна выдерживать ваша инфраструктура, нужно к этим экстремальным показателям прибавить ещё примерно 20%.</p>
43
<p><strong>Безопасность</strong> - у системы не должно быть уязвимостей. Ориентируйтесь на список<a>OWASP Top 10</a>и консультируйтесь со специалистами по информационной безопасности, если таковые имеются в компании.</p>
43
<p><strong>Безопасность</strong> - у системы не должно быть уязвимостей. Ориентируйтесь на список<a>OWASP Top 10</a>и консультируйтесь со специалистами по информационной безопасности, если таковые имеются в компании.</p>
44
<p><strong>Тестируемость</strong> - система считается тестируемой, если она легко "отдаёт" свои ошибки. То есть их легко выявить стандартными способами, например отладчиком или с помощью автоматизированного тестирования. Чем сложнее тестировать продукт, тем дороже его поддержка будет обходиться бизнесу.</p>
44
<p><strong>Тестируемость</strong> - система считается тестируемой, если она легко "отдаёт" свои ошибки. То есть их легко выявить стандартными способами, например отладчиком или с помощью автоматизированного тестирования. Чем сложнее тестировать продукт, тем дороже его поддержка будет обходиться бизнесу.</p>
45
<p><strong>Удобство использования</strong>определяет, насколько легко пользователю выполнять свои задачи и как быстро он может найти решение возникшей проблемы в документации или благодаря службе поддержки. Очевидно, что чем выше уровень удобства, тем лучше.</p>
45
<p><strong>Удобство использования</strong>определяет, насколько легко пользователю выполнять свои задачи и как быстро он может найти решение возникшей проблемы в документации или благодаря службе поддержки. Очевидно, что чем выше уровень удобства, тем лучше.</p>
46
<p><strong>Расширяемость.</strong>Заказчик может решить через год добавить в приложение новые фичи для пользователя или для команды поддержки. При их разработке и внедрении старый код не должен мешать этому.</p>
46
<p><strong>Расширяемость.</strong>Заказчик может решить через год добавить в приложение новые фичи для пользователя или для команды поддержки. При их разработке и внедрении старый код не должен мешать этому.</p>
47
<p><strong>Поддерживаемость.</strong>Работа над продуктом не заканчивается после приёмки - его необходимо поддерживать, причём не только код, но и серверную архитектуру. Поэтому система должна быть удобной для тех, кто будет её использовать в дальнейшем. Например, если разработчики в компании работают на определённом стеке технологий, то желательно, чтобы продукт был написан на нём.</p>
47
<p><strong>Поддерживаемость.</strong>Работа над продуктом не заканчивается после приёмки - его необходимо поддерживать, причём не только код, но и серверную архитектуру. Поэтому система должна быть удобной для тех, кто будет её использовать в дальнейшем. Например, если разработчики в компании работают на определённом стеке технологий, то желательно, чтобы продукт был написан на нём.</p>
48
<p><strong>Взаимодействие с другими системами</strong> - так как сервис разрабатывается внутри имеющейся микросервисной архитектуры, то важно обеспечить его взаимодействие с другими компонентами системы. Это необходимо заранее продумать, так как существующие системы никто не будет подстраивать под разрабатываемые.</p>
48
<p><strong>Взаимодействие с другими системами</strong> - так как сервис разрабатывается внутри имеющейся микросервисной архитектуры, то важно обеспечить его взаимодействие с другими компонентами системы. Это необходимо заранее продумать, так как существующие системы никто не будет подстраивать под разрабатываемые.</p>
49
<p>В любой компании параллельно идёт разработка десятков сервисов, поэтому попытки вносить изменения в существующий код для их запуска, приведут к хаосу. Поэтому компании проектируют микросервисы, подстраивая новые под уже работающие, а не наоборот.</p>
49
<p>В любой компании параллельно идёт разработка десятков сервисов, поэтому попытки вносить изменения в существующий код для их запуска, приведут к хаосу. Поэтому компании проектируют микросервисы, подстраивая новые под уже работающие, а не наоборот.</p>
50
<p>Все перечисленные факторы необходимо расписать для создаваемой системы и оформить в том же документе, что и функциональные требования, собранные от заказчика на предыдущем шаге. Теперь общее описание можно передать на согласование заказчику.</p>
50
<p>Все перечисленные факторы необходимо расписать для создаваемой системы и оформить в том же документе, что и функциональные требования, собранные от заказчика на предыдущем шаге. Теперь общее описание можно передать на согласование заказчику.</p>
51
<p>После того как все требования согласуют, архитектор или разработчик может быть уверен, что его представление о продукте совпадает с видением заказчика. Теперь можно погружаться в технические детали.</p>
51
<p>После того как все требования согласуют, архитектор или разработчик может быть уверен, что его представление о продукте совпадает с видением заказчика. Теперь можно погружаться в технические детали.</p>
52
<p>Создание архитектуры приложения разберём на примере сервиса для крупного застройщика, который возводит элитные жилые комплексы по всей России и за рубежом. Все они объединены в общую IT-инфраструктуру.</p>
52
<p>Создание архитектуры приложения разберём на примере сервиса для крупного застройщика, который возводит элитные жилые комплексы по всей России и за рубежом. Все они объединены в общую IT-инфраструктуру.</p>
53
<p>Для него мы будем создавать сервис для оплаты услуг. Может показаться, что это будет легко. Но это не так - чем больше вопросов будет задавать архитектор, тем больше важных нюансов он узнает.</p>
53
<p>Для него мы будем создавать сервис для оплаты услуг. Может показаться, что это будет легко. Но это не так - чем больше вопросов будет задавать архитектор, тем больше важных нюансов он узнает.</p>
54
<p>На первом этапе общения с заказчиком разработчик выяснил, что у компании тысячи жилых комплексов и коттеджных посёлков. Их жильцы оплачивают услуги ЖКХ, телевидение, интернет, вывоз мусора и так далее. Важно, что это не разовые платежи, а постоянные, совершаемые в разное время суток.</p>
54
<p>На первом этапе общения с заказчиком разработчик выяснил, что у компании тысячи жилых комплексов и коттеджных посёлков. Их жильцы оплачивают услуги ЖКХ, телевидение, интернет, вывоз мусора и так далее. Важно, что это не разовые платежи, а постоянные, совершаемые в разное время суток.</p>
55
<em>Кадр: сериал "Кремниевая долина" / HBO</em><p>Управляющая компания каждого комплекса - отдельное юридическое лицо, не связанное с организацией, где работает команда разработчика.</p>
55
<em>Кадр: сериал "Кремниевая долина" / HBO</em><p>Управляющая компания каждого комплекса - отдельное юридическое лицо, не связанное с организацией, где работает команда разработчика.</p>
56
<p>Часть платежей от УК приходит в другой микросервис компании, который обрабатывает их и складывает данные о проведённых транзакциях в DWH. Это первый источник информации.</p>
56
<p>Часть платежей от УК приходит в другой микросервис компании, который обрабатывает их и складывает данные о проведённых транзакциях в DWH. Это первый источник информации.</p>
57
<p>Второй источник данных - отчёты от управляющих компаний. Важный нюанс в том, что управляющие компании предоставляют данные в разных форматах. У кого-то это CSV-файлы, отправляемые на почтовый ящик, у кого-то это JSON, передаваемый по API и так далее.</p>
57
<p>Второй источник данных - отчёты от управляющих компаний. Важный нюанс в том, что управляющие компании предоставляют данные в разных форматах. У кого-то это CSV-файлы, отправляемые на почтовый ящик, у кого-то это JSON, передаваемый по API и так далее.</p>
58
<p>Задача разрабатываемого микросервиса в том, чтобы<strong>сверять данные из DWH с данными, которые предоставляют управляющие компании. Это нужно для того, чтобы контролировать управляющие компании и внутренние системы на предмет сбоев и ошибок</strong>.</p>
58
<p>Задача разрабатываемого микросервиса в том, чтобы<strong>сверять данные из DWH с данными, которые предоставляют управляющие компании. Это нужно для того, чтобы контролировать управляющие компании и внутренние системы на предмет сбоев и ошибок</strong>.</p>
59
<p>Разработчик предполагает, что пользователями системы будут сотрудники его организации, которых мы дальше будем называть саппортами, и им потребуется админка для отслеживания данных. Она будет находиться в отдельном микросервисе и сможет взаимодействовать с создаваемым приложением по API.</p>
59
<p>Разработчик предполагает, что пользователями системы будут сотрудники его организации, которых мы дальше будем называть саппортами, и им потребуется админка для отслеживания данных. Она будет находиться в отдельном микросервисе и сможет взаимодействовать с создаваемым приложением по API.</p>
60
<p>В логике приложения появились новые действующие лица - саппорты. Разработчик, исполняющий роль архитектора, должен обсудить с ними продукт и собрать информацию о том, какие функции и аспекты работы приложения они считают необходимыми. Параллельно можно узнать у саппортов, как они взаимодействуют с управляющими компаниями сейчас. Например, может выясниться, что они в ручном режиме сверяют Excel-файлы с самописными макросами, которые перешли к ним в наследство от предыдущих сотрудников.</p>
60
<p>В логике приложения появились новые действующие лица - саппорты. Разработчик, исполняющий роль архитектора, должен обсудить с ними продукт и собрать информацию о том, какие функции и аспекты работы приложения они считают необходимыми. Параллельно можно узнать у саппортов, как они взаимодействуют с управляющими компаниями сейчас. Например, может выясниться, что они в ручном режиме сверяют Excel-файлы с самописными макросами, которые перешли к ним в наследство от предыдущих сотрудников.</p>
61
<p>Давайте суммируем все требования и условия, которые смог выяснить разработчик к этому моменту:</p>
61
<p>Давайте суммируем все требования и условия, которые смог выяснить разработчик к этому моменту:</p>
62
<ul><li>микросервис должен обмениваться данными с DWH. Для этого можно использовать интеграцию по API;</li>
62
<ul><li>микросервис должен обмениваться данными с DWH. Для этого можно использовать интеграцию по API;</li>
63
<li>отчёты предоставляются в разных форматах и разным "транспортом";</li>
63
<li>отчёты предоставляются в разных форматах и разным "транспортом";</li>
64
<li>управляющие компании запускают сверку в разное время суток;</li>
64
<li>управляющие компании запускают сверку в разное время суток;</li>
65
<li>расчётные нагрузки на систему на одну сверку составляют от 1000 до 500 000 операций. Цифры получены после обсуждения сервиса с саппортами;</li>
65
<li>расчётные нагрузки на систему на одну сверку составляют от 1000 до 500 000 операций. Цифры получены после обсуждения сервиса с саппортами;</li>
66
<li>текущее количество сверок - до 40 в день;</li>
66
<li>текущее количество сверок - до 40 в день;</li>
67
<li>у некоторых управляющих компаний есть отдельный подвид финансовых операций, которые должны обрабатываться вместе с другими операциями из одной транзакции;</li>
67
<li>у некоторых управляющих компаний есть отдельный подвид финансовых операций, которые должны обрабатываться вместе с другими операциями из одной транзакции;</li>
68
<li>отчёты предоставляются посуточно с данными за предыдущий день;</li>
68
<li>отчёты предоставляются посуточно с данными за предыдущий день;</li>
69
<li>некоторые управляющие компании не присылают отчёты по выходным и праздничным дням. Поэтому их отчёты в понедельник содержат данные за несколько дней;</li>
69
<li>некоторые управляющие компании не присылают отчёты по выходным и праздничным дням. Поэтому их отчёты в понедельник содержат данные за несколько дней;</li>
70
<li>данные в отчётах распределяются не ровно посуточно, а приблизительно посуточно. То есть не получится делать выборки ровно с 00:00:00 до 23:59:59. Это связано с тем, что управляющие компании работают в разных временных зонах и имеют разное время закрытия бизнес-дня;</li>
70
<li>данные в отчётах распределяются не ровно посуточно, а приблизительно посуточно. То есть не получится делать выборки ровно с 00:00:00 до 23:59:59. Это связано с тем, что управляющие компании работают в разных временных зонах и имеют разное время закрытия бизнес-дня;</li>
71
<li>часто управляющие компании не присылают отчёты вовремя.</li>
71
<li>часто управляющие компании не присылают отчёты вовремя.</li>
72
</ul><p>Также удалось сформировать ряд технических требований к продукту:</p>
72
</ul><p>Также удалось сформировать ряд технических требований к продукту:</p>
73
<ul><li>код должен быть покрыт автотестами не менее чем на 98%;</li>
73
<ul><li>код должен быть покрыт автотестами не менее чем на 98%;</li>
74
<li>нужна система мониторинга;</li>
74
<li>нужна система мониторинга;</li>
75
<li>нужна система логирования.</li>
75
<li>нужна система логирования.</li>
76
</ul><p>От этих данных уже можно отталкиваться и переходить к проектированию.</p>
76
</ul><p>От этих данных уже можно отталкиваться и переходить к проектированию.</p>
77
<p>Лучший способ визуализировать внутреннее устройство продукта - представить его в виде диаграммы. Но, прежде чем это сделать, потребуется определить основной технологический стек.</p>
77
<p>Лучший способ визуализировать внутреннее устройство продукта - представить его в виде диаграммы. Но, прежде чем это сделать, потребуется определить основной технологический стек.</p>
78
<p>Предположим, что в команде есть два PHP-разработчика, один фронтенд-разработчик и сам сеньор-разработчик (архитектор или тимлид), который занимается проектированием. Так как он не хочет собирать новую команду разработки под новый технологический стек, то будет использовать привычный для команды с актуальной версией PHP 8.2.</p>
78
<p>Предположим, что в команде есть два PHP-разработчика, один фронтенд-разработчик и сам сеньор-разработчик (архитектор или тимлид), который занимается проектированием. Так как он не хочет собирать новую команду разработки под новый технологический стек, то будет использовать привычный для команды с актуальной версией PHP 8.2.</p>
79
<p>Что дальше? Ограничений по использованию фреймворков нет, а значит, можно выбрать между<a>Symfony</a>и <a>Laravel</a>. Архитектору стоит посоветоваться с командой, чтобы лучше понять их различия, преимущества и недостатки. Дополнительно можно почитать аналитические статьи со сравнением в профильных изданиях. Предположим, что решили остановиться на актуальной на текущий момент версии Symfony 6.4.</p>
79
<p>Что дальше? Ограничений по использованию фреймворков нет, а значит, можно выбрать между<a>Symfony</a>и <a>Laravel</a>. Архитектору стоит посоветоваться с командой, чтобы лучше понять их различия, преимущества и недостатки. Дополнительно можно почитать аналитические статьи со сравнением в профильных изданиях. Предположим, что решили остановиться на актуальной на текущий момент версии Symfony 6.4.</p>
80
<p>В проекте не обойтись без базы данных. Проще всего использовать реляционную БД, например MySQL или Postgres. Прежде чем выбрать конкретное решение, архитектор сравнивает их между собой и определяет, есть ли в команде разработки специалист по работе с конкретной базой данных.</p>
80
<p>В проекте не обойтись без базы данных. Проще всего использовать реляционную БД, например MySQL или Postgres. Прежде чем выбрать конкретное решение, архитектор сравнивает их между собой и определяет, есть ли в команде разработки специалист по работе с конкретной базой данных.</p>
81
<p>Для нового сервиса была выбрана Percona Server for MySQL 8.0, так как с ней имеют опыт работы все члены команды, а у админов есть готовые настроенные пресеты, которые они смогут быстро развернуть на стенд.</p>
81
<p>Для нового сервиса была выбрана Percona Server for MySQL 8.0, так как с ней имеют опыт работы все члены команды, а у админов есть готовые настроенные пресеты, которые они смогут быстро развернуть на стенд.</p>
82
<p>У нас сформировался базовый технологический стек:</p>
82
<p>У нас сформировался базовый технологический стек:</p>
83
<ul><li>PHP 8.2;</li>
83
<ul><li>PHP 8.2;</li>
84
<li>Symfony 6.4;</li>
84
<li>Symfony 6.4;</li>
85
<li>Percona Server for MySQL 8.0.</li>
85
<li>Percona Server for MySQL 8.0.</li>
86
</ul><p>Теперь можно сделать первый набросок архитектуры приложения. Для этого подойдёт онлайн-сервис<a>draw.io</a>или любой аналог.</p>
86
</ul><p>Теперь можно сделать первый набросок архитектуры приложения. Для этого подойдёт онлайн-сервис<a>draw.io</a>или любой аналог.</p>
87
<p>Итак, первый набросок архитектуры:</p>
87
<p>Итак, первый набросок архитектуры:</p>
88
Отмечаем известные вводные на диаграмме<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Что же есть на диаграмме? Слева сверху расположен DWH, хранящий данные от компании. Справа на диаграмме указано несколько интеграций с управляющими компаниями, которые для краткости будем называть просто интеграциями. Также отмечена админка для управления сервисом, база данных и сам сервис в центре изображения.</p>
88
Отмечаем известные вводные на диаграмме<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Что же есть на диаграмме? Слева сверху расположен DWH, хранящий данные от компании. Справа на диаграмме указано несколько интеграций с управляющими компаниями, которые для краткости будем называть просто интеграциями. Также отмечена админка для управления сервисом, база данных и сам сервис в центре изображения.</p>
89
<p>Сейчас это общая диаграмма, которая показывает только то, как сервис взаимодействует с другими элементами. Но пока что неясно, что собой представляет он сам.</p>
89
<p>Сейчас это общая диаграмма, которая показывает только то, как сервис взаимодействует с другими элементами. Но пока что неясно, что собой представляет он сам.</p>
90
<p>Задача разрабатываемого сервиса - сверять пачки (чанки) операций между DWH и данными от управляющих компаний посуточно или около того. Если обобщить, то за какой-либо не полностью нормированный интервал, который чаще равен суткам и не превышает трёх дней. Напомню, что некоторые управляющие компании не работают в выходные, поэтому их данные накапливаются в течение субботы, воскресенья и понедельника.</p>
90
<p>Задача разрабатываемого сервиса - сверять пачки (чанки) операций между DWH и данными от управляющих компаний посуточно или около того. Если обобщить, то за какой-либо не полностью нормированный интервал, который чаще равен суткам и не превышает трёх дней. Напомню, что некоторые управляющие компании не работают в выходные, поэтому их данные накапливаются в течение субботы, воскресенья и понедельника.</p>
91
<p>Исходя из задачи сервиса можно определить, какие ключевые сущности он будет содержать.</p>
91
<p>Исходя из задачи сервиса можно определить, какие ключевые сущности он будет содержать.</p>
92
<p>Сразу запишем самые очевидные из них:</p>
92
<p>Сразу запишем самые очевидные из них:</p>
93
<ul><li><strong>DwhOperation</strong> - операция со стороны DWH, которой должна найтись пара на стороне вендора - управляющей компании через интеграции;</li>
93
<ul><li><strong>DwhOperation</strong> - операция со стороны DWH, которой должна найтись пара на стороне вендора - управляющей компании через интеграции;</li>
94
<li><strong>VendorOperation</strong> - операция со стороны вендора;</li>
94
<li><strong>VendorOperation</strong> - операция со стороны вендора;</li>
95
<li><strong>ReconciliationResult</strong> - результат сверки конкретных операций;</li>
95
<li><strong>ReconciliationResult</strong> - результат сверки конкретных операций;</li>
96
<li><strong>ReconciliationTask</strong> - сущность, которая отражает процесс сверки;</li>
96
<li><strong>ReconciliationTask</strong> - сущность, которая отражает процесс сверки;</li>
97
<li><strong>ReconciliationCalendar</strong> - календарь сверок, который будет регламентировать праздничные и выходные дни разных компаний.</li>
97
<li><strong>ReconciliationCalendar</strong> - календарь сверок, который будет регламентировать праздничные и выходные дни разных компаний.</li>
98
</ul><p>Названия сущностей должны быть понятными и отражать то, что эта сущность делает. Пока что может быть сложно понять их назначение, но мы подробно разберём это дальше.</p>
98
</ul><p>Названия сущностей должны быть понятными и отражать то, что эта сущность делает. Пока что может быть сложно понять их назначение, но мы подробно разберём это дальше.</p>
99
<p>Далее я приведу атрибуты каждой сущности.</p>
99
<p>Далее я приведу атрибуты каждой сущности.</p>
100
<p><strong>DwhOperation:</strong></p>
100
<p><strong>DwhOperation:</strong></p>
101
<ul><li>operationId - основной идентификатор операции на стороне нашей компании;</li>
101
<ul><li>operationId - основной идентификатор операции на стороне нашей компании;</li>
102
<li>transactionId - транзакция в которую входит несколько операций;</li>
102
<li>transactionId - транзакция в которую входит несколько операций;</li>
103
<li>amount - сумма операции в заданных единицах;</li>
103
<li>amount - сумма операции в заданных единицах;</li>
104
<li>currency - валюта проведения операции;</li>
104
<li>currency - валюта проведения операции;</li>
105
<li>createdAt - дата и время создания операции по UTC;</li>
105
<li>createdAt - дата и время создания операции по UTC;</li>
106
<li>vendorPaymentId - идентификатор операции на стороне вендора;</li>
106
<li>vendorPaymentId - идентификатор операции на стороне вендора;</li>
107
<li>operationTypeId - тип операции: оплата, возврат, кешбэк, комиссия, списание по подписке и так далее;</li>
107
<li>operationTypeId - тип операции: оплата, возврат, кешбэк, комиссия, списание по подписке и так далее;</li>
108
<li>operationStatusId - статус операции: success, decline, outdated и другие.</li>
108
<li>operationStatusId - статус операции: success, decline, outdated и другие.</li>
109
</ul><p><strong>VendorOperation:</strong></p>
109
</ul><p><strong>VendorOperation:</strong></p>
110
<ul><li>vendorPaymentId - идентификатор операции на стороне вендора;</li>
110
<ul><li>vendorPaymentId - идентификатор операции на стороне вендора;</li>
111
<li>amount - сумма операции в заданных единицах;</li>
111
<li>amount - сумма операции в заданных единицах;</li>
112
<li>currency - валюта проведения операции;</li>
112
<li>currency - валюта проведения операции;</li>
113
<li>createdAt - дата и время создания операции, приведённое к UTC;</li>
113
<li>createdAt - дата и время создания операции, приведённое к UTC;</li>
114
<li>operationTypeId - тип операции по версии вендора, который, вероятнее всего, не будет совпадать с нашими типами;</li>
114
<li>operationTypeId - тип операции по версии вендора, который, вероятнее всего, не будет совпадать с нашими типами;</li>
115
<li>operationStatusId - статус операции по версии вендора, который, вероятнее всего, не будет совпадать с нашими статусами.</li>
115
<li>operationStatusId - статус операции по версии вендора, который, вероятнее всего, не будет совпадать с нашими статусами.</li>
116
</ul><p><strong>ReconciliationResult:</strong></p>
116
</ul><p><strong>ReconciliationResult:</strong></p>
117
<ul><li>dwhOperationId - идентификатор операции DWH;</li>
117
<ul><li>dwhOperationId - идентификатор операции DWH;</li>
118
<li>vendorOperationId - идентификатор операции вендора;</li>
118
<li>vendorOperationId - идентификатор операции вендора;</li>
119
<li>reconciliationTaskId - идентификатор задачи сверки, к которому относится результат сверки;</li>
119
<li>reconciliationTaskId - идентификатор задачи сверки, к которому относится результат сверки;</li>
120
<li>status - статус сверки.</li>
120
<li>status - статус сверки.</li>
121
</ul><p><strong>ReconciliationTask:</strong></p>
121
</ul><p><strong>ReconciliationTask:</strong></p>
122
<ul><li>id - идентификатор задачи сверки;</li>
122
<ul><li>id - идентификатор задачи сверки;</li>
123
<li>reportDate - дата отчёта;</li>
123
<li>reportDate - дата отчёта;</li>
124
<li>status - статус задачи сверки;</li>
124
<li>status - статус задачи сверки;</li>
125
<li>vendor - название управляющей компании;</li>
125
<li>vendor - название управляющей компании;</li>
126
<li>createdAt - дата и время создания задачи сверки;</li>
126
<li>createdAt - дата и время создания задачи сверки;</li>
127
<li>updatedAt - дата и время обновления задачи сверки;</li>
127
<li>updatedAt - дата и время обновления задачи сверки;</li>
128
<li>error - текст ошибки, если такая имеется.</li>
128
<li>error - текст ошибки, если такая имеется.</li>
129
</ul><p><strong>ReconciliationCalendar</strong></p>
129
</ul><p><strong>ReconciliationCalendar</strong></p>
130
<ul><li>id - идентификатор записи в календаре;</li>
130
<ul><li>id - идентификатор записи в календаре;</li>
131
<li>date - дата;</li>
131
<li>date - дата;</li>
132
<li>process - запускать процесс или нет (boolean-поле);</li>
132
<li>process - запускать процесс или нет (boolean-поле);</li>
133
<li>vendor - название вендора;</li>
133
<li>vendor - название вендора;</li>
134
<li>createdAt - дата и время создания записи в календаре;</li>
134
<li>createdAt - дата и время создания записи в календаре;</li>
135
<li>updatedAt - дата и время обновления записи в календаре.</li>
135
<li>updatedAt - дата и время обновления записи в календаре.</li>
136
</ul><p>Откуда взялись эти сущности и атрибуты? Их определил разработчик на основе всей собранной ранее информации. На этом этапе проектирования требуется включить воображение и подумать о тех сущностях, которые будут описывать бизнес-процессы продукта и события из реального мира.</p>
136
</ul><p>Откуда взялись эти сущности и атрибуты? Их определил разработчик на основе всей собранной ранее информации. На этом этапе проектирования требуется включить воображение и подумать о тех сущностях, которые будут описывать бизнес-процессы продукта и события из реального мира.</p>
137
<p>Попробуем обобщить задачу. У компании есть<strong>операция на её стороне</strong>, которую необходимо сверить с <strong>операцией на стороне вендора</strong>и в результате получить какой-то<strong>результат сверки</strong>. Это может быть информация о том, что данные и результат операции у компании и вендора полностью совпадают. Всё это будет происходить в процессе, который мы назвали<strong>задачей (task) сверки</strong>, а для управления запуском этого процесса будем использовать<strong>календарь сверок</strong>.</p>
137
<p>Попробуем обобщить задачу. У компании есть<strong>операция на её стороне</strong>, которую необходимо сверить с <strong>операцией на стороне вендора</strong>и в результате получить какой-то<strong>результат сверки</strong>. Это может быть информация о том, что данные и результат операции у компании и вендора полностью совпадают. Всё это будет происходить в процессе, который мы назвали<strong>задачей (task) сверки</strong>, а для управления запуском этого процесса будем использовать<strong>календарь сверок</strong>.</p>
138
<p>Посмотрим на схему со всеми базовыми сущностями и их атрибутами:</p>
138
<p>Посмотрим на схему со всеми базовыми сущностями и их атрибутами:</p>
139
Схема становится больше. Теперь мы видим то, что находится внутри самого микросервиса<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Пока что картина далека от готового продукта, так как разработчик обозначил только основные понятия навскидку. Теперь пришло время добавить детализации и продумать, как будет происходить сверка.</p>
139
Схема становится больше. Теперь мы видим то, что находится внутри самого микросервиса<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Пока что картина далека от готового продукта, так как разработчик обозначил только основные понятия навскидку. Теперь пришло время добавить детализации и продумать, как будет происходить сверка.</p>
140
<p>Следующий шаг - подумать, как будет проходить процесс сверки с технической точки зрения. Сейчас известна только отправная и конечная точка, а что и как происходит между ними - неясно. Чтобы сервис работал, это нужно прописать.</p>
140
<p>Следующий шаг - подумать, как будет проходить процесс сверки с технической точки зрения. Сейчас известна только отправная и конечная точка, а что и как происходит между ними - неясно. Чтобы сервис работал, это нужно прописать.</p>
141
<p>Разобраться в том, как проходит процесс сверки, помогут правильные вопросы:</p>
141
<p>Разобраться в том, как проходит процесс сверки, помогут правильные вопросы:</p>
142
<ul><li>Как он будет запускаться?</li>
142
<ul><li>Как он будет запускаться?</li>
143
<li>По какому алгоритму будет проходить процесс сверки?</li>
143
<li>По какому алгоритму будет проходить процесс сверки?</li>
144
<li>Как нужно делать выборки данных для сверки?</li>
144
<li>Как нужно делать выборки данных для сверки?</li>
145
<li>Каков объём этих данных?</li>
145
<li>Каков объём этих данных?</li>
146
<li>Можно ли запустить параллельную обработку данных или их нужно обрабатывать в один поток?</li>
146
<li>Можно ли запустить параллельную обработку данных или их нужно обрабатывать в один поток?</li>
147
<li>Как технически будет проходить передача данных?</li>
147
<li>Как технически будет проходить передача данных?</li>
148
<li>Как будет работать схема для вендоров, которые не прислали отчёт вовремя?</li>
148
<li>Как будет работать схема для вендоров, которые не прислали отчёт вовремя?</li>
149
<li>Как выделить интерфейс для вендоров так, чтобы реализовать простые интеграции с каждым из них?</li>
149
<li>Как выделить интерфейс для вендоров так, чтобы реализовать простые интеграции с каждым из них?</li>
150
<li>Как реализовать систему расписания сверок?</li>
150
<li>Как реализовать систему расписания сверок?</li>
151
<li>Как реализовать кастомизированные процессы сверок для компаний, у которых есть транзакционная сверка?</li>
151
<li>Как реализовать кастомизированные процессы сверок для компаний, у которых есть транзакционная сверка?</li>
152
</ul><p>Начать стоит с глубокого изучения данных. Можно попробовать сверить небольшой кусок вручную или написать простейший скрипт, который сделает это автоматически. Такой подход поможет выявить довольно большое количество интересных деталей, которые потребуется учесть для построения правильной архитектуры нового приложения.</p>
152
</ul><p>Начать стоит с глубокого изучения данных. Можно попробовать сверить небольшой кусок вручную или написать простейший скрипт, который сделает это автоматически. Такой подход поможет выявить довольно большое количество интересных деталей, которые потребуется учесть для построения правильной архитектуры нового приложения.</p>
153
<p>После анализа архитектору стало понятно, что нужно сопоставлять операции друг с другом по какому-то свойству. В текущей версии событий есть всего одно свойство, по которому это можно сделать, - vendorPaymentId, так как этот ключ есть и в операции DWH, и в отчётах вендора. Поэтому оно будет ключом для сопоставления операций.</p>
153
<p>После анализа архитектору стало понятно, что нужно сопоставлять операции друг с другом по какому-то свойству. В текущей версии событий есть всего одно свойство, по которому это можно сделать, - vendorPaymentId, так как этот ключ есть и в операции DWH, и в отчётах вендора. Поэтому оно будет ключом для сопоставления операций.</p>
154
-
<p>Но известно, что у многих вендоров это поле не является уникальным и может содержать под собой несколько различных операций, например продажу и возврат. Поэтому ключ сопоставлен��я следует сделать составным - он будет включать в себя vendorPaymentId и тип операции.</p>
154
+
<p>Но известно, что у многих вендоров это поле не является уникальным и может содержать под собой несколько различных операций, например продажу и возврат. Поэтому ключ сопоставления следует сделать составным - он будет включать в себя vendorPaymentId и тип операции.</p>
155
<p>Вопрос с ключами решён. Теперь можно рассмотреть сценарии сверки, которые будут возникать в процессе сопоставления операций.</p>
155
<p>Вопрос с ключами решён. Теперь можно рассмотреть сценарии сверки, которые будут возникать в процессе сопоставления операций.</p>
156
<p>Какие сценарии могут быть:</p>
156
<p>Какие сценарии могут быть:</p>
157
<ul><li>мы смогли подобрать операции, и все их параметры полностью сошлись;</li>
157
<ul><li>мы смогли подобрать операции, и все их параметры полностью сошлись;</li>
158
<li>мы смогли подобрать операции, но разошлась сумма;</li>
158
<li>мы смогли подобрать операции, но разошлась сумма;</li>
159
<li>мы смогли подобрать операции, но разошлась валюта;</li>
159
<li>мы смогли подобрать операции, но разошлась валюта;</li>
160
<li>мы смогли подобрать операции, но разошлась как сумма, так и валюта;</li>
160
<li>мы смогли подобрать операции, но разошлась как сумма, так и валюта;</li>
161
<li>мы нашли операцию на стороне DWH, но не нашли на стороне вендора данных;</li>
161
<li>мы нашли операцию на стороне DWH, но не нашли на стороне вендора данных;</li>
162
<li>мы нашли операцию на стороне вендора данных, но не нашли на стороне DWH.</li>
162
<li>мы нашли операцию на стороне вендора данных, но не нашли на стороне DWH.</li>
163
</ul><p>Отправной точкой сверки является отчёт, так как в нём данные уже каким-то образом привязаны к временному интервалу. Так как данных может быть очень много, то проводить поиск поштучно не лучший вариант. Это приведёт к повышенной нагрузке на DWH и всю сеть в целом.</p>
163
</ul><p>Отправной точкой сверки является отчёт, так как в нём данные уже каким-то образом привязаны к временному интервалу. Так как данных может быть очень много, то проводить поиск поштучно не лучший вариант. Это приведёт к повышенной нагрузке на DWH и всю сеть в целом.</p>
164
<p>Значит, необходимо сначала получить данные от вендора и только затем из DWH, выбрав те, которые присутствуют в отчёте управляющей компании. Это можно сделать запросом по ключам сопоставления. Но если ограничиться только такой выборкой, то не получится закрыть сценарий, когда операция нашлась на стороне DWH, но не нашлась на стороне вендора.</p>
164
<p>Значит, необходимо сначала получить данные от вендора и только затем из DWH, выбрав те, которые присутствуют в отчёте управляющей компании. Это можно сделать запросом по ключам сопоставления. Но если ограничиться только такой выборкой, то не получится закрыть сценарий, когда операция нашлась на стороне DWH, но не нашлась на стороне вендора.</p>
165
<p>Возникает вопрос: как это учесть? Самый очевидный способ - делать выборку по времени, например с даты и времени создания операции, сверенной последней в предыдущем таске сверки, и до даты и времени создания операции, сверенной последней в текущем таске сверки. Таким образом мы сможем выбрать все операции из DWH, которые подпадают под интервал операций в отчёте вендора данных.</p>
165
<p>Возникает вопрос: как это учесть? Самый очевидный способ - делать выборку по времени, например с даты и времени создания операции, сверенной последней в предыдущем таске сверки, и до даты и времени создания операции, сверенной последней в текущем таске сверки. Таким образом мы сможем выбрать все операции из DWH, которые подпадают под интервал операций в отчёте вендора данных.</p>
166
<p>Но как это реализовать? Необходима стадийность сверки, так как некоторые процессы внутри неё не могут идти параллельно, а значит, их нужно запускать последовательно друг за другом. При этом каждая стадия будет опираться на данные, полученные на предыдущей стадии.</p>
166
<p>Но как это реализовать? Необходима стадийность сверки, так как некоторые процессы внутри неё не могут идти параллельно, а значит, их нужно запускать последовательно друг за другом. При этом каждая стадия будет опираться на данные, полученные на предыдущей стадии.</p>
167
<p>Таким образом, у разработчика-архитектора появляется понимание того, что у сверки должны быть стадии и результат работы получается только по итогу прохождения через каждую из них.</p>
167
<p>Таким образом, у разработчика-архитектора появляется понимание того, что у сверки должны быть стадии и результат работы получается только по итогу прохождения через каждую из них.</p>
168
<p>Сразу возникают новые вопросы:</p>
168
<p>Сразу возникают новые вопросы:</p>
169
<ul><li>Какие это будут стадии?</li>
169
<ul><li>Какие это будут стадии?</li>
170
<li>Сколько их будет?</li>
170
<li>Сколько их будет?</li>
171
<li>Как они будут взаимодействовать друг с другом?</li>
171
<li>Как они будут взаимодействовать друг с другом?</li>
172
<li>Какой транспорт данных будет между стадиями?</li>
172
<li>Какой транспорт данных будет между стадиями?</li>
173
</ul><p>Без ответов на эти вопросы идти дальше не стоит. Надо вновь подумать и представить логику всего процесса.</p>
173
</ul><p>Без ответов на эти вопросы идти дальше не стоит. Надо вновь подумать и представить логику всего процесса.</p>
174
<p>У нашего архитектора получится такой список стадий сверки:</p>
174
<p>У нашего архитектора получится такой список стадий сверки:</p>
175
<p><strong>1. initiated</strong> - стартовая стадия. Запускается, когда становится понятно, что необходимо что-то сверить. На этой стадии создаётся таск сверки, в который передаются необходимые для этого параметры: название вендора, дата сверки и так далее.</p>
175
<p><strong>1. initiated</strong> - стартовая стадия. Запускается, когда становится понятно, что необходимо что-то сверить. На этой стадии создаётся таск сверки, в который передаются необходимые для этого параметры: название вендора, дата сверки и так далее.</p>
176
<p><strong>2. get_vendor_operations</strong>- на этой стадии сервис получает и сохраняет ответ от вендора. Здесь появляется хороший вопрос - куда мы всё это сохраняем? Вернёмся к нему позже.</p>
176
<p><strong>2. get_vendor_operations</strong>- на этой стадии сервис получает и сохраняет ответ от вендора. Здесь появляется хороший вопрос - куда мы всё это сохраняем? Вернёмся к нему позже.</p>
177
<p><strong>3. get_dwh_operations</strong> - стадия получения данных из DWH для сверки по ключам сопоставления.</p>
177
<p><strong>3. get_dwh_operations</strong> - стадия получения данных из DWH для сверки по ключам сопоставления.</p>
178
<p>Стадии 2 и 3 можно было бы объединить. Но в этом случае стадия будет перегружена из-за выполнения двух логических действий - одновременного получения данных от вендора и из DWH. Так как стоит придерживаться принципов SOLID, то её лучше разделить на две.</p>
178
<p>Стадии 2 и 3 можно было бы объединить. Но в этом случае стадия будет перегружена из-за выполнения двух логических действий - одновременного получения данных от вендора и из DWH. Так как стоит придерживаться принципов SOLID, то её лучше разделить на две.</p>
179
<p><strong>4. reconciliation_by_keys</strong> - сверка по ключам сопоставления. В этот момент сервис получает список первых результатов сверки, а также дату и время последней, сверенной в текущем таске сверки, операции.</p>
179
<p><strong>4. reconciliation_by_keys</strong> - сверка по ключам сопоставления. В этот момент сервис получает список первых результатов сверки, а также дату и время последней, сверенной в текущем таске сверки, операции.</p>
180
<p><strong>5. get_dwh_operations_by_interval</strong> - получение данных из DWH по интервалу. Интервал, как мы помним, определяется датой и временем операции, сверенной последней в предыдущем таске сверки и датой и временем операции, сверенной последней в текущем таске сверки. Эту дату сервис выявил на предыдущей стадии.</p>
180
<p><strong>5. get_dwh_operations_by_interval</strong> - получение данных из DWH по интервалу. Интервал, как мы помним, определяется датой и временем операции, сверенной последней в предыдущем таске сверки и датой и временем операции, сверенной последней в текущем таске сверки. Эту дату сервис выявил на предыдущей стадии.</p>
181
<p><strong>6. reconciliation_by_interval</strong> - сверка операций по интервалу.</p>
181
<p><strong>6. reconciliation_by_interval</strong> - сверка операций по интервалу.</p>
182
<p><strong>7. reconciliation_results_saving</strong> - сохранение результатов сверки. Для упрощения будем считать, что результат сверки сохраняется в DWH, а не в отдельное хранилище.</p>
182
<p><strong>7. reconciliation_results_saving</strong> - сохранение результатов сверки. Для упрощения будем считать, что результат сверки сохраняется в DWH, а не в отдельное хранилище.</p>
183
<p><strong>8. finish_reconciliation</strong> - закрываем все процессы, формируем данные для админки и завершаем процесс сверки.</p>
183
<p><strong>8. finish_reconciliation</strong> - закрываем все процессы, формируем данные для админки и завершаем процесс сверки.</p>
184
<p>Так как нам точно потребуется API для работы с админкой, то сразу запланируем его наличие.</p>
184
<p>Так как нам точно потребуется API для работы с админкой, то сразу запланируем его наличие.</p>
185
<p>Посмотрим на схему с внесёнными дополнениями:</p>
185
<p>Посмотрим на схему с внесёнными дополнениями:</p>
186
На диаграмме появился большой блок со стадиями сверки<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Схема стала более полной, но пока остаются открытые вопросы. Например, непонятно, как сверка будет запускаться, как будет осуществляться транспорт данных, взаимодействие классов и так далее.</p>
186
На диаграмме появился большой блок со стадиями сверки<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Схема стала более полной, но пока остаются открытые вопросы. Например, непонятно, как сверка будет запускаться, как будет осуществляться транспорт данных, взаимодействие классов и так далее.</p>
187
<p>Первый вопрос, который должен задать архитектор: как будет запускаться каждая сверка? Пока что неизвестно, что будет для неё триггером и как это будет работать в деталях.</p>
187
<p>Первый вопрос, который должен задать архитектор: как будет запускаться каждая сверка? Пока что неизвестно, что будет для неё триггером и как это будет работать в деталях.</p>
188
<p>Прежде чем найти решение, стоит подумать о том, каким образом будет построена работа приложения в целом. Прояснить это помогут следующие вопросы:</p>
188
<p>Прежде чем найти решение, стоит подумать о том, каким образом будет построена работа приложения в целом. Прояснить это помогут следующие вопросы:</p>
189
<ul><li>Запуск будет происходить командой из интерфейса командной строки?</li>
189
<ul><li>Запуск будет происходить командой из интерфейса командной строки?</li>
190
<li>Можно ли будет управлять запуском из интерфейса?</li>
190
<li>Можно ли будет управлять запуском из интерфейса?</li>
191
<li>Каждая стадия должна запускаться автоматически?</li>
191
<li>Каждая стадия должна запускаться автоматически?</li>
192
<li>Что будет переключать стадии?</li>
192
<li>Что будет переключать стадии?</li>
193
<li>На чём будет работать стадийность - на кронах или на очередях или, возможно, каким-то другим способом?</li>
193
<li>На чём будет работать стадийность - на кронах или на очередях или, возможно, каким-то другим способом?</li>
194
</ul><p>Допустим, в нашем примере разработчик отказался от ручного запуска и хочет, чтобы всё происходило автоматически. То есть возможности управлять стадиями через интерфейс не будет.</p>
194
</ul><p>Допустим, в нашем примере разработчик отказался от ручного запуска и хочет, чтобы всё происходило автоматически. То есть возможности управлять стадиями через интерфейс не будет.</p>
195
<p>Значит, остаётся выбрать, на каком подходе будет построена система стадий и вся сверочная линия в целом. Архитектор решает рассмотреть три возможных варианта реализации.</p>
195
<p>Значит, остаётся выбрать, на каком подходе будет построена система стадий и вся сверочная линия в целом. Архитектор решает рассмотреть три возможных варианта реализации.</p>
196
<p>Преимущества:</p>
196
<p>Преимущества:</p>
197
<ul><li>простая реализация;</li>
197
<ul><li>простая реализация;</li>
198
<li>кратчайшие сроки разработки.</li>
198
<li>кратчайшие сроки разработки.</li>
199
</ul><p>Недостатки:</p>
199
</ul><p>Недостатки:</p>
200
<ul><li>низкая производительность;</li>
200
<ul><li>низкая производительность;</li>
201
<li>если в системе что-то упадёт, то упадёт и весь процесс без возможности восстановления;</li>
201
<li>если в системе что-то упадёт, то упадёт и весь процесс без возможности восстановления;</li>
202
<li>тяжёлая поддержка - долгие процессы сложнее мониторить;</li>
202
<li>тяжёлая поддержка - долгие процессы сложнее мониторить;</li>
203
<li>отсутствие масштабируемости;</li>
203
<li>отсутствие масштабируемости;</li>
204
<li>отсутствие возможности перезапуска конкретной стадии;</li>
204
<li>отсутствие возможности перезапуска конкретной стадии;</li>
205
<li>расписание запусков придётся хранить в операционной системе. Это плохо, так как расписание относится к бизнес-логике самого приложения;</li>
205
<li>расписание запусков придётся хранить в операционной системе. Это плохо, так как расписание относится к бизнес-логике самого приложения;</li>
206
<li>аллокация большого количества ресурсов сервера на долгий срок.</li>
206
<li>аллокация большого количества ресурсов сервера на долгий срок.</li>
207
</ul><p>Преимущества:</p>
207
</ul><p>Преимущества:</p>
208
<ul><li>аллокация ресурсов сервера на короткие промежутки времени;</li>
208
<ul><li>аллокация ресурсов сервера на короткие промежутки времени;</li>
209
<li>масштабируемость;</li>
209
<li>масштабируемость;</li>
210
<li>возможность перезапуска стадий;</li>
210
<li>возможность перезапуска стадий;</li>
211
<li>организовать мониторинг проще, чем в предыдущем варианте.</li>
211
<li>организовать мониторинг проще, чем в предыдущем варианте.</li>
212
</ul><p>Недостатки:</p>
212
</ul><p>Недостатки:</p>
213
<ul><li>более сложная реализация по сравнению с вариантом с кронами;</li>
213
<ul><li>более сложная реализация по сравнению с вариантом с кронами;</li>
214
<li>срок разработки больше.</li>
214
<li>срок разработки больше.</li>
215
</ul><p>Преимущество: можем потенциально выиграть время и повысить скорость обработки данных. Но это не точно!</p>
215
</ul><p>Преимущество: можем потенциально выиграть время и повысить скорость обработки данных. Но это не точно!</p>
216
<p>Недостатки:</p>
216
<p>Недостатки:</p>
217
<ul><li>очень сложная реализация;</li>
217
<ul><li>очень сложная реализация;</li>
218
<li>долгая разработка;</li>
218
<li>долгая разработка;</li>
219
<li>есть вопросы к целесообразности решения для этой задачи.</li>
219
<li>есть вопросы к целесообразности решения для этой задачи.</li>
220
</ul><p>Исходя из предложенных вариантов, архитектор делает вывод, что лучший вариант второй - очереди с супервизором.</p>
220
</ul><p>Исходя из предложенных вариантов, архитектор делает вывод, что лучший вариант второй - очереди с супервизором.</p>
221
<p><strong>Важно!</strong>Мы описываем абстрактный пример, и этот вариант архитектуры, возможо, не самый оптимальный. Но для понимания общего подхода к созданию архитектуры приложений его будет достаточно.</p>
221
<p><strong>Важно!</strong>Мы описываем абстрактный пример, и этот вариант архитектуры, возможо, не самый оптимальный. Но для понимания общего подхода к созданию архитектуры приложений его будет достаточно.</p>
222
<p>Теперь важно решить, как будет запускаться приложение и кто будет управлять переключением стадий.</p>
222
<p>Теперь важно решить, как будет запускаться приложение и кто будет управлять переключением стадий.</p>
223
<p>Предположим, что время запуска не нужно указывать с точностью до секунды, а значит, в настройках каждой интеграции можно использовать cron-подобное расписание, то есть выполняющее задачи в определённое время. Поэтому в приложении пригодится какой-то класс, консольная команда, которая будет запускаться раз в минуту, сверять часы и анализировать, исходя из настроек интеграций и календаря ReconciliationCalendar, какие сверки стоит запустить в конкретную минуту.</p>
223
<p>Предположим, что время запуска не нужно указывать с точностью до секунды, а значит, в настройках каждой интеграции можно использовать cron-подобное расписание, то есть выполняющее задачи в определённое время. Поэтому в приложении пригодится какой-то класс, консольная команда, которая будет запускаться раз в минуту, сверять часы и анализировать, исходя из настроек интеграций и календаря ReconciliationCalendar, какие сверки стоит запустить в конкретную минуту.</p>
224
<p>Проще всего это сделать консольной командой, внутри которой будет логика запуска с последующим вызовом функции sleep, которую впоследствии поставим под супервизор. Назовём этот класс ReconciliationStarter. Он будет создавать таски в очередь на обработку и таски для сущности ReconciliationTask.</p>
224
<p>Проще всего это сделать консольной командой, внутри которой будет логика запуска с последующим вызовом функции sleep, которую впоследствии поставим под супервизор. Назовём этот класс ReconciliationStarter. Он будет создавать таски в очередь на обработку и таски для сущности ReconciliationTask.</p>
225
<p>Как будет устроено управление процессами стадий? Для этого создаётся класс ReconciliationManager. Это демон, обрабатывающий свою собственную очередь и переключающий стадии сверок по их завершении.</p>
225
<p>Как будет устроено управление процессами стадий? Для этого создаётся класс ReconciliationManager. Это демон, обрабатывающий свою собственную очередь и переключающий стадии сверок по их завершении.</p>
226
<p>Если архитектор посмотрит на схему, то поймёт, что предусмотрел не все поля сущностей. Необходимо добавить новые:</p>
226
<p>Если архитектор посмотрит на схему, то поймёт, что предусмотрел не все поля сущностей. Необходимо добавить новые:</p>
227
<p>ReconciliationResult.additionalInfo - п оле для хранения детализированной информации о найденных расхождениях между операциями.</p>
227
<p>ReconciliationResult.additionalInfo - п оле для хранения детализированной информации о найденных расхождениях между операциями.</p>
228
<p>ReconciliationTask.attempts - счётчик количества попыток свериться. Он необходим, так как ряд вендоров может присылать отчёты не по расписанию, а с опозданием. В этом случае нужнам механика перезапуска отдельной стадии по отложенному таймеру. Это как раз позволяет реализовать выбранный вариант реализации стадийности.</p>
228
<p>ReconciliationTask.attempts - счётчик количества попыток свериться. Он необходим, так как ряд вендоров может присылать отчёты не по расписанию, а с опозданием. В этом случае нужнам механика перезапуска отдельной стадии по отложенному таймеру. Это как раз позволяет реализовать выбранный вариант реализации стадийности.</p>
229
<p>ReconciliationTask.duration - будет хранить среднее значение времени работы одной сверки.</p>
229
<p>ReconciliationTask.duration - будет хранить среднее значение времени работы одной сверки.</p>
230
<p>ReconciliationTask.lastOperationDt - поле для сохранения даты и времени последней сверенной операции в таске сверки в таймзоне UTC.</p>
230
<p>ReconciliationTask.lastOperationDt - поле для сохранения даты и времени последней сверенной операции в таске сверки в таймзоне UTC.</p>
231
<p>ReconciliationTask.comment - необязательное поле с комментарием от саппорта к таскам сверки.</p>
231
<p>ReconciliationTask.comment - необязательное поле с комментарием от саппорта к таскам сверки.</p>
232
<p>Остаётся несколько важных технических и архитектурных вопросов:</p>
232
<p>Остаётся несколько важных технических и архитектурных вопросов:</p>
233
<ul><li>Как будет происходить передача данных между стадиями?</li>
233
<ul><li>Как будет происходить передача данных между стадиями?</li>
234
<li>На чём должны быть реализованы очереди?</li>
234
<li>На чём должны быть реализованы очереди?</li>
235
<li>Как обрабатывать разные форматы отчётов?</li>
235
<li>Как обрабатывать разные форматы отчётов?</li>
236
<li>Как обрабатывать специфические случаи?</li>
236
<li>Как обрабатывать специфические случаи?</li>
237
</ul><p>Разберём вопросы по порядку, начав с транспорта данных. Какие технологии доступны команде разработки? Что принято использовать в компании? С чем разработчики из команды имеют опыт работы?</p>
237
</ul><p>Разберём вопросы по порядку, начав с транспорта данных. Какие технологии доступны команде разработки? Что принято использовать в компании? С чем разработчики из команды имеют опыт работы?</p>
238
<p>Представим, что после ответа на эти вопросы остаётся два кандидата - это<a>Memcached</a>и <a>Redis</a>. Обе технологии доступны и используются в компании, и с обеими из них у команды есть опыт работы. Так какую же выбрать, если обе такие хорошие?</p>
238
<p>Представим, что после ответа на эти вопросы остаётся два кандидата - это<a>Memcached</a>и <a>Redis</a>. Обе технологии доступны и используются в компании, и с обеими из них у команды есть опыт работы. Так какую же выбрать, если обе такие хорошие?</p>
239
<p>В таких случаях полезно смотреть на исходное предназначение инструментов и их различия.</p>
239
<p>В таких случаях полезно смотреть на исходное предназначение инструментов и их различия.</p>
240
<p><strong>Memcached</strong> - высокопроизводительный сервис, работает быстро вне зависимости от количества хранимых данных. Быстрее, чем Redis. Можно сказать, что это хранилище "ключ - значение", поддерживающее атомарные операции. Длина ключей может достигать 250 байт, а объём данных под одним ключом - 1 МБ.</p>
240
<p><strong>Memcached</strong> - высокопроизводительный сервис, работает быстро вне зависимости от количества хранимых данных. Быстрее, чем Redis. Можно сказать, что это хранилище "ключ - значение", поддерживающее атомарные операции. Длина ключей может достигать 250 байт, а объём данных под одним ключом - 1 МБ.</p>
241
<p><strong>Redis</strong>поддерживает большое количество типов данных. Он умеет периодически сохранять информацию на жёсткий диск и позволяет хранить до 512 МБ данных в значениях. Redis поддерживает master-slave-репликацию, и его можно использовать в качестве постоянного хранилища данных. Он однопоточный.</p>
241
<p><strong>Redis</strong>поддерживает большое количество типов данных. Он умеет периодически сохранять информацию на жёсткий диск и позволяет хранить до 512 МБ данных в значениях. Redis поддерживает master-slave-репликацию, и его можно использовать в качестве постоянного хранилища данных. Он однопоточный.</p>
242
<p>Возможно, выбор здесь будет не совсем очевиден, но для этого приложения Redis избыточен, так как данные нужно не хранить на постоянной основе, а только передавать между стадиями сверки. Поэтому архитектор выбирает Memcached.</p>
242
<p>Возможно, выбор здесь будет не совсем очевиден, но для этого приложения Redis избыточен, так как данные нужно не хранить на постоянной основе, а только передавать между стадиями сверки. Поэтому архитектор выбирает Memcached.</p>
243
<p>Следующий вопрос - очереди. Здесь тоже есть несколько вариантов -<a>Kafka</a>,<a>Gearman</a>и <a>RabbitMQ</a>.</p>
243
<p>Следующий вопрос - очереди. Здесь тоже есть несколько вариантов -<a>Kafka</a>,<a>Gearman</a>и <a>RabbitMQ</a>.</p>
244
<p>Предположим, что с Gearman в команде никто не работал и под него нужно писать клиент с нуля, а это займёт много времени - поэтому он отпадает.</p>
244
<p>Предположим, что с Gearman в команде никто не работал и под него нужно писать клиент с нуля, а это займёт много времени - поэтому он отпадает.</p>
245
<p>У Kafka большая пропускная способность в сравнении с RabbitMQ, и он легко масштабируется. RabbitMQ умеет в сложную маршрутизацию и поддержку различных протоколов - это его основные преимущества, но в нашем приложении они не нужны. Поэтому выбираем Kafka.</p>
245
<p>У Kafka большая пропускная способность в сравнении с RabbitMQ, и он легко масштабируется. RabbitMQ умеет в сложную маршрутизацию и поддержку различных протоколов - это его основные преимущества, но в нашем приложении они не нужны. Поэтому выбираем Kafka.</p>
246
<p>Остаётся два открытых архитектурных вопроса и уже ощутимо разросшаяся диаграмма продукта, которая теперь выглядит так:</p>
246
<p>Остаётся два открытых архитектурных вопроса и уже ощутимо разросшаяся диаграмма продукта, которая теперь выглядит так:</p>
247
Сущности размещены в привязке к архитектурным частям приложения<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>На схеме обновлены сущности, добавлены связи между админкой и DWH, указано, какие сущности хранятся и взаимодействуют с БД, размещены Kafka и Memcached.</p>
247
Сущности размещены в привязке к архитектурным частям приложения<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>На схеме обновлены сущности, добавлены связи между админкой и DWH, указано, какие сущности хранятся и взаимодействуют с БД, размещены Kafka и Memcached.</p>
248
<p>Необходимо решить вопросы настраиваемой обработки отчётов и работы с различными форматами данных, поступающих от вендоров. Напомним, что эти данные предоставили саппорты на первом этапе сбора информации.</p>
248
<p>Необходимо решить вопросы настраиваемой обработки отчётов и работы с различными форматами данных, поступающих от вендоров. Напомним, что эти данные предоставили саппорты на первом этапе сбора информации.</p>
249
<p>В поиске ответов помогут паттерны проектирования и ООП.</p>
249
<p>В поиске ответов помогут паттерны проектирования и ООП.</p>
250
<p>Первым делом предстоит решить вопрос с различными форматами и другими различиями между вендорами. При этом процесс сверки будет одинаковым почти для всех них и для большинства операций. Различаются лишь форматы данных и некоторые аспекты реализации интеграций с вендорами.</p>
250
<p>Первым делом предстоит решить вопрос с различными форматами и другими различиями между вендорами. При этом процесс сверки будет одинаковым почти для всех них и для большинства операций. Различаются лишь форматы данных и некоторые аспекты реализации интеграций с вендорами.</p>
251
<p>Поэтому можно выделить базовую и интеграционную части. Для интеграционной части потребуется оформить какой-то интерфейс, с которым будет работать базовая часть. А в ней будут расположены операции сверки DwhOperation и VendorOperation.</p>
251
<p>Поэтому можно выделить базовую и интеграционную части. Для интеграционной части потребуется оформить какой-то интерфейс, с которым будет работать базовая часть. А в ней будут расположены операции сверки DwhOperation и VendorOperation.</p>
252
<p>Давайте попробуем определить интерфейс для интеграции - ReconciliationInterface:</p>
252
<p>Давайте попробуем определить интерфейс для интеграции - ReconciliationInterface:</p>
253
<p>public function getVendorData(): VendorOperationCollection - метод предполагает, что интеграция с вендором вернёт коллекцию объектов VendorOperation. Он будет вызываться на стадии get_vendor_operations.</p>
253
<p>public function getVendorData(): VendorOperationCollection - метод предполагает, что интеграция с вендором вернёт коллекцию объектов VendorOperation. Он будет вызываться на стадии get_vendor_operations.</p>
254
<p>public function getVendorReconciliationKey(VendorOperation): string - этот метод позволит доставать ключ сопоставления из любого поля VendorOperation.</p>
254
<p>public function getVendorReconciliationKey(VendorOperation): string - этот метод позволит доставать ключ сопоставления из любого поля VendorOperation.</p>
255
<p>public function canOperationsBeMatched(DwhOperation, VendorOperation): bool - метод определяет, можем ли мы сравнивать операции, например, по типу, если они совпали по ключу сопоставления.</p>
255
<p>public function canOperationsBeMatched(DwhOperation, VendorOperation): bool - метод определяет, можем ли мы сравнивать операции, например, по типу, если они совпали по ключу сопоставления.</p>
256
<p>public function compareOperations(DwhOperation, VendorOperation): ReconciliationResult - метод, который будет сверять данные из двух операций по их свойствам.</p>
256
<p>public function compareOperations(DwhOperation, VendorOperation): ReconciliationResult - метод, который будет сверять данные из двух операций по их свойствам.</p>
257
<p>Такой интерфейс позволяет парсить отчёты в разных форматах и даже обращаться за данными в API. Кроме этого, можно использовать различные ключи сопоставления для операций и проводить дополнительные проверки для определения фактической возможности сверки двух операций.</p>
257
<p>Такой интерфейс позволяет парсить отчёты в разных форматах и даже обращаться за данными в API. Кроме этого, можно использовать различные ключи сопоставления для операций и проводить дополнительные проверки для определения фактической возможности сверки двух операций.</p>
258
<p>Отдельно стоит упомянуть о возможности сверять операции в разных интеграциях. Например, в одной сверке мы сверяем у операций сумму, номер кошелька и фамилию пользователя, а в другой - номер карты и валюту. Всё это реализуется за счёт архитектуры в одном контуре с подменной только части кода.</p>
258
<p>Отдельно стоит упомянуть о возможности сверять операции в разных интеграциях. Например, в одной сверке мы сверяем у операций сумму, номер кошелька и фамилию пользователя, а в другой - номер карты и валюту. Всё это реализуется за счёт архитектуры в одном контуре с подменной только части кода.</p>
259
<p>Посмотрим на схему с добавленным интерфейсом:</p>
259
<p>Посмотрим на схему с добавленным интерфейсом:</p>
260
<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Итак, на схеме появился ReconciliationInterface и одна новая стадия, которую архитектор забыл отобразить ранее - это reconciliation_by_interval. Забыть что-то добавить на диаграмму очень просто, поэтому полезно повторно проходить по ней, повторяя логику приложения.</p>
260
<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Итак, на схеме появился ReconciliationInterface и одна новая стадия, которую архитектор забыл отобразить ранее - это reconciliation_by_interval. Забыть что-то добавить на диаграмму очень просто, поэтому полезно повторно проходить по ней, повторяя логику приложения.</p>
261
<p>Остаётся один нерешённый вопрос - как разрешить проведение кастомизированных транзакционных сверок при условии необходимости сверки нескольких операций?</p>
261
<p>Остаётся один нерешённый вопрос - как разрешить проведение кастомизированных транзакционных сверок при условии необходимости сверки нескольких операций?</p>
262
<p>Тут нам поможет дополнительный интерфейс, который будет опционален для реализации, в отличие от ReconciliationInterface, под названием CustomReconciliationInterface. У него будет всего один метод:</p>
262
<p>Тут нам поможет дополнительный интерфейс, который будет опционален для реализации, в отличие от ReconciliationInterface, под названием CustomReconciliationInterface. У него будет всего один метод:</p>
263
<p>public function reconcileOperations(DwhOperations, VendorOperations): ReconciliationResultCollection. Этот метод позволит сверять те операции, которые имеют полностью кастомную функциональность сверки. В него будут передаваться оставшиеся несверенные операции вендора и DWH, а на выходе будет ожидаться коллекция объектов ReconciliationResult.</p>
263
<p>public function reconcileOperations(DwhOperations, VendorOperations): ReconciliationResultCollection. Этот метод позволит сверять те операции, которые имеют полностью кастомную функциональность сверки. В него будут передаваться оставшиеся несверенные операции вендора и DWH, а на выходе будет ожидаться коллекция объектов ReconciliationResult.</p>
264
<p>Теперь нужно определиться с местом его вызова. Лучше всего предусмотреть для этого отдельную стадию custom_reconciliation.</p>
264
<p>Теперь нужно определиться с местом его вызова. Лучше всего предусмотреть для этого отдельную стадию custom_reconciliation.</p>
265
<p>Обновлённая схема:</p>
265
<p>Обновлённая схема:</p>
266
<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Теперь схема завершена и отображает всю архитектуру приложения. Но нужно проверить исходный список задач, которые сформулировал архитектор.</p>
266
<em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Теперь схема завершена и отображает всю архитектуру приложения. Но нужно проверить исходный список задач, которые сформулировал архитектор.</p>
267
<p><strong>Необходимо настроить взаимосвязь с DWH посредством интеграции по API.</strong>Внутри приложения будет создан клиент или сервис для связи с DWH по API. Нюансы его реализации в этой статье указывать не будем, так как без конкретных параметров продукта и инфраструктуры это невозможно сделать.</p>
267
<p><strong>Необходимо настроить взаимосвязь с DWH посредством интеграции по API.</strong>Внутри приложения будет создан клиент или сервис для связи с DWH по API. Нюансы его реализации в этой статье указывать не будем, так как без конкретных параметров продукта и инфраструктуры это невозможно сделать.</p>
268
<p><strong>Необходимо уметь обрабатывать различные отчёты в различных форматах.</strong>Реализовано за счёт ReconciliationInterface.</p>
268
<p><strong>Необходимо уметь обрабатывать различные отчёты в различных форматах.</strong>Реализовано за счёт ReconciliationInterface.</p>
269
<p><strong>Сверки должны запускаться в разное время в течение дня.</strong>Реализовано за счёт ReconciliationStarter и ReconciliationCalendar.</p>
269
<p><strong>Сверки должны запускаться в разное время в течение дня.</strong>Реализовано за счёт ReconciliationStarter и ReconciliationCalendar.</p>
270
<p><strong>Расчётные нагрузки на систему на одну сверку от 1000 до 500 000 операций.</strong>Стоит провести нагрузочное тестирование, но в целом такие цифры не выглядят проблемой в текущей архитектуре.</p>
270
<p><strong>Расчётные нагрузки на систему на одну сверку от 1000 до 500 000 операций.</strong>Стоит провести нагрузочное тестирование, но в целом такие цифры не выглядят проблемой в текущей архитектуре.</p>
271
<p><strong>Количество сверок по текущим данным - до 40 в один день.</strong>Стоит провести нагрузочное тестирование, но это небольшие цифры, чтобы переживать из-за них.</p>
271
<p><strong>Количество сверок по текущим данным - до 40 в один день.</strong>Стоит провести нагрузочное тестирование, но это небольшие цифры, чтобы переживать из-за них.</p>
272
<p><strong>Обработка отчётов от управляющих компаний, которые не присылают их по выходным и праздничным дням.</strong>Для этого предусмотрен ReconciliationCalendar, который позволяет управлять днями сверки из админки или принудительно включать или выключать их в определённые дни.</p>
272
<p><strong>Обработка отчётов от управляющих компаний, которые не присылают их по выходным и праздничным дням.</strong>Для этого предусмотрен ReconciliationCalendar, который позволяет управлять днями сверки из админки или принудительно включать или выключать их в определённые дни.</p>
273
<p><strong>Обработка специальных финансовых операций, которые существуют у ряда управляющих компаний, требующих обработки вместе с другими операциями из одной транзакции.</strong>Для этого предусмотрен CustomReconciliationInterface.</p>
273
<p><strong>Обработка специальных финансовых операций, которые существуют у ряда управляющих компаний, требующих обработки вместе с другими операциями из одной транзакции.</strong>Для этого предусмотрен CustomReconciliationInterface.</p>
274
<p><strong>Обработка отчётов, которые поставляются посуточно с данными за предыдущий день.</strong>Это учтено в архитектуре, так как она строилась на основе этой информации.</p>
274
<p><strong>Обработка отчётов, которые поставляются посуточно с данными за предыдущий день.</strong>Это учтено в архитектуре, так как она строилась на основе этой информации.</p>
275
<p><strong>Учесть обработку данных в отчётах, которые формируются не строго посуточно в интервале с 00:00:00 до 23:59:59.</strong>Это учтено в сверке по интервалу даты и времени, который рассчитывается в процессе самой сверки, а не строго задан в конфигурации.</p>
275
<p><strong>Учесть обработку данных в отчётах, которые формируются не строго посуточно в интервале с 00:00:00 до 23:59:59.</strong>Это учтено в сверке по интервалу даты и времени, который рассчитывается в процессе самой сверки, а не строго задан в конфигурации.</p>
276
<p><strong>Обрабатывать данные от управляющих компаний, которые не присылают отчёты в выходные и праздничные дни.</strong>Отчёт в понедельник может содержать данные за несколько дней. Данный вариант обрабатывается процессом интервальной сверкой, так как интервал формируется в процессе самой сверки.</p>
276
<p><strong>Обрабатывать данные от управляющих компаний, которые не присылают отчёты в выходные и праздничные дни.</strong>Отчёт в понедельник может содержать данные за несколько дней. Данный вариант обрабатывается процессом интервальной сверкой, так как интервал формируется в процессе самой сверки.</p>
277
<p><strong>Обрабатывать данные от управляющих компаний, которые не присылают отчёт вовремя.</strong>Для этого в процессе сверки предусмотрены стадии, которые можно перезапускать при необходимости. Вариантов технической реализации тут довольно много, и это можно оставить на усмотрение разработчика.</p>
277
<p><strong>Обрабатывать данные от управляющих компаний, которые не присылают отчёт вовремя.</strong>Для этого в процессе сверки предусмотрены стадии, которые можно перезапускать при необходимости. Вариантов технической реализации тут довольно много, и это можно оставить на усмотрение разработчика.</p>
278
<p><strong>Автотестами должно быть покрыто не менее 98% кода.</strong>Поскольку в технологическом стеке есть Symfony, можно использовать отличный фреймворк для автотестов Codeception с подробной документацией. В нём также предусмотрены инструменты для замера процента покрытия с подсветкой не закрытого автотестами кода, что удобно для разработчиков.</p>
278
<p><strong>Автотестами должно быть покрыто не менее 98% кода.</strong>Поскольку в технологическом стеке есть Symfony, можно использовать отличный фреймворк для автотестов Codeception с подробной документацией. В нём также предусмотрены инструменты для замера процента покрытия с подсветкой не закрытого автотестами кода, что удобно для разработчиков.</p>
279
<p><strong>Создание системы мониторинга.</strong>В качестве инструментов мониторинга можно использовать<a>Grafana</a>или любой аналогичный инструмент, принятый внутри компании. Обычно этот вопрос уточняют у группы эксплуатации или администраторов.</p>
279
<p><strong>Создание системы мониторинга.</strong>В качестве инструментов мониторинга можно использовать<a>Grafana</a>или любой аналогичный инструмент, принятый внутри компании. Обычно этот вопрос уточняют у группы эксплуатации или администраторов.</p>
280
<p><strong>Создание системы логирования.</strong>Как и в любом фреймворке, в Symfony есть логгер, который можно использовать в разработке. Главное - определить ключевые места кода, где необходимо логирование, и добавить его туда. Для просмотра логов подойдёт<a>Kibana</a>или её аналоги.</p>
280
<p><strong>Создание системы логирования.</strong>Как и в любом фреймворке, в Symfony есть логгер, который можно использовать в разработке. Главное - определить ключевые места кода, где необходимо логирование, и добавить его туда. Для просмотра логов подойдёт<a>Kibana</a>или её аналоги.</p>
281
<p>Итак, мы рассмотрели пример создания архитектуры нового приложения с нуля. Прошли путь от идеи до готового концепта, который можно описать в документе, а затем на основе этого описания составить техническое задание и нарезать задачи.</p>
281
<p>Итак, мы рассмотрели пример создания архитектуры нового приложения с нуля. Прошли путь от идеи до готового концепта, который можно описать в документе, а затем на основе этого описания составить техническое задание и нарезать задачи.</p>
282
<p>В завершение хотел бы дать рекомендации начинающим архитекторам:</p>
282
<p>В завершение хотел бы дать рекомендации начинающим архитекторам:</p>
283
<p><strong>Не стесняйтесь спрашивать мнения коллег и не игнорируйте их советы.</strong>Обмен идеями позволяет по-новому взглянуть на логику работы приложения и не упустить важные детали на старте работы.</p>
283
<p><strong>Не стесняйтесь спрашивать мнения коллег и не игнорируйте их советы.</strong>Обмен идеями позволяет по-новому взглянуть на логику работы приложения и не упустить важные детали на старте работы.</p>
284
<p><strong>После завершения проектирования проводите презентацию архитектуры саппортам, разработчикам и другим коллегам, которые будут работать с приложением.</strong>Они могут задать важные вопросы, которые по какой-то причине не возникли на первых этапах работы.</p>
284
<p><strong>После завершения проектирования проводите презентацию архитектуры саппортам, разработчикам и другим коллегам, которые будут работать с приложением.</strong>Они могут задать важные вопросы, которые по какой-то причине не возникли на первых этапах работы.</p>
285
<p><strong>Детализируйте схему системы и подробно описывайте назначение каждого компонента.</strong>Если у нас есть класс, то пропишите его в деталях: как будет работать каждый метод, какие будут свойства и так далее. Это позволяет увидеть систему в целом и подготовить описание для технических заданий разработчикам.</p>
285
<p><strong>Детализируйте схему системы и подробно описывайте назначение каждого компонента.</strong>Если у нас есть класс, то пропишите его в деталях: как будет работать каждый метод, какие будут свойства и так далее. Это позволяет увидеть систему в целом и подготовить описание для технических заданий разработчикам.</p>
286
<p><strong>Согласуйте список используемого технологического стека с отделом информационной безопасности.</strong>Некоторые ваши решения могут противоречить внутренним правилам ИБ. Специалисты по информационной безопасности смогут предложить аналоги, разрешённые в компании.</p>
286
<p><strong>Согласуйте список используемого технологического стека с отделом информационной безопасности.</strong>Некоторые ваши решения могут противоречить внутренним правилам ИБ. Специалисты по информационной безопасности смогут предложить аналоги, разрешённые в компании.</p>
287
<p><strong>При сравнении технологий и выборе инструментов рассматривайте минимум три их разновидности, стараясь соблюдать объективность.</strong>Не стоит делать выбор только на основе привычек.</p>
287
<p><strong>При сравнении технологий и выборе инструментов рассматривайте минимум три их разновидности, стараясь соблюдать объективность.</strong>Не стоит делать выбор только на основе привычек.</p>
288
<p><strong>Старайтесь не проецировать удачный опыт предыдущих проектов на текущий, потому что он может быть нерелевантен в данной ситуации.</strong>Предыдущие решения можно рассмотреть, но не стоит их приоритизировать.</p>
288
<p><strong>Старайтесь не проецировать удачный опыт предыдущих проектов на текущий, потому что он может быть нерелевантен в данной ситуации.</strong>Предыдущие решения можно рассмотреть, но не стоит их приоритизировать.</p>
289
<p>Если хотите погрузиться в тему глубже, вот список ресурсов, с которых я рекомендую начать:</p>
289
<p>Если хотите погрузиться в тему глубже, вот список ресурсов, с которых я рекомендую начать:</p>
290
<ul><li><a>серия постов про паттерны проектирования</a>в моём блоге;</li>
290
<ul><li><a>серия постов про паттерны проектирования</a>в моём блоге;</li>
291
<li>"<a>Фундаментальный подход к программной архитектуре: паттерны, свойства, проверенные методы</a>" Марка Ричардса и Нила Форда;</li>
291
<li>"<a>Фундаментальный подход к программной архитектуре: паттерны, свойства, проверенные методы</a>" Марка Ричардса и Нила Форда;</li>
292
<li>"<a>Современный подход к программной архитектуре: сложные компромиссы</a>" Нила Форда и Марка Ричардса.</li>
292
<li>"<a>Современный подход к программной архитектуре: сложные компромиссы</a>" Нила Форда и Марка Ричардса.</li>
293
</ul><a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>
293
</ul><a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>