Про карті Мегафона — технічні подробиці

В попередніх постах ми вже обговорювали банківську карту МегаФона як фінансовий продукт і розповідали про її можливостях для кінцевого споживача. Але, безумовно, за таким проектом стоїть величезна робота, яку виконала команда професіоналів. В цей раз ми детальніше розповімо саме про технічні особливості реалізації цього проекту і про пристрої програмного забезпечення.



Враховуючи масштаб проекту, описати всі тонкощі в рамках одного поста не вийде, тому ми почнемо з розповіді про бэкенде системи ДБО (дистанційного банківського обслуговування). Завдання бекенду — забезпечити робочу зв'язку всіх спеціалізованих систем у рамках єдиної логіки, а також функціонування великої кількості фонових процесів. А найголовніше — зручний і функціональний особистий кабінет для користувачів.

Технічним партнером проекту карти Мегафон вибрав компанію TYME. Весь час роботи фахівці двох компаній працювали в тісній зв'язці з постачальниками банківського ПЗ, білінгу, платіжними системами та іншими постачальниками, збираючи розрізнені функціональні шматочки мозаїки майбутнього проекту в єдине ціле.

«У нас були стислі терміни і великий обсяг роботи. Не було зайвих днів на довгі обговорення і права на помилку при виборі технології і підходів. Здорово, що нам разом з компанією TYME вдалося реалізувати складний і інноваційний проект.»
Ян Кухальский, Генеральний директор МегаЛабс
У 2013 стартував проект «Термінали», і з цього часу ми постійно вдосконалювали рішення, інтегруючи його зі своїми сервісами і новими провайдерами послуг і додаючи нові функції для клієнтів.

У TYME досить великий досвід роботи в фінтех-галузі, вони успішно подолали всі труднощі і ми разом з технологічними партнерами успішно запустили карту МегаФона. Далі на сторінках блогу МегаФона даємо слово команді TYME, нехай хлопці самі розкажуть про деталі своєї частини проекту.

Деталі великого проекту
Після реалізації кожного масштабного проекту ми озираємося назад, щоб оцінити виконану роботу. У вельми стислі строки нам вдалося запустити вкрай складну систему, яка знаходиться в самому серці фінансового продукту федерального масштабу.

Трохи цифр для прикладу:

  • 18 зовнішніх систем для інтеграції
  • 600 бізнес-процесів були реалізовані в рамка проекту
  • 770 сторінок технічної документації
  • 2500 сценаріїв для автотестів
  • 15000 людино-годин розробки
Оцінити істинний обсяг завдань можна тільки тоді, коли розробка проекту закінчується. Обсяг завдань в ході роботи постійно збільшувався. Якщо дивитися на це зараз, то стає навіть трохи страшно — як ми в принципі могли підписатися на такий обсяг в такі терміни.



Листопад 2015-го. Проект — на стадії концепції. У перекладі на людський — у нас є лише чітко визначена дата запуску і приблизний ТЗ від бізнесу.

Відсікаємо мармур


Можливість вивчити замовника і не діставати його постійними питаннями у нас з'явилася завдяки правильно побудованим відносин і декількох років спільної роботи.

Ось деякі принципи, дотримання яких нам дуже допомогло:

  • Працювати, виходячи з поточного стану вимог. Потрібно шукати конкретні завдання, за які вже можна взятися прямо зараз, замість того, щоб займатися скрупульозної деталізацією.

  • Застосовувати декомпозицію. Потрібно розподіляти роботи і вести проектування та розробку незалежно.

  • Використовувати готові джерела. Одна з наших завдань – інтеграція з вже готовими системами, які на момент початку робіт вже частково були запущені. Це прозвучить банально, але те, що дозволило нам спростити інтеграцію — це вдумливе вивчення документації по функціонуючих систем і спільна фіксація принципів роботи на ранніх етапах проекту.

  • Виконувати лідируючу роль в управлінні. Заставу успіх проекту — це ініціатива розробника у процесі формалізації вимог. Тобто працювати треба завжди на випередження, шукати можливість просунутися вперед по іншим частинам плану, якщо якісь інші провисають.
Само собою, при такому підході неминуче виникає ризик для розробника — адже ресурси на аналітику доводиться витрачати досить істотні, і за власною ініціативою. Підходить цей шлях в тих проектах, в яких ви повністю впевнені у своїх взаєминах із замовником, і якщо ви добре орієнтуєтеся в самій галузі.

