--- title: '' disqus: hackmd --- # Тестовое задание SkyEng [TOC] ## Задание 1 *Есть N микросервисов, каждый хранит у себя часть данных. Например: данные о пользователе, оплаты пользователя, начисления и списания продуктов, аналитика мобильного приложения. Заказчик просит сделать endpoint, который вернет данные с возможностью фильтровать и сортировать по любым полям, при этом нужны данные из всех микросервисов. Дополнительно должна быть возможность пагинации. Какие технические решения возможны и как ты будешь выбирать подходящее?* ### Размышления Чтобы писать меньше букв, договоримся, что сервис-поставщик -- это микросервис, хранящий часть данных #### Фаза 0 (отрицание) Сначала было бы круто узнать какую конечную цель преследует наш заказчик, возможно и проектировать ничего не придётся или функциональные требования поменяются диаметрально.  #### Фаза 1 Дальше важно выяснить вопрос о том насколько часто будет требоваться описанный эндпоинт. Если на входе понятно, что это разовая акция или же наоборот ничего непонятно и полезность фичи нужно еще проверить, то я бы пошел по наименее трудозатратному пути и в качестве решения предложил бы организовать разовую выборку данных (тут, не хватает знаний об объеме выбираемых данных), хранящихся в сервисах-поставщиках в любое хранилище у которого есть UI (считайте, что можно взять любую реляционную строковую СУБД), в котором можно посортировать и пофильтровать. При выборе конечного хранилища не побрезговал бы даже гуглотаблицами, хотя там и нет пейджинга, но с другой стороны мы и объема данных не знаем. Может пейджинг это просто блажь, которая случайно затесалась в требования (шутка). Т.е. самый примитивный вариант реализации выглядел бы вот так: ```graphviz digraph graphname{ rankdir=LR; SS [label="Service-source"] SS2 [label="Service-source2"] Points[shape=none label="..."] SSN [label="Service-sourceN"] CSV [label="CSV"] CSV2 [label="CSV2"] Points2 [shape=none label="..."] CSVN [label="CSVN"] GD [label=" Google SpreadSheet "] CL [label="Client"] SS->CSV[label="Data"] SS2->CSV2[label="Data"] SSN->CSVN->GD[label="Data"] Points->Points2->GD[style=invis] CSV->GD[label="Data"] CSV2->GD[label="Data"] {rank=max;CL} CL->GD[dir=both] } ``` #### Фаза 2 В реальной жизни при принятии решения стараюсь опираться на команду, на технические компетенции её участников, на вектор желаемого развития участников команды. Самое шикарное когда удаётся совместить выполнение бизнес-потребности с желаемым вектором развития сотрудника(-ов). #### Фаза 3 (принятие) Если так случилось, что решение по каким-то причинам нужно принимать в "одну каску" и без контекста, то давайте примем еще ряд допущений: * нет ограничений по времени и бюджету * нет зависимых технологий, на которые мы должны опираться * нет ограничений по внешнему виду конечного сервиса * нет необходимости резервировать данные * нет потребности в мониторинге сервисов * нет потребности ограничивать доступ к эндпоинту * нет возможности управлять стеком технологий, используемых в сервисах-поставщиках (знаю, что в skyeng стек стабильный, при решении задачи фантазиурю) * мы имеем равнораспределенную нагрузку на сервис, без пиковых нагрузок Попытаемся додумать и сформулировать перечень требований к системе. Множество сервисов-поставщиков намекает на то, что: 1. Мы имеем дело с гетерогенным стеком технологий 2. Нельзя рассчитывать на синхронность при обмене данными 3. Количество сервисов-поставщиков и объем данных может меняться (обычно растёт) 4. Хочется минимизировать трудозатраты со стороны команд, разрабатывающих сервисы-поставщики 5. Исключить влияние на логику сервиса-поставщика Очертим функциональные требования к эндпоинту: 1. Данные представляются в виде грида 2. Данные можно фильтровать 3. Данные можно сортировать 4. Есть пейджинг Картинка отражающая финальное техническое решение: ```graphviz digraph graphname{ rankdir=LR; SS [label="Service-source"] SS2 [label="Service-source2"] Points[shape=none label="..."] SSN [label="Service-sourceN"] Broker [label=Kafka] A [label="Application"] DB [label="DB"] CL [label="Client"] {rank=max;CL} SS->Broker[label="Data"] SS2->Broker[label="Data"] SSN->Broker->DB->A[label="Data"] Points->Broker[style=invis] DB->Broker[label="Request"] A->DB[label="Request"] CL->A[dir=both] } ``` Ключевой функцией системы является сбор данных, для её реализации я решил использовать Apache Kafka, потому что с ней мы: - можем получать данные тогда, когда хотим - не зависим от стабильности работы сервисов-поставщиков - имеем возможность сделать не один, а несколько эндпоинтов с подобной функциональностью, не привязываясь к конкретным технологиям - можем добавлять новые сервисы-поставщики, опять же, не привязываясь к конкретным технологиям Выбранное архитектурное решение позволяет воспринимать эндпоинт как один лаконичный компонент большой системы и развивать его тоже можно постепенно по мере поступления проблем, в том числе экспериментируя с технологиями и инструментами. Поэтому над выбором СУБД и ЯП эндпоинта ломать голову не будем и возьмем первое приглянувшееся, например, postgresql, php и vue. Для пейджинга, сортировки, фильтрации на фронте будем использовать [https://bootstrap-vue.org/](https://bootstrap-vue.org/) #### Чекинг | Требование | Решение | Решено? | |:----------------------------------------------------------------------------------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |:------------------:| | Гетерогенность технологии сервисов-поставщиков | Готовые клиенты или REST API от Confluent Platform [https://www.confluent.io/product/confluent-platform/multi-language-development/](https://www.confluent.io/product/confluent-platform/multi-language-development/) | :heavy_check_mark: | | Асинхронное взаимодействие между сервисами-поставщиками и ендпоинтом | Apache Kafka в коробке даёт возможность асинхронного взаимодействия | :heavy_check_mark: | | Готовность к изменению количества сервисов-поставщиков и набора поставляемых данных | Если какой-то сервис-поставщик перестанет существовать, то на эндпоите просто не будет данных которые поставлялись этим сервисом. Если появится новый сервис-поставщик, то прикрутим два confluent-коннектора (producer и consumer) и организуем вывод данных на эндпоинте | :heavy_check_mark: | | Минимизация трудозатрат команд сервисов-поставщиков | Потребуется только доступ на чтение (и чуть-чуть на запись) в БД и краткая консультация о структуре хранения данных | :heavy_check_mark: | | Исключить влияние на логику сервиса-поставщика | Сервис-поставщика не меняем | :heavy_check_mark: | | Данные представляются в виде грида | bootstrap-vue | :heavy_check_mark: | | Данные можно фильтровать | bootstrap-vue | :heavy_check_mark: | | Данные можно сортировать | bootstrap-vue | :heavy_check_mark: | | Пейджинг | bootstrap-vue | :heavy_check_mark: | _Портрачено времени: 6 часов_ ## Задание 2 _Ты пришел в команду как тимлид. Разработчики жалуются: легаси, говнокод, много багов. Двое разработчиков предлагают рефакторинг, которым никто давно не занимался. Другие двое — переписать всё с нуля. Что ты будешь делать?_ ### Размышления Белые пятна в контексте: 1. состояние бизнеса: Активный рост/стабильность/кризис/? 2. потребности бизнеса? 3. критичность сервиса для бизнеса? 4. фактический уровень разработчиков? 5. степень погруженности разработчиков в предметный домен и код? 6. длительность работы с текущей кодовой базой каждого разработчика? 7. документация? 8. и прочее Постараюсь придерживаться следующего алгоритма действий: #### 1. Анализ 1. Выслушаю каждого тет-а-тет, позадаю вопросы, уточняющие мотивацию каждого разработчика и уровень решимости переходить к действиям 2. Узнаю планы и потребности бизнеса 3. Узнаю планы в IT-управлении компании: общий вектор развития, желание внедрению массовых IT-решений 4. Соберу общую встречу(-и) на которой попробуем вместе с командой зафиксировать больные точки и плюсы/минусы вариантов решения. На встрече займу роль фасилитатора 5. Проанализирую кодовую базы и архитектурные решения 6. Предыдущие шаги кроме информации должны дать время, чтобы успеть посмотреть за реальной работой по задачам, пособирать статистику решения задач: ttm, попадание в оценку, попадание в требования. Если времени не хватит, то возьму искусственную паузу в принятии решения. #### 2. Принятие решения Вот тут могут быть самые разные решения: от "остановить выпуск фич и переписать всё с нуля" до "оставить всё как есть и даже не рефакторить". Решение будем принимать исходя из данных полученных в результате анализа, т.е. оглядываясь на бизнес, роадмап развития разработчиков, состояние продукта. Скорее всего остановимся на каком-то промежуточном варианте при котором мы и тех.долг сокращаем и бизнес-фичи пилим. Что важно: 1. Принимать решение и отвечать за него будем внутри команды 2. Расскажем бизнесу о принятом решении 3. Общую цель, принципы её достижения и роадмап максимально визуализируем и для себя, и для бизнеса 4. Разложим работу на микрозадачи 5. По возможности решение бизнес-задач совместим с повышением качества 6. Будем измерять профит от каждого действия например, в виде берндаунчарта 7. Есть вероятность, что для сняти боли потребуется изменить процесс или ввести новые роли в команду _Затрачено времени: 1час_ ## Задание 3 _Продакт приходит к тебе с огромной задачей: сделать собственное решение видеосвязи на платформе обучения, просит оценить её. Как будешь оценивать?_ ### Размышления Размышления буду строить, опираясь на факт, что в компании уже есть общий движок для видеосвязи - [https://habr.com/ru/company/skyeng/blog/446444/](https://habr.com/ru/company/skyeng/blog/446444/) Прежде чем оценивать узнаю о причинах, по которым продакту нужно своё решение. Предполагаю, что результат диалога будет таким: 1. делать своё решение нелесобразно 2. сформированы перечень требований в команду видеосвязи 3. вместе с продактом откурируем реализацию требований командой видеосвязи О варианте когда продакт переубедил могу поразмышлять устно. _Затрачено времени: 1час_