---
# System prepended metadata

title: Тестовое задание SkyEng

---

---
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час_