Agile і довгострокове планування
Про достоїнства Agile-методології сказано вже багато. Не будемо повторюватися і сконцентруємося на тих моментах, які зазвичай замовнику найважче прийняти.

  • Немає жорстких термінів закінчення великого проекту
  • Витрати на великий проект можуть зрости при його опрацюванні
  • Непередбачувані межі проекту, тобто скоуп робіт завжди буде відносним, а спроба його фіналізувати лише призведе до сильно відкладеного старту.
Так як ми працювали по SCRUM, то проблема була стандартною – замовнику потрібен був «водоспадний» план проекту на найближчий рік. А деталізація проекту була готова лише на кілька найближчих спринтів, за які команда взяла на себе зобов'язання виконати ці завдання.

Часто можна побачитинаступну рекомендацію: якщо ви хочете отримати довгостроковий план, працюючи з Agile, заведіть у Project кожен спринт або ітерацію як завдання. У результаті на виході буде приблизно наступна картина:



Рекомендація настільки загальна, що у нас не прижилася. Цей варіант плану не показує віхи продукту, значимі для замовника, і не може бути повноцінно використано для обговорення довгострокового графіка проекту.

Срібну кулю в 1986-му придумав Баррі Боем, американський військовий. Його ідея — спіральна модель розробки. Багато айтішники вже знають, що це, але на практиці все одно дуже часто спостерігаються крайнощі — або Agile без довготривалих планів, або водоспад з термінами та бюджетами, які постійно змінюються.

Артемій Лебедєв в «Ководстве» непогано висловився на цей рахунок.

Завдяки спіральної моделі ми вирішили відразу два завдання:

  • підтримували актуальний довгостроковий план, зрозумілий замовнику
  • видавали в розробку завдання ітеративне, не перетворюючи при цьому SCRUM водоспад.
Проектна робота будувалася так:

  • Итеративная деталізація вимог. Документ, який описував вимоги по кожному з модулів системи, мав свою внутрішню структуру, коли складові її компоненти можуть перебувати в різному ступені готовності. На кожній з ітерацій деталізація вимог збільшувалася, даючи можливість взяти в розробку чергової обсяг завдань.
  • Еволюція робочих продуктів. На кожній ітерації розробки ми переглядали весь стек робочих продуктів на повну глибину у відповідності з новими реаліями вимог і фідбеком на прототипи. Це змушувало нас іноді переробляти архітектуру продукту. Приміром, на старті проекту планувалося, що всі процеси будуть забезпечуватися в рамках 40 микросервисов, і в ході деталізації архітектури їх кількість було скорочено до 20.Так еволюціонували уявлення про те, яким чином необхідно декомпозировать бізнес-логіку за сервісів. В результаті це дало дуже велика перевага — ми постійно мали можливість отримувати фідбек про поточної реалізації архітектури, і практично не накопичували технічний борг.
  • Регулярне перестроювання плану. Довгостроковий план проекту також був «живим», виходячи з актуальних вимог, інформації про графік розробки зовнішніх систем та інших ввідних. Ми не ставилися до плану як до константи, закріпленої на старті проекту, для нас це був «маршрут», який повинен привести з тієї точки, де ми знаходимося, до кінцевої мети. Відповідно, якщо ситуація навколо змінюється (а відбувається це регулярно), уточнюється і план.
  • Орієнтованість на ранній результат. Ми постійно працювали над тим, щоб максимально рано взяти завдання на розробку, і як можна швидше видати результат для приймання і тестування. При цьому ми намагалися розбивати залежності, які заважали нам це зробити — якщо не готовий зовнішній сервіс, ми не чекаємо його реалізації, а пишемо «заглушку»; якщо існує невизначеність з якоїсь частини завдання, намагаємося декомпозировать її ще сильніше і виконати роботи по тим складовим, де визначеність є. Часто команди розробки не йдуть на подібні витрати, побоюючись зробити зайву роботу, і часто ці побоювання обгрунтовані. В цей раз ми зробили ставку на швидкість.
  • Розробка по SCRUM. Ми докладали максимальних зусиль для того, щоб ізолювати від розробників невизначеностей у проекті, не порушуючи звичний ритм SCRUM. Управління проектом було побудовано таким чином, що в кожний момент часу був «буфер» зрозумілих команді завдань як мінімум на один спринт вперед. Це дозволило не втрачати темп протягом усього періоду активної розробки.
У результаті ми прийшли до такого маппингу завдань між планом в MS Project для замовника і Jira для команди розробки



За саме управління потоком робіт відповідала Jira (але це міг би бути будь-який зручний для Agile продукт), а план в MS Project був потрібен для контролю глобального статусу робіт і візуалізації для замовника.

Макроефект від микросервисов
Проект перетворився на купу проектів, які були дуже пов'язані між собою.
Так як ми ще спочатку вибрали підхід, що забезпечує таке дроблення — ми могли це собі дозволити.

Тренд микросервисов існує в світі розробки вже досить давно. Величезна кількістьобговорень на цю тему відбуваються на профільних конференціях. Хтось принципово заперечує користь від такої побудови систем, є і ті хто зайняв протилежну позицію і переводить всі свої складні системи на микросервисную архітектуру.

Микросервисная архітектура — це підхід до розробки, при якому замість створення одного великого програми, може бути, розділеного на шари (GUI, Бізнес-логіка, БД), створюється безліч невеликих, ізольованих один від одного компонент, які називаються микросервисами. Не вдаючись у теоретичні деталі, які можна досить легкознайти на Хабре, хотілося б зупинитися на тому, як опинився даний підхід корисний у нашому проекті.

Ось головні плюси такого підходу (на наш погляд):

  1. Кожен сервіс вирішує конкретний набір завдань, у нього визначений API, за яким можна звертатися до сервісу. Ми відмінно ізолюємо відповідальність в межах одного сервісу.

  2. Один микросервис, при бажанні, можна легко замінити новою версією, або швидко провести безпечний рефакторинг.

  3. Горизонтальне масштабування микросервиса при наявності складнощів з швидкодією. Це killer-feature для систем, які повинні працювати в режимі 24*7. Масштабування завжди йде разом з моніторингом швидкодії кожного сервісу, ми збираємо цю статистику і приймаємо рішення про запуск додаткових инстансов.

  4. Особливості корпоративних мереж такі, що по ІБ ми зобов'язані працювати в закритому контурі, але при цьому частина нашої платформи має доступ в інтернет, інші сервіси ізольовані і працюють з десятком зовнішніх систем у межах окремих підмереж. Ми виділили сегменти, які працюють у публічному інтернеті, внутрішні сервіси та інтеграційні сервіси, які знаходяться в спеціальній зоні з максимально закритим доступом. У разі моноліту, довелося б поєднувати на одному сервері кілька мереж, що не завжди подобається співробітникам забезпечує ІБ.
Само собою, не вдалося уникнути деяких труднощів:

  1. найскладніше рішення — про кордони микросервиса. Потрібно безпомилково відповісти на питання — який з існуючих микросервисов повинен виконувати цю задачу? На старті нам доводилося дублювати деякі рішення в декількох микросервисах, щоб зберегти їх ізольованість. Так, для розробника це трохи незвична ситуація, так як переиспользование коду — основне завдання.

  2. Кардинально інший підхід до оновлення нашого застосування. Без автоматизації цього процесу для адміністратора багаторазово ускладнюється, так як йому довелося б у вікно обслуговування виконати у декілька разів більша кількість операцій, щоб доставити оновлення в промислову середу.
Поділ системи на набір микросервисов + невелика команда + розробка по SCRUM: ось рецепт, який допоміг нам знизити рівень залежностей і максимально ефективно використовувати всі наші можливості та компетенції, вести розробку одночасно по декількох напрямках одночасно, мінімізуючи вплив кожного сервісу на інші частини системи.

Бути в центрі подій
Наша система не лише забезпечує бізнес-логіку подання даних банку для клієнта, це ще й інтеграційна шина, яка об'єднує front-end і всі беруть участь зовнішні системи.

Коли відмовляє наш бекенд — це автоматично означає, що користувач бачить збій. Коли відмовляє будь-яка інша система — у нас є можливість пом'якшити проблему і зберегти працездатність більшої частини функцій.

Це означає, що наша система повинна володіти експлуатаційними характеристиками, що перевищують ці показники будь-суміжної з нами платформи:

  • Кращий uptime
  • Найбільший запас по продуктивності
  • Краща стійкість по відношенню до відмов і збоїв
Ми від початку розуміли, що наша система стане головним вузлом, з якого буде починатися діагностика інцидентів, і ми повинні володіти вичерпною інформацією для будь-яких технічних розслідувань.

Ці вступні дані визначили додаткові умови для розробки:

  • Швидка доставка оновлення
  • Максимальну якість роботи кожного сервісу
  • Вичерпне наскрізне лігування
Оновити за 90 секунд
Коли працюєш з платформою, побудованої на микросервисах, важливо розуміти:

  • Оновлення потрібно максимально автоматизувати. Пора забути про ручне оновлення і максимально усунути людський фактор.

  • Величезний плюс микросервисов — децентралізованого. Ми запланували, що наші системи не повинні мати єдиної точки збою, щоб забезпечити максимальний аптайм.

При цьому ми не могли дозволити собі вводити якісь технологічні вікна на оновлення — будь-які, навіть невеликі простої системи в нашому випадку вкрай небажані.

Об'єднавши зусилля служби експлуатації і розробників, ми отримали рішення, яке володіє всіма потрібними властивостями:

  • Швидке оновлення, яке не вимагає «ручного» втручання розробників або адміністраторів. Ми налаштували авто-deploy, який забезпечив викачування «однією кнопкою» з урахуванням нашої специфіки. Підготовка збірки відбувається на ресурсах постачальника, а фактичне розгортання – в захищеному контурі замовника.
  • Під час оновлення сервіс не зупиняється. Так як кожен сервіс розгорнутий і працює мінімум на двох паралельних серверах, під час оновлення ми відключаємо від трафіку групу оновлюваних в поточний момент серверів і розподіляємо навантаження з інших екземплярів микросервисов. Після оновлення — перевіряємо smoke-тестом роботу нової версії сервісу і, якщо все пройшло успішно, оновлюємо наступну групу сервісів, переводячи трафік на вже оновлені сервіси. Так, поступово піднімаючи версії, ми отримуємо працюючу систему, без повної зупинки платформи.
  • Безперервний контроль деградації функціоналу. Завдяки покриттю автотестами всіх процедур, нам вдалося забезпечити можливість дуже швидко діагностувати відхилення перед деплоем на бій і усвідомлено прийняти рішення про проведення оновлення.
  • Швидка доставка функціоналу на бій. Завдяки всім раніше викладеним моментів, ми можемо дуже швидко викочувати в промислову експлуатацію виправлення і новий функціонал без шкоди для безперервності роботи.
Є ряд моментів, які можна поліпшити в процесі оновлення — наприклад, оновлення БД кожного з сервісів і забезпечення зворотної сумісності для роботи старої і нової версій сервісу одночасно.

Якщо це буде цікаво, ми з задоволенням випустимо окрему статтю про тих підходах, які ми застосовуємо у себе.

Філософія якості
Сервіс, який не повинен зупинятися, і при цьому динамічно розвивається, завжди перебуває між двох вогнів. У разі простою фінансові та репутаційні втрати будуть колосальними. А якщо згадати про надзвичайно стислі терміни і мінливі вимоги в процесі розробки, то ступінь складності продовжувала підвищуватися. Тому перед відділом якості встала амбітне завдання вибудувати тестування продукту таким чином, щоб воно було:

  • Швидким. У нас стислі терміни, короткі спринти і ми не хочемо чекати по декілька днів, поки тестери проведуть регрессионное тестування з чек-листів. В ідеалі – потрібно отримувати відповідь, який регрес зазнала система після кожної зміни коду.
  • Повним. Швидке здійснення тестів – не самоціль. Справжня мета – бути впевненими, що якщо тести пройшли успішно, то наша система готова до оновлення. А значить тести повинні бути не лише швидкими, але і повністю охоплювати функціонал продукту.
  • Гнучким. Швидкі і повні тести це прекрасно. Але якщо у замовника є нові вимоги, і зміни вимагають повного переписування тестів – це нікуди не годиться, тому що ми знову втрачаємо швидкість. Відповідно, тести повинні бути гнучкими до змін.
  • Дешевим. Ресурс тестувальника при великій швидкості розробки завжди буде виходити на перший план, якщо нам потрібно одержати високу якість. Тому все, що описано вище, повинно виконуватися існуючим кількістю фахівців з тестування. Ми тут лише підтвердили загальне співвідношення, коли на 3 розробників припадає 1 тестувальник.
В якості основи автотестів був обраний Python укупі з фреймворком py.test. Python — це швидкий (в плані розробки) і потужний мову, а py.test з його чудовою підсистемою фікстур та параметризації – гнучкий інструмент, що дозволяє широко переиспользовать код тестів.

Як агрегатора результатів: білд-сервер TeamCity з встановленими плагінами для інтерпретації результатів перевірки від py.test.

Самі тести пишуться максимально ізольовано, виконання кожного тесту ніяк не залежить від результату виконання інших тестів. Якщо тесту потрібно підключатися до БД системи і отримувати дані, значить, фікстура тіста повинна ці дані забезпечити до виконання тесту. Якщо на тест може вплинути значення, що лежить в кеші, значить інша фікстура повинна очистити кеш до виконання цього тесту. Так, це призвело до того, що багато часу знадобилося для розробки систематизованої сітки фікстур, але дуже швидко ці інвестиції стали окупатися швидкістю додавання нових тестів і, найголовніше, стабільністю їх результатів. Повний контроль над досліджуваною системою означає мінімум помилкових спрацьовувань тестів.

Інтеграція з сервером складання TeamCity дала можливість просто натиснути одну кнопку, щоб тести перевірили всі процеси платформи. При цьому ніяких приготувань робити не потрібно, а значить, це може зробити будь-який член команди. Звіт про тестування в докладному і наочному вигляді відображається на веб-інтерфейсі build-сервера.

Не пожаліли ми і про повну відмову від автоматизації тестів API через спеціалізовані рішення. Так, такі інструменти дають набір функціональності прямо з коробки. Але, по-перше, це недешево, по-друге, нам все одно потрібно більше можливостей.

Приміром, у певних тест-кейсах нашого API було потрібно отримувати СМС-код підтвердження на операцію, прокидати його в тести і спостерігати за поведінкою системи. Ось тут і виходить на перший план міць coded тестів, нехай їх розробляти і дорожче, ніж, наприклад, зібрати test-step'и в SoapUI.

У підсумку, зараз процес побудований таким чином, що Postman або той же SoapUI використовується тестерами тільки на етапі первинної перевірки. В кінцевому підсумку процес все одно повинен бути покритий автотестами на Python і впроваджений в загальний репозиторій. Це закон.

Жодна зміна функціоналу системи не обходиться у нас без тестування взагалі і без автотестів зокрема. Story просто не вважається виконаною, поки вона не покрита автотестами. Такий підхід вимагає високої самодисципліни від команди і продуктивності від тестувальників, але результат того вартий: якщо на білд-машині тести зелені, ми впевнені в якості своєї системи.

Зараз кількість функціональних тестів перевалило за 1300 і продовжує зростати. Виконання займає 25 хвилин.

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

One more thing
Документація — це аспект ІТ-проектів, який часто залишається в тіні історій про архітектуру, проектування і спілкування з замовником. Але це дуже важлива деталь, неувага до якої може ускладнити експлуатацію і розвиток навіть самої чудової, з точки зору внутрішньої організації, системи.

Нами був обраний підхід, при якому документація еволюціонує по ходу проходження циклу розробки:

  • Початкові вимоги від замовника відразу ж утворюють перші сторінки майбутньої документації

  • На етапі проектування вона доповнюється технічним описом планованого варіанти реалізації

  • Під час оцінки та планування вона доповнюється відповідями на питання розробників, якщо вони не були враховані під час проектування

  • Після того як вимоги потрапляють в розробку, вони декомпозируются задач, що кожна задача одержує посилання на розділ документації, відповідно до якої вона повинна робитися

  • При приймальному тестуванні реалізованої функції перевіряється не тільки її правильна робота, але і актуальність документації — часто при реалізації робляться уточнення і «спливають» моменти, які не були очевидні при проектуванні, всі невідповідності повертаються аналітику роботу

  • Після завершення приймання і тестування розроблена функція має набір тестів і підсумкову перевірену документацію.
Подібний підхід дав відразу кілька переваг:

  • Робота над документацією виявилася розподілена по процесу розробки, ми уникли ситуації, коли по завершенні потрібно виділити великий ресурс на документування
  • Документація по кожному модулю правилася в той момент, коли всі учасники максимально занурені в тему, і це дозволило зробити її максимально точної і не витрачати час на спроби згадати «а як же воно зроблено», які неминучі, якщо б ми винесли цей етап за рамки розробки
  • У разі якихось суперечок і сумнівів у нас завжди є можливість провести трасування, що включає вихідні вимоги, завдання на розробку і документацію
Найголовніше — ми в будь-який час можемо надати замовникові документацію як по поточній версії платформи, так і за планованим змінам, щоб забезпечити готовність з їх боку до оновлень.

Завдяки парі днів, які пішли на загальну редактуру і налаштування вивантаження з Confluence, вивантаження підсумкового документа зараз може бути виконана протягом години по всім компонентам системи.

Замість висновку
Ми постаралися описати загальний принцип роботи компаній і розкрити внутрішню кухню розробки.

Було б чудово почути від вас складні питання, які б ми могли використовувати як основу для нових статей!



Спасибі хлопцям за такий докладний розповідь! Це тільки перша частина технічної складової карти Мегафона, будуть ще історії. Залишайтеся на зв'язку.

Суміжні теми
Посилання
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.