Quantcast
Channel: Категорія [Статьи] — DOU
Viewing all 2421 articles
Browse latest View live

Досвід упровадження SAFe: як організувати процес та який результат

$
0
0

Усім привіт! Мене звуть Андрій, я PM у київському офісі компанії N-iX. У цій статті я поділюся передісторією й особливостями впровадження SAFe на нашому проекті, а також розкажу про отримані результати після запуску фреймворка. Щоб не порушувати політику конфіденційності, назву проекту, імена замовників і подібну інформацію змінено. Проект матиме назву ― Project X, а замовники ― «Корпорація». Поїхали!

Вхідні дані

Історія цього проекту для нас почалася зі взаємодії з клієнтом ― тоді ще невеликим стартапом. Ми працювали з вісьмома іншими крос-функціональними командами з різницею часових поясів до 9 годин (дві команди були з нашої компанії і шість ― з інших країн).

До впровадження SAFe всі команди працювали по Scrum в єдиному операційному ритмі: спринти починали й завершували того ж дня; реліз фіч робили раз на два тижні, і це завжди був Release to Production. Щотижня ми проводили міжкомандні синкапи — Scrum of Scrums, PO synchs, гільдії, інженерні tech talks, де ми ділилися думками, генерували ідеї, дискутували й упроваджували ініціативи для поліпшення робочих процесів. Суттєва різниця в часі й робота з представниками різних культур і захоплювала, і накладала свій відтінок «шарму» на щоденну роботу — реліз о 7-йранку або плановий deploy UAT для клієнтів о 12-йночі стали для нас звичними.

Уже тоді існував певний прототип каденції і синхронізації, проте це був швидше результат зусиль Scrum-майстрів, ніж усвідомлений крок до реалізації цих практик, а також Continuous Deployment and Release on Demand з боку архітекторів, development-менеджерів, продакт- і бізнес-оунерів.

Ключова мета й організаційні трансформації

Зміни розпочалися після того, як стартап викупила велика «Корпорація», і ми поступово ставали частиною великої бюрократичної організації.

У зв’язку з суттєвою різницею в часі центрів розробки, вартістю й обсягом загальних витрат на розробку, менеджери «Корпорації» ухвалили рішення реструктурувати віддалений центр розробки. Ставку зробили на європейські команди. У віддаленому часовому поясі залишилася тільки команда продакт-оунерів.

Плани про впровадження SAFe вперше почали обговорювати трохи більше як рік тому. Клієнт вірив, що це розв’язало б такі недоліки:

  1. Відсутність прогнозованих точок інспекції інкременту й синхронізації на рівні програми — ефективно побудовані Scrum-церемонії відпрацьовували себе лише на командному рівні, що не давало змоги впевнитися, що загальні результати ітерацій усіх команд можна безболісно інтегрувати.
  2. Недостатня прозорість артефактів — продуктові беклоги були недонаповнені й відображали бачення продукту лише на один спринт уперед. Решта була тільки в головах продакт-оунерів (командні продакт-оунери насправді відігравали роль бізнес- та функціональних з мінімальним правом ухвалення рішень щодо розвитку продукту), які не дуже переймалися генерацією ідей та пришвидшенням features Time-to-Market.
  3. Занедбаний стан архітектури — здоровенний, кількарічний моноліт, який усе більше й більше розростався, і, крім девелоперів, ніхто «з місцевих» архітекторів не був спроможний запропонувати розумні альтернативи оптимізації.
  4. Відсутність реалістичного довгострокового RoadMap — продукт рухався в невизначеному напрямку, класні фічі були заморожені в репозиторіях на стадії UAT, а наявний RoadMap не давав належного розуміння перспектив.

Адаптація Scrum-майстрів і продакт-оунерів до SAFe Mindset відбувалася за підтримки зустрічей з SPC (SAFe Program Consultant). Remote-команди з інших країн розпущено через майбутні невиправдані операційні витрати, пов’язані з логістикою й комунікацією для планування та реалізації програмного інкременту. А тому залишилися тільки наші N-iX-команди й команда продакт-оунерів. Деякий час ми розвивали Project X самостійно, однак подальший розвиток потребував залучення додаткових команд з одного часового поясу й географічної локації (для зменшення операційних і логістичних витрат і зручнішого планування делівері). Тому «Корпорація» ініціювала запуск другого центру розробки для створення й оптимізації єдиного продукту в портфоліо «Корпорації».

Підготовка

Ми активно почали готувати запуск SAFe на Project X:

  • Визначили зміну й розподіл ролей у проекті відповідно до SAFe-семантики. Продакт-оунери з боку клієнта дістали роль продакт-менеджерів, а київські продакт-оунери — більше автономії в ухваленні рішень щодо розвитку продукту. Для забезпечення більшої автономії виокремили додаткову роль продакт-менеджера в київському офісі.
  • Виникла нова ланка архітекторів: у проекті з’явився System, а техліди дістали змогу бути консультантами й частково виконувати обов’язки System Architect, які були їм делеговані.
  • Сформовано System Team, щоб виконувати пласт операційних завдань для ART (Agile Release Train) і забезпечувати підготовку релізів згідно з розкладом.
  • Головний продакт-менеджер дістав роль бізнес-оунера й майже повністю перемкнувся на верхньорівневу координацію продакт-менеджерів та оунерів на стратегічне планування програмного RoadMap для продукту на декілька PIs (program increment planning) уперед.
  • Продакт-менеджери нарешті сконцентрувалися на підготовці й оптимізації програмного RoadMap на найближчі 6-9 місяців,який за результатами цих зусиль став набагато прозорішим і доступнішим для всіх учасників проекту — візія продукту набула чітко окресленого напрямку.
  • Продакт-оунери, техліди й системні архітектори сфокусувалися на активній підготовці програмного й командного контенту на планування, що значно поліпшило справи командних і програмних беклогів: фічі, енейблери та сторі активно грумилися, оцінювалися й корегувалися заздалегідь перед плануванням програмного інкременту.
  • Виокремлено роль RTE (Release Train Engineer), головне завдання якої — координація ефективної роботи командного й програмного рівня для виконання обіцяного обсягу PI-цілей у визначений термін (2,5 місяця від початку PI) і з відповідною якістю (Built-in Quality), забезпечення якісної підготовки планування програмного інкременту, фасилітація мітингів програмного рівня — SoS, PO synchs тощо, а також розв’язання й усунення перешкод для delivery-продукту на рівні програми.
  • Запущено й виокремлено LeanUX-спільноту, яка відповідала за розробку й оптимізацію дизайну для потреб потяга (Agile Release Train).

Запуск пробного потяга

Ми підійшли до етапу запуску першого пробного потяга. Він мав тривати півтора місяця для того, щоб адаптуватися до оптимізованих особливостей роботи й вирівняти свій графік з іншими потягами корпорації. Для цього в усьому проекті запустили відповідні лінійки SAFe-тренінгів:

  • Leading SAFe — для менеджерів, лідерів, Scrum-майстрів і бізнес-оунерів для поліпшення розуміння специфіки лідерства й ментальної установки фреймворка, його принципів, фундаментів, загального бачення та мети.
  • SAFe for Teams — для команд, продакт-оунерів і Scrum-майстрів для поглиблення і систематизації знань щодо специфіки роботи командного рівня та завдань у структурі фреймворка.
  • SAFe PO/PM — для продакт-оунерів і менеджерів для формування бачення розвитку продукту та його оптимізації під час програмних інкрементів.

Перший день тренінгу. Виконання заданих вправ

Тренінги тривали два місяці. Сертифікація була обов’язкова для всіх, і всі учасники проекту успішно пройшли її у визначений термін. Ще два тижні використано для останніх приготувань: фінальні грумінги, перевірка архітекторів, підготовка системи репортингу, планування зустрічей, завершення поточних ітерації, підрахунок capacity на PI тощо.

Після сертифікації і приготувань ми провели перший пробний PI. Він проходив водночас у двох центрах розробки, куди прилетіли продакт- і девелопмент-менеджери з боку замовників. Захід був незвичний: постійні синкапи, крос-командні комунікації, усі переміщувались у трохи метушливому порядку; SPC з шаблонними фразами, що завдання з вищим WSJF мають бути першим, незважаючи на те, що їхній Business value нижчий від інших; SoS і PO synchs що півтори години, розбір і планування залежностей і програмних ризиків тощо. На першому плануванні я працював з двома командами — зі своєю Agile й System Teams. Ми перебували в одному часовому поясі, проте в різних фізичних локаціях, тому координувати таку роботу було нелегко.

Ми розпочали подію о 9-йранку за київським часом. Я дуже вдячний своїй Agile-команді за їхній професіоналізм, ініціативність і самоорганізацію. Протягом зустрічі я радше консультував їх, адже більшість часу мені потрібно було бути з девопсами. Якщо у вас дві команди в різних локаціях й одна з них нова (у моєму випадку DevOps), то краса опису PI planningбуде знівельована реальністю. О 18:00 розпочали загальне рев’ю прототипів планів команд і ROAM-розбір командних ризиків. Учасників команд і продакт-оунерів відпустили — залишилися тільки продакт-менеджери, представники менеджменту (engineering and development менеджери й RTE) і Scrum-майстри, яким треба було будувати процес роботи команд протягом другого дня. Через декілька годин дискусій був вироблений загальний план і стратегія на другий день.

Протягом другого дня вдалося розподілити час на дві команди рівномірно. Було вже значно менше мітингів, команди сфокусувалися на деталізації планів і створенні PI objectives з продакт-менеджерами. Так працювали до 16:30. Далі продакт-оунери презентували плани команд і цілі на цей програмний інкремент. Одразу після цього ми провели Program Confidence Vote, де продемонстрували рівень упевненості в успішності доставки загального інкременту в цьому програмному інкременті.

Друга частина першого дня PI планування. Очікуємо бізнес-рев’ю прототипів планів

Хочу зазначити, що досвід роботи конкретно з цією системною командою досить своєрідний, адже команда невелика за кількістю учасників (чотири людини), проте має двох продакт-оунерів. А це вже суперечить логіці підпорядкування речей і визначенню пріоритетів у роботі. Ми довго сперечалися з двома SPC щодо розподілу навантаження і процесу роботи команди, оскільки вона абсолютно операційна, і їй потрібен найгнучкіший фреймворк — Kanban. А ось тут і собака зарита, адже SAFe — а це ж, передусім, фреймворк, Карле! — зазначає, що Kanban-команди повинні працювати синхронно зі Scrum-командами в межах двотижневих ітерацій, прописувати цілі ітерацій і рахувати свою Velocity (швидкість) і Lead Time, щоб не порушувати принцип загальної каденції, commitment points і синхронізації.

Це круто — справді круто, і я тільки погоджуюся і підтримую ідеї постановки цілей на певний період і періодичний підрахунок результатів продуктивності команд, окрім ідеї обмеження Kanban-команд двотижневими межами — така пропозиція, на мою думку, дуже контроверсійна, бо суперечить природі операційних команд. Друге болюче питання — Capacity Allocation — скільки команда має витрачати зусиль, щоб підкидати дров у грубку паротяга, а скільки витрачати на будування містка між розробкою й операційною частиною (DevOps).

Дискутували довго... Домовилися, що 60% зусиль команда витрачатиме на потреби потяга, а 40% — займатиметься операційною роботою. Привіт, гнучкість! Забігаючи наперед, трохи заспокою, що в другому PI SPCs таки переглянули відсоток співвідношення навантажень.

Другий повноцінний PI

Другий PI вже був повноцінний — ми планували роботу на 2,5 місяця. З важливого: він уже був простіший, загальна комунікація виваженіша, планування команд швидше, програмних ризиків і залежностей більше, але вони були легші й зрозуміліші порівняно з першим плануванням. Представників з боку замовників було значно менше. Команди будували свою роботу розмірковано й ефективно. Постійний онлайн-зв’язок підтримували з чотирма локаціями з різних поясів — це було трохи незручно. Планування проводили за київським часом, розпочинаючи, як і попереднє, о 9-йранку.

Друга частина другого дня PI планування. Загальне голосування щодо впевненості поставки програмного інкременту

Результати

Що приніс і пофіксив SAFe своєю імплементацією в проекті:

  • Поліпшене загальне бачення стратегії розвитку — усі учасники проекту почали розуміти напрямок руху й завдання програми, заданий вектор став прозорим.
  • Вирівнювання процесу здачі продукту — ми співіснуємо в єдиному, зрозумілому для всіх ритмі, попри індивідуальні характеристики: швидкість команд і кількість учасників, прогнозованість їхньої роботи тощо, адже це можна й треба корегувати, проте — каденція одна, як і commitments and review points.
  • Поліпшення архітектури — тепер 15% своєї місткості команда виокремлює на оптимізацію архітектури й планує технічні енейблерив PI, а Innovation days дає змогу витрачати тиждень командам на підготовку, прототипування, хакатони й демонстрацію своїх доробків, які можуть бути взяті в роботу в наступному PI.
  • Прогнозованість руху потяга — прогрес прозорий, командні й програмна дошки доступні кожному учаснику проекту, а зустрічі з синхронізації та звіти допомагають координувати досягнення результатів.
  • Виникнення чітких програмних цілей — ми розуміємо, чого хочемо досягти конкретно за ці 2,5 місяця роботи, і на яких пріоритетах сфокусуватися.
  • Зменшення відтоку працівників у проекті й поліпшена мотивація команд — особливо в Innovation days. Я бачив, як «горять очі» в людей, коли вони проектували й презентували свої прототипи, як сподівалися на оцінки від продакт-менеджерів й архітекторів, які можуть піти в наступний PI як фічі.

Над чим варто задуматися

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

Значення SPC під час трансформації і в процесі розвитку проекту — у нас їх було два — один основний, а другий консультативний. У них була вся «повнота влади», але існувала велика небезпека, що наша робота могла перетворитися на двомісячний Fixed Scope Project — кожне завдання, додане або витягнуте зі спринта розглядали як «державну зраду». Побуду кепом і розвінчаю міф про фіксований Scope беклога спринта/ітерації, скоуп якого живе й еволюціонує зі спринтом/ітерацією, але за двох умовах:

  1. Цілі спринта/ітерації та обсяг завдань, підібраний під них, непорушні й можуть бути досягнуті після завершення спринта/ітерації.
  2. Пов’язані взаємні залежності й ризики мають бути знівельовані або усунуті перш ніж стирати або додавати скоуп робіт у спринт/ітерацію, бо саме це завдання розв’язують на PI planning — ось тільки це й лишається незмінним.

Найпростіший приклад: коли нове завдання не має залежностей на інші команди й збігається з цілями спринта або це незалежний Support defect / Exploration Enabler (Spike). Як наслідок подібні ситуації слід детально обґрунтувати, адже вони можуть перешкоджати «цілісності» програми! Якщо ситуації повторювалися, Scrum-майстер команди визнавався «зрадником» великих ідей :) й отримував корегувальний one-to-one з RTE.

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

Інтеграція RTE в проект — людину призначено на цю роль нещодавно, тому певні аспекти роботи ще варто поліпшувати. Наприклад:

  • на загальних ART-зустрічах під час дискусій взаємних залежностей і ризиків окремих команд витрачають час усіх учасників замість того, щоб зробити це окремою зустріччю з обмеженим, проте цільовим, оточенням;
  • невизначеність формату репортингу — досі незрозуміло, на які звіти сподівається центральний APMO і про що саме звітувати;
  • порядку денного й тривалості загальних зустрічей часто не дотримуються;
  • мету майбутніх поліпшень радше продиктовано SPCs, ніж критично усвідомлено й аргументовано Scrum-майстром програмного рівня (RTE).

Певен, що ситуацію поліпшуватимуть.

Висновки

Як говорив класик: «Ітоги подвєдьом...» SAFe — це не панацея від усіх неприємностей, пов’язаних з керуванням масштабними Agile-проектами, проте — це корисний інструмент у разі ефективного застосування. У нас у проекті була мета, яку SAFe, як інструментарій, мав виконати. Якщо говорити загалом — цей інструментарій ліпше використовувати за таких умов:

  1. Менеджмент проекту або C-Levelкомпанії чітко усвідомлює потребу в процесних змінах — використовувані методи або не приносять сподіваного результату — цінності, або некоректно імплементовані, або не дають змоги масштабуватися, або не приводять до досягнення стратегічних цілей.
  2. У проекті працює від 40 людей — SAFe радить діапазон від 50-125,проте можна стартувати навіть з 35-40 людьми.
  3. Це економічно рентабельно — SAFe — задоволення не з дешевих, його імплементація обійдеться в кругленьку суму.
  4. Поточний процес не виправдовує себе — напрацювання, ліпші практики або їхній мікс, адаптованих під конкретні завдання, більше не приносить результату й не виправдовує операційних витрат на оптимізацію.
  5. Ви працюєте на західного замовника або компанія орієнтована на західний ринок — технологічні й процесні інновації завжди починаються звідти. Тим паче, що у вітчизняний комерційний сектор SAFe повноцінно ввірветься лише в найближчі років п’ять, а в державний — через 20 за сприятливих умов (особистий прогноз).
  6. Проект масштабується — компанія планує розширюватися, і координація програмно-портфельного рівня є невіддільною частиною стратегії розвитку.

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


Як українські IT-компанії святкували Halloween 2019

$
0
0

Щорокуми збираємо моторошні фото українських IT-шників з Геловіну. Не зраджуємо традиції: дивіться і надихайтесь креативом колег!

Для зручності ми поділили компанії на групи за розміром:

Понад 1500 спеціалістів

Ciklum

Провели 9-йщорічний конкурс Ciklum Pumpkin Carving Contest!






DataArt

Весь тиждень тривав тематичний квіз на Skillotron, в день свята в офісах проходили Scavenger H(a)unt, Halloween trivia, запрошували гримерів та змагалися за кращий костюм. Кульмінацією святкування стала лекція від Оксани Півень (провідна наукова співробітниця в Інституті молекулярної біології та генетики НАН України, лектор INSCIENCE) «Bio-engineered soldier, chimera or still a human? Genetics of tomorrow».




Intellias





Luxoft

За багаторічною традицією Luxoft на Геловін провела для спеціалістів компанії оздоровчу ініціативу «День донора» у Києві та Одесі.

NIX

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

800...1500 спеціалістів

ELEKS

Елексівці у Львові, Києві, Тернополі та Івано-Франківську вирізали гарбузи, грали у настільні ігри, фотографувались, пригощались, та й загалом розважались на повну, тож Геловін пройшов страшенно весело :)

Lohika

N-iX

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

Sigma Software

У найжахітливішу ніч року в офісах Sigma Software самі відьми варили глінтвейн власноруч, Харлі Квін готувала поп-корн, а страшний Фредді Крюгер крутив фільми жахів! «Буууу!» — віталися колеги один з одним того дня. Ніхто не пішов з офісу не нажаханим)

3DLOOK

Організували атмосферну вечірку Mystic Chic в дусі Нового Орлеану початку 20-гостоліття. Усі охочі могли вивчити стародавні тексти API & SDK заклинань і побувати на справжньому спіритичному сеансі. Все це супроводжувалося шоу барменів і живою музикою саксофону.

200...800 спеціалістів

AB Soft

Підготували кілька сюрпризів для співробітників: частували солодощами у вигляді пальців відьми та чорною піцою. Усі охочі могли взяти на пам’ять стікери з надписами, що відображають основні «фобії» IT-спеціалістів. Відбувся конкурс на кращий костюм та на найоригінальніше прикрашений гарбуз.

AgileEngine

Влаштували конкурси на кращий костюм і найнеординарніший гарбуз, а також шведінг на стрічку «Сяйво» Стенлі Кубріка. Це був воістину мерзенний день!

AMC Bridge

31-огожовтня в компанії AMC Bridge у всіх п’яти локаціях відбулася вечірка на честь Геловіну. Колеги перевтілились у моторошних героїв та пригощались смаколиками у тематиці свята. Відбувся конкурс на кращий костюм та прикрашений кабінет. Було влаштовано перегляд класичних фільмів до дня Геловіну «Сімейка Аддамс» та «Страшні історії для розповіді у темряві» з попкорном.







Apriorit

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

Astound Commerce

В усіх п’яти офісах Astound Commerce на Halloween влаштували справжнє свято. З самого ранку гостей зустрічали смаколиками та гарячими напоями. Кожен бажаючий міг зробити світлини на згадку біля тематичних фотозон із інсталяціями. Увечері на всіх чекали захопливі квести, майстер-клас із приготування ласощів та спільний перегляд жахастиків. Було страшно весело!







Beetroot

Диміли відьомські коктейлі, грали квести за мотивами книг Стівена Кінга і горланили в караоке найжахливіші хіти «Руки Вверх».





Daxx

У найстрахітливіший день року усі офіси Daxx прикрашали тематичні декорації, а співробітники перевтілювались у моторошних героїв, пригощались смаколиками та фотографувались біля фотозон. У Києві провели конкурс з вирізання гарбузів і нагородили власника найлячнішого костюму. У Харкові грали в мафію, співали в караоке, вирізали гарбузи, а також ласували солодощами і кривавими шашликами. У Дніпрі відбулась вечірка «Horror movies»: у кінотеатрі всі охочі переглядали фільми жахів, куштували попкорн і хот-доги, а також брали участь в інтерактиві на знання культових кіногероїв.





Delphi Software

Влаштували святкове помаранчеве кавування.

Depositphotos

Вечірка Depositphotos Horror Party відбулась у фотостудії Lightfield Production з невеликою програмою, кінозалом з фільмами жахів, фотозоною з постерами й інсталяцією «Кладовища страхів».

Dev-Pro

Відзначили Halloween не тільки тематичними фотозонами і традиційними смаколиками, а й влаштували захоплюючий квест в рамках внутрішнього English Marathon.

Digicode

Ось так пройшов найжахливіший тиждень року для команди Digicode у київському та полтавському офісах. Вийшло страшно класно :)




Digitally Inspired

Цього року на Геловін офіси Digitally Inspired занурились в моторошну атмосферу! Такі умови що найкраще сприяли проведенню конкурсу на найжахливіше фото!




Govitall

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

Grid Dynamics

У харківському офісі компанії відбувся святковий квіз, де команди відповідали на тематичні питання та змагалися за звання страшноерудованої команди. У львівській локації на екрані крутили кінострічки на геловінську тематику 1990-хроків, також всі охочі брали участь у страшно веселих конкурсах. Для київських колег спеціаліст з карвингу провів майстер-клас із вирізання гарбузових ліхтариків Jack-o’-lantern.





G5 Entertainment

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

Innovecs

Компанія Innovecs об’єднала понад 200 співробітників київського та миколаївського офісів під час святкування Halloween. Усі охочі брали участь у конкурсі на кращий образ та святковий макіяж, змагалися в караоке батлах, а також виступали в Halloween талант-шоу. Було страшно весело!

LoopMe

Вдень робили грим, а ввечері була вечірка з тематичною їжею та напоями.

MGID

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

Perfectial

Працівники компанії з року в рік обожнюють виряджатися у дивакуваті, страшні і стильні костюми, тому вечірка наприкінці жовтня — must be. Цей рік не став винятком, ба більше, Гелоувін святкували в усіх офісах — Львові, Івано-Франківську та Києві.

Plarium

Цьогоріч у студії Plarium Kharkiv відійшли від традиційного святкування Геловіну й обрали темою заходу сучасне жахіття. Відсутність Wi-Fi або помилка під час збереження проекту — ось справжній страх, від якого сьогодні стигне кров.

P2H

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

Skelia

Skelia має особливу традицію: влаштовувати Newcomer’s Day — свято для новачків — під Halloween. Newcomer’s Day — це завжди Trick&Treat: круті конкурси, квести, моторошні герої і солодкі призи. І куди ж без глінтвейну та інших смаколиків?

SPD-Ukraine

Хтось любить перевтілюватись, хтось — ні, для SPD-Ukraine головне — повага до бажань команди. 45 кг гарбузів, 30 метрів марлі, 6 гримерів, 5 кг сухого льоду та 3 упаковки фетрових павуків. Так святкували Геловін команди SPD-Ukraine з черкаських та київского офісів.





Svitla Systems

Компанія влаштувала Halloween Party з костюмами, піцою та іграми в київському, львівському та харківському офісах. Також обрали переможців серед найкращих, страшно красивих образів. Святкування Halloween у Svitla Systems є традиційним не перший рік.

Ubisoft

Студії Ubisoft у Києві та Одесі розпочали святкування Halloween з тематичних солодощів. Цього дня в студіях був організований конкурс на найкреативніший костюм та традиційний Trick-or-treating між командами. Святкової атмосфери додавали декорації в офісі: павутиння, гірлянди, гарбузи та кульки.

81...200 спеціалістів

AB Games

В AB Games настільки люблять занурюватися в сеттінг Hidden City, що іноді стає страшно весело. Ну, або вселенськи страшно!

Agiliway

Майстер-клас з аквагриму, декорування гарбузів, конкурс на найкращий образ і смачна вечеря очікували на працівників компанії.

BAKOTECH

Тотально чорний — колір свята Геловін у BAKOTECH. Традиційно компанія влаштувала святкову атмосферу із кульками, тематичними прикрасами та смачними десертами в найнеочікуваніших варіаціях. Ввечері колектив розважився, змагаючись у настільні ігри, плейстейшн та обираючи переможця в кулінарному конкурсі «Страшенно смачно».

Bini Bambini

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

BOSS. Gaming solutions

Орім Scary party провели конкурс на найоригінальніший костюм! Уся компанія взяла участь в анонімному голосуванні для визначення трьох переможців, які отримають круті подарунки від компанії.

Cleveroad

Співробітники компанії Cleveroad у Дніпрі змагалися в створенні найзловіснішого «Ліхтаря Джека». Об’їдалися страшенно смачними солодощами та грали в покер «на гаманець» і в настолки «на життя». А Харківський офіс перевтілився у супер-героїв та відразу приступив до порятунку світу :)




CodeIT

Цього року геловінські костюми в CodeIT були дуже креативними. А офіс компанії перетворився на справжній будинок з привидами. Зробили безліч фото, вибрали найкращий костюм, пообідали з привидами, а в вечері дивилися страшне кіно з попкорном.

Codeminders

День почався з веселої фотосесії. На обід була піца та море позитивного спілкування у колі друзів. Ідеальним завершенням дня став похід у кінотеатр на прем’єру комедії жахів.

Codemotion

Провели святковий квест. Шукалі скарби в офісі, домовлялися про взаємовигідний обмін перлинами, після чого влаштували гучну вечірку.

EIS Group Ukraine

Співробітники EIS Group Ukraine створювали дуже страшні образи, куштували тематичні ласощі, грали у геловінську вікторину та дартс.

Global Message Services

Замість традиційного Halloween провели День мертвих (El Día de Muertos).

HYS Enterprise

Компанія дуже яскраво відзначила Halloween. Вечірка була доповнена декором, декількома фотозонами, гостем свята був майже справжній герой фільму «Воно» Пеннівайз, а також був тематичний квест.

iLogos Game Studios

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

IMREV

«Trick or treat?», — запитували справжні революціонери сфери інтернет-продажів компанії IMREV на своїй Halloween-party. Сміливі фантазії над образами й декором, магічне зілля й ласощі — все це по-особливому доповнило атмосферу свята.

Intego Group

Interkassa

Interkassa святкувала Halloween у атмосферному лофті. Був конкурс костюмів, марафон фільмів жаху, хоррор-ігри на PlayStation VR та справжній танцювальний шабаш.

Відзначили свій Геловін фотосесією у тематичних костюмах, декором офісів та святковим кенді-баром.

Maklai

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

Mobilunity

День почався пранком над співробітниками із гарбузовим монстром та прихованою камерою, а закінчився костюмованою Halloween Pizza Party, на якій за кращий хоррор костюм учасники отримали солодкі призи.

KeepSolid

Компанiя відсвяткувала Геловiн, провела голосування за найстрашніший костюм серед спiвробiтникiв i найкраще вирізаний гарбуз. Також працівники прослухали лекцію з косплею вiд Front-end-розробника, який колись займався цим професiйно, поки не потрапив в IT. I наостанок, зiркою перформансу став французский бульдог Леон, який, до речi, ласував яблука.

Rails Reactor

RubyGarage

Влаштували традиційну Геловінську вечірку з барменами, які готували коктейлі та розважали гостей. Також вирізали гарбузи та сходили на сімейку Аддамсів у кіно, тож День всіх святих пройшов яскраво.

Scalors

Компанія Scalors відсвяткувала Halloween-2019 грою в Мафію. А ще охочі розмалювали обличчя страшним аквагримом та фотографувалися біля тематичної фотозони.

SkySoft.tech

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

SSA Group

SSA Group провели Геловін у тісному колі колег та привидів. Смакували желейних черв’ячків, вирізали гарбузові «ліхтарі Джека» та проводили конкурс на кращий геловінський хенд-мейд.

UNIT

В офici UNIT влаштували вечірку зі страшенно смачники смаколиками. Зловісний і грайливий дизайн солодощів та гарний настрій відганяв нечисту силу весь день!

Waverley Software

Загримовані під мерців і в яскравих квітчастих костюмах команди Waverley провели справжні мексиканські вечірки у львівському та харківському офісах. Одночасно відбувся конкурс на найкреативніший автентичний костюм в стилі Дня Мертвих серед усіх колег Waverley Ukraine.




WorkNest Technologies

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

Vakoms

У цей моторошний день у офісі компанії Vakoms було страшенно весело, солодко і кольорово!

Yukon Software

Провели конкурс «Найкреативніший костюм» та методом голосування обрали трьох переможців. Учасники та не тільки мали змогу пригоститися домашнім пуншем та цукерками. Спойлер: переміг священик.

21-80спеціалістів

Adraba

Цього року відбулися командні ігри та квест. Необхідно було розв’язати головоломки, проявити кмітливість та пройти розважальний квест.

Appus

BeKey

У цей найстрашніший день року офіс компанії «BeKey» перетворився на шабаш. Тут були i скелети, і відьми, і гарбузи, і сімейка Адамсів. Доповнювали атмосферу тематичний декор офісу та геловінські страви.

Codica

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

Eska

Робили конкурс на найстрашніший, смішний і несподіваний костюм, розіграли призи за номінації і влаштували невелику вечірку з шотами зі шприців, страшно смачними закусками і димлячим пуншем.

Forbytes

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

Forma Pro

Співробітники компанії Forma Pro вирішили в цьому році відсвяткувати Геловін, прослухавши лекцію про основні психологічні механізми створення жахів в книгах, фільмах та іграх. Лекція була проілюстрована прикладами зі світового мистецтва.

Jelvix

Itera Research

Зібралися в прикрашеному офісі всією командою в тематичних костюмах, провели веселі конкурси з подарунками, вирізали багато гарбузів. Свято Гелоувін — магічний привід зібратися разом.

openGeeksLab

У компанії openGeeksLab влаштували вечірку у форматі «Smart-Quiz» на кшталт «Що? Де? Коли?» і провели конкурс на найкраще horror-перевтілення. Переможцем став Капітан Атаман, який отримав приз, такий же міцний, як і його булава.

OTAKOYI

SDH

SDH провела вечірку в стилі «horror». Протягом останнього тижня працівники компанії намагалися врятуватися від величезних павуків та привидів, що блукали офісом. На щастя, ніхто, окрім пекельних пирогів та відомського глінтвейну, не постраждав.

SE Ranking

Що буде, якщо під одним дахом зберуться герої казки про довгоносого дерев’яного хлопчика, трохи мертва наречена, поціновувачка шуб із далматинців, ельфійська принцеса, відважна поліцейська, неприборкана ідіанка, сила-силенна нечисті та сам Той-Кого-Не-Можна-Називати? Буде страшно весело і по-особливому атмосферно. А за кращий костюм в SE Ranking ще й подарунки роздають. Ну а щоб вистачило запалу танцювати до ночі, можна було поживитися піцою з вином або червоненьким коктейлем зі шприців і черев’ячками — тут уже кому що до смаку :)

Sparkybit

Присвятили 31 жовтня фоновим тематичним активностям: вранці — геловiнськi кекси, вдень — конкурс з вирізання гарбузів з призами для переможців, ввечері — посиденьки з піцою та пивом під мультфільми Тіма Бертона. Харківський офіс компанії відзначив Геловін п’ятничним пушем і закусками.

Synebo

Влаштували Halloween з червоно-красним дресскодом, тематичною фотозоною, а також провели конкурс на хендмейд-лiхтарик Джека. Команда, що зробила найкращий лiхтарик з гарбуза, виграла похiд до розважального закладу на власний вибiр.

Tateeda

Ховалися від нечесті, лякали колег і насолоджувалися запахом гарбуза — таким був Halloween в Tateeda.

TBWA\MOBILE

Харківський офіс TBWA\MOBILE у Геловін зустрічав своїх піратів смачним зіллям і солодощами.

TenantCloud

Цього Хелловіну втілили жахіття відчайдушних домогосподарок та орендарів квартир, і на одну ніч стали страхітливим сервісом.

Tranzzo

У Tranzzo найстрашнішу ніч року відсвяткували балом, на якому була купа всякої нечисті та Леон з Матильдою. Обрали найкращий костюм, провели марафон страшних фільмів та вбивчих танців (від яких ніхто не постраждав). Як то кажуть: були і tricks, і treats.

UKEESS Software House

Обидва офіси UKEESS Software House навіювали потрібну атмосферу свята Halloween павутиною, скелетами та іншою симпатичною нечистю. А співробітники чаклували над страхітливими гарбузами під час конкурсу, де головною винагородою були квитки на концерт гурту «Бумбокс». Завершенням святкування стали смачні кекси у вигляді людського мозку і шоколадні десерти з черв’ячками.

YouScan

Влаштували Horror Movie Night: запаслись попкорном і тематичними смаколиками, загримувались, вимкнули світло в офісі і разом дивились фільми жахів.


Якщо ви хочете додати свої фото в статтю, пишіть на maria@dou.ua.

«Живий» прогноз погоди, або Як використати генеративне мистецтво у вебі

$
0
0

У рубриці DOU Проекторвсі охочі можуть презентувати свій продукт (як стартап, так і ламповий pet-проект). Якщо вам є про що розповісти — запрошуємо взяти участь. Якщо ні — можливо, серія надихне на створення власного made in Ukraine продукту. Питання і заявки на участь надсилайте на editors@dou.ua.

Мене звуть Мар’яна, я випускниця програми Computer Science в УКУ. У цій статті я хотіла б розповісти про свій дипломний проект. Його суть у тому, щоб зробити веб-застосунок, який зображатиме реальні погодні умови на прикладі природного пейзажу, створеного за допомогою генеративного мистецтва. Ідея полягає в тому, щоб створити новий підхід до зображення погодних умов, що має спростити сприйняття інформації користувачем.

Що таке генеративне мистецтво

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

Усі добре знайомі з наявними прогнозами погоди, у яких зазвичай використовують іконки для передачі інформації. Це лаконічно й просто, однак іконка не може передати всі характеристики погоди, особливо динамічні (такі як вітер). Саме тому мені захотілося зробити своєрідне «живе вікно», яке показувало б погоду в русі.

Особливість створеного пейзажу також у тому, що він завжди унікальний, хоча водночас зберігає глобальне розміщення компонентів. Це зроблено завдяки генеративному підходу до створення елементів і, як на мене, додає елементам природнішого вигляду. Для реалізації проекту використовується JavaScript, а всі елементи намальовані в Canvas. Загалом робота над проектом тривала протягом весни — близько трьох місяців, де значну частину часу забирали експерименти з виглядом компонентів.

Пейзаж складається умовно з чотирьох компонентів: дерево, земля, небо, опади. З такими компонентами зручно зображати пору року й такі погодні умови: дощ/сніг, вітер, хмарність.

Дерево

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

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

Крона дерева неоднорідна, як куля, а складається з груп, наче кілька кульок. Це впливає на колір листочків, де одні більш затінені, а другі світліші. Для визначення цього кольору крона дерева ділиться на групи, де кожна група замальовується зліва направо в палітрі від найсвітліших до найтемніших кольорів і назад. Функція divide(start, finish, intervalsAmount, n)розділяє числовий проміжок між start та finish на задану кількість інтервалів intervalsAmount і визначає, в якому проміжку перебуває n.

const branchGroupDepth = 10;
const leavesGroupSize = 2 ** (branchGroupDepth-1);
let groupCounter = 0;

function generate(angle, depth, arr) {
 let leafColor = colors[divide(0, leavesGroupSize, colors.length, groupCounter)];
  arr.push({
   angle,
   branchArmLength: random(minBranchLenght, maxBranchLenght),
   color: leafColor
 });
 if (depth === branchGroupDepth) { groupCounter = 0; }
 if (depth === 0) { groupCounter++; }
 if (depth != 0) {
   if (depth > 1) {
     generate(angle - random(minAngle, maxAngle), depth - 1, arr);
     generate(angle + random(minAngle, maxAngle), depth - 1, arr);
   } else {
     generate(angle, depth - 1, arr);
   }
 }
}

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

windSideWayForce — прорахування напрямку гілки залежно від напрямку вітру.

bendabiityOfCurrentBranch — прорахування коефіцієнта сили нахилу гілки від вітру залежно від товщини гілки.

calcX(angle, r)/calcY(angle, r) — функції, що виконують r * cos(angle)/r * sin(angle)для того, щоб знайти координати точки закінчення гілки.

let branchCounter = 0;
const bendability = 2;
const leafBendability = 17;

function branch(x1, y1, arr, depth, windConfig) {
 if (depth != 0) {
   const xx = calcX(dir, depth * branchArmLength);
   const yy = calcY(dir, depth * branchArmLength);
   const windSideWayForce = windX * yy - windY * xx;
  const bendabiityOfCurrentBranch = (1 - (depth * 0.7) / (maxDepth * 0.7)) **        bendability;
   dir = angle + wind * bendabiityOfCurrentBranch * windSideWayForce;
   let x2 = x1 + calcX(dir, depth * branchArmLength);
   let y2 = y1 + calcY(dir, depth * branchArmLength);
   lines[depth].push([x1, y1, x2, y2]);
  
   if (depth > 1) {
     branch(x2, y2, arr, depth - 1, windConfig);
     branch(x2, y2, arr, depth - 1, windConfig);
   } else {
     branch(x2, y2, arr, depth - 1, windConfig);
   }
 } else {
   const leafAngle = angle + wind * windSideWayForce * leafBendability;
   leaves[color].push([x1, y1, leafAngle]);
 }
}

Малювання гілок відбувається простою lineTo()функцією в канвасі. Кожна гілочка — це проста лінія.

Кожен листочок намальований за допомогою двох кривих Безьє, а саме функцією bezierCurveTo() в канвасі. Кожна крива має три точки: початок (блакитна точка), кінець (блакитна точка) і контрольна точка (жовта). Саме контрольна точка формує вигин кривої.

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

Земля

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

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

function generate(number) {
 for (var i = 0; i < number; i++) {
   var y = random(fieldTopStart, h + fieldBottomDeviation);
   var x = random(0, w);
  var colorGroup = divide(fieldTopStart, h + fieldBottomDeviation  + 1,  fieldAreas, y);                                             
   var color = colors[colorGroup][random(0, colors[colorGroup].length)];
   var angle = random(-maxAngleDeviation, maxAngleDeviation);
   var speed = random(minSpeed, maxSpeed);
   dots.push([x, y, color, angle, speed]);
 }
 dots.sort();
}

Кожна травинка малюється за допомогою двох кривих Безьє, як це було у випадку з листочками на дереві. Щоб змусити травинку реагувати на вітер, координати контрольних (жовтих) точок і координата кінчика травинки залежать від значення вітру.

Небо й опади

Найважливіші елементи неба — хмаринки та їхня кількість. Загалом хмаринки міняють свій розмір залежно від свого розміщення на небі. Саме небо поділене на умовні горизонтальні сектори, і що вище сектор, то більшого розміру в ньому хмаринки і то швидше вони рухаються вздовж неба.

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

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

Інші важливі елементи неба — опади, а саме дощ і сніг. Самі краплинки малюються доволі просто — коротенькою вертикальною лінією, товщина якої залежить від рясності дощу. Сніжинка ж малюється за допомогою градієнтного напівпрозорого кола. Особливістю руху сніжинок є те, що вони можуть суттєво відрізнятись за розміром, і більші мають більшу швидкість падіння. Завдяки цьому з’являється відчуття, що більші сніжинки розміщено ближче до користувача.

Результат

Для того, щоб оживити застосунок, у ньому використовуються справжні дані про погоду у Львові на цю мить з ресурсу OpenWeather. Дані опрацьовуються, а саме переводяться в зрозумілу для системи шкалу.

Трішки гри з кольорами для різних пір року, застосування реальної погоди — і рік крізь це «живе вікно» на відео матиме такий вигляд:

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

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

Дякую за увагу!

Тестирование Big Data: вызов принят

$
0
0

Всем привет! Меня зовут Дмитрий Собко, и я занимаюсь тестированием больше 7 лет. Начинал свою карьеру с должности Junior Manual QA на проекте по разработке Android-приложения. Также был Automation Lead команды, которая разрабатывает приложение big data на стеке GCP (Google Cloud Platform). И именно эти опытом хотел бы поделиться.

В статье рассмотрены особенности тестирования именно приложений big data, которое немного отличается от тестирования REST API, UI и тем более Android/iOS. В то же время, зная основные моменты, можно построить достойный процесс контроля качества даже таких, на первый взгляд, нетестируемых решений.

Что такое big data

I keep saying that the sexy job in the next 10 years
will be statisticians, and I’m not kidding.

Hal Varian, chief economist at Google

Big data — это понятие, о котором, наверное, слышали уже все. Google Trends показывает, что интерес к big data возник примерно в 2012 году и не стихает до сих пор.

Чтобы определиться, что же такое big data, используем Google и находим следующие объяснения:

  • это просто много данных (> 10 Тбайт);
  • это настолько большие таблицы, что их невозможно открыть и проанализировать в Excel;
  • это неструктурированные данные из разных источников, разного объема, которые показывают, как ведут себя наши кастомеры и т. д.

Мне больше всего нравится определение из Википедии:

Big data — это область, которая определяет способы анализа, систематического извлечения информации или, иными словами, имеет дело с набором данных, которые слишком большие или сложные для традиционных программных способов обработки.

Существует и так называемая 3V-теорема, раскрывающая суть термина big data с другой стороны.

Volume — объем данных. Он действительно большой. Обычно это больше 50 Тбайт и до бесконечности.

Velocity — данные регулярно обновляются, поэтому требуется их постоянная обработка (от batch processing, когда данные загружаются пакетами, например раз в сутки, до real time streaming, когда данные в реальном времени попадают на графики / в отчеты и даже влияют на системы принятия решений на основе ML).

Variety — разнообразные данные могут иметь абсолютно разные форматы, быть неструктурированными или структурированными частично (от CSV/Avro-файлов с четкой структурой до логов в потоке).

Путь в Cloud

Со временем хранить такие объемы данных на собственных или арендованных серверах становится все сложнее и дороже. И когда в 2006-мпоявился AWS (Amazon Web Services), лишь немногие догадывались, к каким глобальным инфраструктурным изменениям это приведет.

В 2019 году достаточно взглянуть на этот график:

В 2020-мпримерно половина всех серверов будет в клауде, и с этим необходимо считаться.

Одной из компаний, которая наиболее подробно описывала путь от собственной инфраструктуры к Google Cloud, является Spotify. В ее блогеподробно рассказывается, почему были выбраны те или иные решения. Рекомендую почитать всем, кто интересуется этой темой.

И немного о Cloud-провайдерах:

Каждое третье приложение в клауде приходится на AWS. Azure от Microsoft и Google Cloud Platform соответственно лидеры оставшегося сегмента. Сопоставив эти два графика, можно сделать вывод, что изучение Cloud-технологий в целом и AWS в частности для тех, кто пока далек от этого, в том числе для QA-инженеров, становится скорее необходимостью, чем возможным желанием.

Как вообще выглядит проект big data

Обычный проект big data выглядит (очень упрощенно) следующим образом:

  1. На вход приложения попадают разные данные из разных источников. Обычно таких источников два:
    • streaming (потоковые) данные — любая message queue (Kafka, Google PubSub, Amazon SNS и пр.);
    • batch (пакетные) данные — обычно CSV, TXT, Avro, JSON-файлы.
  2. Данные извлекаются и складываются в Staging-таблицы. На этом этапе также возможна дедубликация, отдельная обработка записей, которые мы не смогли распарсить, и т. д. По сути, это настоящие source-данные as is.
  3. Дальше данные из Staging-таблиц трансформируются, группируются, фильтруются, дополняются метаданными и попадают в DWH (Data Warehouse), или в так называемый Target layer. Эти данные уже структурированы (например, имеют одинаковый формат полей с датой), и таблицы также имеют структурные связи между собой. Подробнее можно почитать здесь. В случае Google Cloud Platform это может быть BigQuery. У Amazon это Redshift. Но также это может быть Oracle, PostgreSQL и т. д.
  4. На основе данных в DWH формируются аналитические отчеты / принимаются решения ML-системами.В самом простом случае на выходе у нас:
    • набор данных, на основе которых уже строится визуализация (Tableau, Power BI, Zoomdata и пр.);
    • отчеты в виде CSV-файлов, которые отправляются, например, на SFTP-сервер или на S3-бакет.

Пример data pipeline на Google Cloud Platform

На входе данные поступают в виде batch-файлов или потоков (stream).

С помощью фреймворка Cloud dataflow данные извлекаются, трансформируются, обрабатываются и загружаются в DWH. В данном примере в основе DWH лежит BigQuery.

На основе полученных данных строится аналитика Cloud Machine Learning, Data Studio, возможная визуализация (Third-Party Tools) и т. д. Также в данном примере для кеширования данных используется Cloud Bigtable.

А как это протестировать

Как видно, здесь нет в чистом виде ни back-end- (API), ни front-end-частей. То есть у нас есть:

  • входные данные, которые мы практически не можем проконтролировать;
  • data processing (программная часть, которая отвечает за ETL — extract, transform, load);
  • таблицы/файлы/визуализация на выходе.

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

Подходы к тестированию

Тестирование на моках/стабах

В этом случае мы проверяем корректность трансформаций, выгрузки на mocked-данных. Например, используем CSV с несколькими строками на входе. Отдельно проводим негативное тестирование (XML-файлс незакрытыми тегами и пр.). Таким образом, мы сможем покрыть практически весь функционал data flow, но при этом у нас не будет уверенности, что все корректно и правильно работает на проде (а это самое важное!).

Тестирование на реальных данных

В таком случае мы пишем тесты для реальных данных, только догадываясь, сколько их будет и какими они будут. Допустим, мы знаем, что все кастомеры из CSV Customers на входе из страны Ukraine должны попасть в staging-таблицу customers_stage с кодом страны UA, а уже оттуда — в таблицу super_customers в Target-слой. Соответственно, мы и пишем такие тесты, опираясь на те данные, которые к нам пришли реально, и отталкиваясь от них.

Микс двух подходов

Unit/Integration-тесты пишем с использованием mocks/stubs. Также пару функциональных (end-to-end) тестов пишем для проверки реальной ситуации на энвайронменте с реальными данными. По моему мнению, этот подход является самым оптимальным, поскольку позволяет получить уверенность, что все хорошо идет на проде. И при этом при разработке новых фич он позволяет с помощью Unit/Integration-тестов быстро убедиться, что нет регрессии и вся логика построена правильно. Кроме того, на проде, конечно же, должна работать система мониторинга со сбором разнообразных метрик и отправкой нотификаций/алертов и пр.

Виды тестирования

Основных видов тестирования два: нефункциональное и функциональное. Нефункциональное тестирование включает в себя тестирование производительности, безопасности, нагрузочное и пр. В этом разделе мы коснемся функционального тестирования, которое, в свою очередь, делится на четыре вида.

Metadata Testing

Проверяем метаданные собственно данных (длину, тип) и таблиц (дату изменения, дату создания, количество строк, индексы и пр.).

Data Validation Testing

Проверяем, корректно ли данные прошли все трансформации. В качестве примера можно использовать преобразование Unix-тайм-стампа к дате.

Completeness (Reconciliation) Testing

Проверяем, все ли source-данные корректно обработаны. (Данные, которые успешно распарсились, попали в staging-слой, а если нет, то в error-таблицы или просто записались в логи.)

Accuracy Testing

Проверяем корректность логики трансформаций таблиц по пути от staging до analytics-слоя. (Обычно это делается путем создания с помощью SQL соответствующих проверочных view.)

А как это все автоматизировать

Для Unit/Integration-тестов можно легко использовать JUnit/TestNG (в случае Java-кода). Для Scala и GCP интересной альтернативой может быть библиотека Scioот того же Spotify.

Для функциональных тестов в нашем случае оптимальной была связка Kotlin + Spring + Cucumber BDD.

С помощью BDD-подхода мы наиболее точно и лаконично описывали все манипуляции с данными в рамках тестов. И при этом тест-репортами пользовались также дата-аналитики.

Почему Kotlin? Как мне кажется, это сейчас один из самых интересных JVM-языков для использования в том числе в автотестах. Есть много фишек, отличающих его от Java в лучшую сторону. Для тестировщиков, знающих Java/Groovy, переход будет очень легким. Ну и по состоянию на 2019 год можно уже смело утверждать, что этот язык перерос большинство детских болезней и продолжает развиваться.

Spring использовали для Dependency injection и еще нескольких приятных особенностей.

Позитивные итоги

Big data — это та область, которая почти наверняка будет развиваться, и узкоспециализированные технологии будут быстро и активно совершенствоваться. Кроме того, все больше компаний/проектов, которые обходили этот аспект своей деятельности стороной, будут обращать на него внимание.

Тестирование приложения big data непривычно, ставит перед QA много вызовов, которые нужно принимать и можно уверенно решать. И вместе с тем это интересно.

Спасибо за внимание!

DOU Hobby: кікбоксинг – ефектне поєднання боксу і східних бойових мистецтв

$
0
0

[DOU Hobby — рубрика про нетехнічні проекти IT-фахівців: творчість, цікаві хобі та інші lifestyle-досягнення. Якщо вам є про що розповісти — пишіть на valentina@dou.ua]

Віталій Шквира — Sr. Project Manager в компанії SoftServe. Він вже три роки займається кікбоксингом. В інтерв’ю для DOU Віталій розповів, як він захопився цим видом єдиноборства, як минають тренування та чим отримані у спорті навички можуть виявитися корисними в роботі й у житті.

Люблю «бій із тінню», бо тут ніхто не дає здачі :)

— Віталію, що таке кікбоксинг? З чого почалося твоє захоплення?

Кікбоксинг — це вид контактних єдиноборств, який виник у США в 1966 році. Один з його засновників — японець Ноґуті Осаму. В кікбоксингу поєднуються техніка і правила боксу, але додаються удари ногами. Зазвичай кількість раундів у поєдинку менша, ніж у боксі — від 3 до 5 в залежності від версії або турніру. Проте кікбоксинг за рахунок ударів ногами та більшої кількості нокаутів вважається більш видовищним.

Тренуватись я почав три роки тому. Основна причина захоплення досить банальна — придбавши автівку, почав менше рухатись і, відповідно, втрачати форму. До того я активно займався спортом у студентські роки: грав у футбол і хокей на траві, з останнього навіть здобув звання кандидата в майстри спорту.

Чому саме кікбоксинг? Мені він здається одним з найбільш інтенсивних і ефектних єдиноборств. Мабуть, не останню роль зіграли фільми, якими всі хлопці мого віку захоплювались у дитинстві: «Кривавий спорт», «Подвійний удар», «Уокер — техаський рейнджер». До речі, наші відомі на весь світ боксери Віталій і Володимир Клички починали саме з кікбоксингу.

— Чи пам’ятаєш, якими були перші тренування? Що найбільше вразило? Що здавалось найбільш складним?

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

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

Найскладнішою частиною тренування, як не дивно, була розминка, яка тривала приблизно 40 хвилин. Ти маєш бути добре розігрітий, щоб розтяжки і решта заняття минули ефективно і без травм. Спочатку вони здавались настільки важкими, що іноді темніло в очах або нудило. Та згодом я адаптувався і звик, набрав форму. Цікаво, що за шість перших місяців моя вага зменшилась з 90 до 82 кілограмів, що було для мене суперовим результатом.

Приблизно за два-три місяці тренер почав випускати мене в ринг на спаринги. Але спочатку то був не вільний бій, а відпрацювання конкретних завдань. Найважчими виявились розтяжки. Мабуть, давалась взнаки робота в офісі — 10-12годин сидіння за комп’ютером не кращим чином впливають на гнучкість.

— А як минають тренування зараз? І як часто тренуєшся?

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

Набивка — це відпрацювання ударів ногами по ногах і корпусу. Робота доволі різнопланова — з використанням захисту та без нього, на блок або ж по корпусу. Головна мета — навчитись тримати удар.

Робота на мішках — це силова робота. Як правило, середній темп чергується з так званими спуртами, різкими підвищеннями темпу на короткий інтервал часу, 30-40 секунд.

Функціонал — це, в основному, кросфіт, дуже популярна штука в багатьох видах спорту. Ми використовуємо від 8 до 10 снарядів: канати, штангу, молот, гирі, степ тощо. Проходимо три кола по 60, 40 і 20 секунд відповідно. На кожному снаряді потрібно відпрацювати максимальну кількість повторень за відведений час і перейти на інший снаряд.

Зазвичай я маю три тренування на тиждень по дві години.

Дуже популярний останнім часом кросфіт підвищує витривалість

— Чи потрібне якесь екіпірування? Що скільки коштує? Як новачкові вибрати правильні речі?

Так, екіпірування для занять необхідне. Але все й одразу купувати не обов’язково. Для початку вистачить пари бинтів, захисту ніг і спарингових рукавиць — їхня вага від 12 до 16 унцій залежно від вагової категорії спортсмена. Ціни дуже різні, все залежить від бренду і місця придбання. Наприклад, одна й та сама модель рукавиць може коштувати рівно вдвічі дешевше, якщо порівняти пафосний магазин у центрі з купою консультантів і магазин у підвальному приміщенні спального району Києва.

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

Новачкам радив би для початку не витрачати значні кошти на екіпірування. Початковий бюджет приблизно такий: рукавиці — від 500 грн, захист ніг — від 400 грн, бинти — від 200 грн. Наприклад, рукавиці топових брендів можуть коштувати 8 тис. грн і більше. Але доки не зрозумієш, що це «твоє», такі кошти витрачати не варто.

— Чи брав участь у якихось змаганнях, чемпіонатах? Якщо так, розкажи, як все минуло.

Свого часу тренер пропонував виступати в лізі «Б» Києва — це аматорські змагання із середнім рівнем підготовки. В лізі «А» виступають спортсмени достатньо пристойного рівня. Також запрошували виступити на турнірі білих комірців — це регулярні змагання з правил боксу серед новачків. Головна умова — щоб учасник ніколи до того не брав участі у змаганнях.

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

— За ким з професійних кікбоксерів або боксерів стежиш? За кого зазвичай вболіваєш? Кого вважаєш взірцем для наслідування?

Гадаю, не лише я, а й більшість хлопців стежить за виступами наших топових боксерів — Василя Ломаченка, Олександра Усика та Олександра Гвоздика. Втім, цей список можна продовжувати безкінечно, адже українська школа боксу — одна з найкращих у світі. Українські кікбоксери також входять до світової еліти — наприклад, Артур Кишенко, Роман Крикля. Якщо казати про змішані єдиноборства (ММА), то з нулем поразок Україну в найпрестижнішому промоушені світу UFC представляє Ярослав Амосов. Тож існує ціла низка українців, за якими варто стежити і наслідувати.

Щодо представників інших країн, особисто для мене кумирами є Buakaw Banchamek, Saenchai, Andy Souwer, Badr Hari, Gokhan Saki.

— Які навички, отримані під час занять спортом, виявляються корисними в роботі та в житті загалом? Чи доводилось тобі застосовувати вміння битися поза залом — наприклад, захищатись від грабіжників?

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

Колеги іноді жартують, що кікбоксинг допомагає мені краще працювати з командами, бо в разі чого я можу застосувати якісь «прийомчики». Але це все жарти, звісно.

Вулична бійка — це взагалі абсолютно інше явище у порівнянні зі спарингом або поєдинком за правилами. Відсутність будь-якої амуніції (рукавиць, шолому, капи тощо) збільшує ймовірність травм до 100%, бій триває не більше 20-30 секунд,і для його завершення достатньо одного-двох влучних ударів. Треба користуватися будь-якою можливістю уникнути бійки, якщо тільки йдеться не про життя, здоров’я або честь близьких.

Що ж стосується мене особисто, такий випадок за останні роки трапився лише раз: доводилось захищати товариша. Можу сказати, що без підготовки наслідки були б для мене дуже сумними. Але, на щастя, все закінчилось добре.

— Наскільки взагалі в Україні розвинута спільнота з кікбоксингу? Які є клуби, турніри?

Мені складно проаналізувати якісь тренди розвитку кікбоксингу за багато років, але відколи я почав займатись, кількість осіб, що приходять на тренування, постійно збільшується. Україна має високий авторитет на міжнародній арені, в різних вікових і вагових категоріях, у різних версіях є чемпіони світу і Європи, багато професійних спортсменів. Одесит Артур Кишенко визнаний одним із найсильніших кікбоксерів світу незалежно від вагової категорії. Такий собі Ломаченко в світі кікбоксингу.

Клубів в Україні дуже багато. Лише в одному Києві, за моїми підрахунками, їх понад 15. Мабуть, не пораджу щодо вибору клубу, адже я весь час займаюся в одному місці — Fight Family. Його можу рекомендувати без вагань: крутий склад тренерів, класна локація, гарні умови, різноманіття напрямків. Відчувається, що керівництво серйозно займається його розвитком — тут відбуваються регулярні майстер-класи від відомих чемпіонів та інші заходи в клубі та поза його межами.

Якщо казати про турніри, то один із відомих, що проходить у Києві, — «Арка». Він проводиться у травні на день міста біля арки Дружби Народів.

Front middle-kick — гарний спосіб тримати суперника на дистанції

— Що порадиш початківцям? Якою має бути фізична підготовка для цього спорту? Як уберегтися від травм?

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

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

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

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

— Які спортивні цілі ставиш собі на майбутнє?

Найближчим часом планую збільшувати кількість тренувань на тиждень до чотирьох — почну індивідуальні заняття, аби виправити деякі технічні помилки. Можливо, спробую виступити в якомусь аматорському турнірі. Це завдання максимум на поточний рік. Завдання мінімум — продовжити тренування і тримати форму. Всім спорту!

Это работает: как эффективно управлять процессами в продуктовой IT-компании

$
0
0

Что делать, когда компания проходит этап взрывного роста? Очевидно, что с увеличением количества сотрудников нужно менять не только структуру отделов, но и все процессы, которые до того казались наиболее удачными. За 15 лет опыта в IT я прошел путь от разработчика интернет-решений для банковской сферы до технического директора. Поэтому на личном опыте знаю, насколько важны правильно выстроенные процессы и четко поставленные задачи с точки зрения разработки и насколько благоприятным может быть грамотно настроенное взаимодействие с бизнес-юнитом.

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

Что-то здесь не так

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

Восемь лет назад мы были заняты жизненно важными, с точки зрения разработки, задачами: строили свою инфраструктуру, создавали сайт megogo.net и писали приложения для Smart TV. И всем этим занимались около 20 человек, поэтому структура всего отдела разработки была максимально простой и плоской. Нам не нужны были проджекты и тимлиды, сложные процессы взаимодействия были бы избыточными.

Сейчас все иначе. Нас почти 120, и это только люди, задействованные в разработке продуктов. Поэтому сегодня бизнес-процессы сильно отличаются от того, что было в 2011–2012 годах.Первые несколько лет существования компании не все было гладко и не все принятые нами решения и установленные процессы были оптимальными.

Сначала у нас не было деления на команды, а задачи передавались «первому свободному разработчику». Мы ввели Road map, а директор разработки, по сути, выполнял функции главного project manager: самостоятельно распределял задачи и следил за ходом всей разработки. Тем не менее до идеала было далеко: у нас не существовало процесса передачи задач, техническую документацию готовили условные product owners в лучшем случае в Google Docs. Кроме того, что этот подход сильно замедлял всю разработку, project manager тратил огромное количество времени, чтобы из такого документа вычленить и организовать только важную для разработки информацию. В итоге из-за отсутствия согласованности выполнение даже «маленьких» задач в разы затягивалось по срокам.

В процессе развития стало понятно, что используемые методы перестают работать, замедляют рост и ход разработки платформы и, в принципе, давно устарели. Так мы пришли к тому, что пора скорректировать устоявшиеся процессы.

А с чего начать?

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

В итоге мы составили для себя план отстройки: запустили ретроспективу своих процессов и на некоторых этапах даже задействовали внешних консультантов.

Первый шаг — общение с командами. Мы собирали «боль» разработчиков во время работы над задачами с точки зрения процессов. Именно обратная связь от команд стала важнейшим рычагом для внедрения изменений.

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

Так у нас появилась команда системных аналитиков. Они превращали документацию от бизнес-юнита в реальные требования для разработки. Параллельно с аналитиками в «бизнесе» создали департамент продуктологов, которые собирали требования, организовывали их в onepagers для аналитиков, следили за целостностью документации и тесно сотрудничали в процессе подготовки требований к разработке.

Следующим шагомбыло проведение масштабного воркшопа по методологии Agile. Рассказали менеджменту и командам, зачем это нужно в нашем случае и как внедрение поможет упростить работу всей разработки.

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

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

Тестирование продуктовых идей

В том же временном промежутке у нас проводилась оценка перспективных технологий, которые способны упростить разработку и расширить возможности нашей платформы. За их исследование отвечали архитекторы и тимлиды, затем тестировали команды. Самые перспективные технологии взяли в работу. Так мы начали использовать Scala и React.

Новые принципы работают

Естественно, мы не остановились на внедрении Agile. Например, мы усложнили структуру команд, но смогли упростить взаимодействие между различными отделами. Теперь в каждой из команд кроме разработчиков и QA-инженеров есть project manager, который занимается планированием и обсуждением требований к функциональностям, управляет релизами и их развертыванием, следит за выполнением задач. И обязательно есть team lead, отвечающий за распределение задач, code review, выбор технологий и архитектурные решения.

Структура отдела разработки

За каждой из продуктовых команд закреплен системный аналитик, который является своего рода связующим звеном между бизнесом и разработкой. Его задача — формирование backlog и подготовка формализованных требований для реализации фич.

Отдел системных аналитиков получает бизнес-задачи, каждая из которых проходит через воронку требований. Воронка включает идеи, Road Map с приоритетами и улучшения. Мы получаем некий обозримый набор задач, поэтому важно определить приоритеты и оценить, что улучшит пользовательский опыт и что сможет улучшить сервис. Затем аналитики описывают задачи детальнее, идет подготовка дизайнов и полной спецификации для команд Smart TV, Mobile (Android, iOS, Android TV и Apple TV), Web (desktop и mobile). Далее продуктовые команды передают задачу сервисным командам, которые разрабатывают логику на Back-end. Именно в таком взаимодействии актуально выбранное нами разделение — большее число продуктовых команд создает условную конкуренцию за ресурсы сервисных команд. Эта проблема решается выбором разных методологий (Scrum и Kanban) и однозначным Road Map, явно указывающим на новые функции или особенности, которые необходимо реализовать каждой из команд.

Еще один важный этап в нашем flow — MVP-анализ для тестирования объемных функций и неочевидных идей. Часто он позволяет существенно сократить Time to market для новых продуктов, что, в свою очередь, дает нам существенную фору по сравнению с конкурентами. Когда появляется гипотеза, мы формируем минимальный scope задач, достаточных для релиза и тестирования.

Вот один из последних примеров. У нас была классическая на медиарынке задача — увеличить Retention пользователей на мобильных устройствах. Мы предположили, что популярный в мобильном сегменте формат Stories может нам помочь. В качестве гипотезы для тестирования мы решили использовать наиболее интересные фрагменты из телепередач, сериалов и фильмов. Создавались короткие ролики до 10 минут с возможностью перехода к полной версии. Суммарно над задачей работало около 20 специалистов в течение 3 месяцев. Мы разработали новый инструмент для iOS и Android, настроили метаданные и создали новые профили транскодинга.

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

Время важных вопросов

После всех оптимизаций и ретроспектив мы поставили себе вполне логичный вопрос: как понять, что процессы работают? Объективно это сделать сложно. У нас нет классических KPI. Мы выбрали для себя главный показатель — выдача готового проекта в кратчайшие сроки с допустимым минимумом багов и максимумом функциональности. На каждом члене команды лежит ответственность за процесс. Для большой задачи мы оцениваем, сколько на нее уйдет времени и ресурсов. Но если в итоге не попали в цель, разбираем на ретроспективах, что пошло не так. Во многих случаях Jira наглядно показывает, почему и на каком этапе зависла задача. Ко всему прочему для оценки серьезных проблем в команде есть Incident Manager.

На эффективность процессов влияют не системы трекинга, а сами люди. И конечно, нам приятно, когда сотрудники самомотивированны. К счастью, у нас есть интересные проекты и амбициозные задачи. Медиарынок постоянно развивается. Чтобы успевать за изменениями, мы раз в две недели организовываем неформальные презентации, на которых разбираем новые технологии либо делимся перспективными решениями, над которыми работаем сами. К примеру, на одной из встреч мы разбирались во Flutter, а на другой — рассказывали, как работает система рекомендаций.

Мы четко видим, куда нам двигаться, чтобы и далее улучшать свой flow. Во-первых, следует принимать решения на основании данных, A/B-тестов и строгих метрик — здесь нам не обойтись без алгоритмов Data Science. Во-вторых, построить масштабный Idea Backlog, в основе которого будет глубокая статистика, чтобы убрать субъективные метрики и руководствоваться цифрами.

В итоге мы довольны своим flow и процессами, которые за ним стоят. Разработка функционирует, с нашей точки зрения, оптимально и эффективно. А это единственный важный показатель.

Выплачиваем технический долг с пользой для бизнеса

$
0
0

Решать, как развивать продукт, довольно непросто. Нужно учитывать десятки разных факторов, и некоторые из них — непредсказуемые. Часть решений явно или косвенно принимается технической командой, в том числе стратегия по работе с техническим долгом. Тема эта старая, сложная, мало кого оставляет равнодушным — этим и интересна.

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

Митинг

Менеджмент(радостно): мы согласовали все детали и запускаем новую фичу!

Девелопмент(недовольно): у нас устарела либа для отрисовки графиков, ужасная сортировка в старом модуле. И мы уже полгода не можем привести в порядок структуру проекта, после того как маркетингу срочно понадобилось переименовать тему.

QA (озабоченно): не работает апгрейд с AmEx картами и не применяются кастомные темы, это нужно забрать в следующий milestone.

На таких митингах кажется, что у всех разные цели. Бизнес уже наступал на грабли инвестиций в девелопмент без видимого результата. Тимлид знает, что накопленные костыли рано или поздно выстрелят ему в ногу. А QA на прошлой неделе 10 минут рассказывал на ретроспективе «what we should start doing», после того как ключевые юзеры зарепортили баги напрямую CEO.

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

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

— Я так не могу, мне стыдно, что в продукте такой код. У меня в субботу будет время, пойду наведу порядок, хотя бы где успею.

— Тима очень настаивала, мы выделили один спринт под рефакторинг, смогли согласовать с клиентом, но вчера после демо он остался недоволен и попросил сфокусироваться на business priorities.

Мы за все хорошее

То, что кажется разными проблемами, на самом деле является одной и той же. И бизнес, и QA хотят, чтобы как можно меньше значимых юзероввстретили баги. Бизнес заинтересован развивать продукт с наименьшими затратамии как можно быстрее. Девелопмент заинтересован иметь качественный codebase, который легко поддерживатьи куда можно наращивать фичибез опасения наткнуться на хрупкий, загадочный и немасштабируемый legacy. Что соответствует бизнес-целям тоже:

  • меньше значимых юзеров — значит, что баг становится проблемой, когда касается большого процента target audience (в основном это те, кто приносит прибыль или потенциально может ее принести);
  • наименьшими затратами = легко поддерживать = наращивать фичи, только речь идет не об абстрактной фиче, а о том, что уйдет в работу в ближайшее время.

На примере одного беклога

Давайте посмотрим на практике (баги техническим долгом не считаются, но часто фигурируют где-то рядом, поэтому глянем и на них). В беклоге лежит:

IssueDescription
update PrettyCharts libraryЛиба, которую используют для отрисовки графиков, устарела на две версии.
an error when trying to setup custom themeУ всех юзеров, которые пытаются настроить кастомный UI, прилетает 500 с сервера, и настройки не сохраняются.
payment fails when upgrading with AmEx cardНе проходит апгрейд, если карточка — AmEx.
apply new sorting logic to the old moduleВ новых модулях сделали элегантную сортировку, а в старом оставили изначальное корявое решение, сделанное наспех.
duplicate folders theme and theme_goldenКогда-то тема в приложении была одна, потом добавились другие темы, и дефолтную переименовали в Golden. В коде часть файлов от нее осталась лежать в папке theme, часть перенеслась в theme_golden.

Все айтемы заслуживают внимания, баги серьезные. В соответствии с best practices либы надо вовремя обновлять, сортировка должна быть consistent везде, а с папками вообще фейспалм. Окей.

В то же времявсе айтемы сами по себе никому не мешают до тех пор, пока кто-то не столкнется с проблемой. Например, коряво реализованная сортировка в старом модуле становится проблемой, когда в этой части кода надо что-то менять. То же — с багами: наличие бага само по себе не страшно, все зависит от контекста — в каком случае он попадаетсяюзерам и как много людейего встретят.

Добавляем к нашим айтемам контекст и описываем, почему это проблема.

IssueDescriptionContext
update PrettyCharts libraryЛиба, которую используют для отрисовки графиков, устарела на две версии.В последней версии либы лучше производительность и есть два новых типа графиков.
Если нужен будет экспорт ежедневных отчетов, старая либа с ним не справится.
an error when trying to setup custom themeУ всех юзеров, которые пытаются настроить кастомный UI, прилетает 500 с сервера, и настройки не сохраняются.Фича доступна только платным юзерам. По статистике, из платных юзеров 10% пробуют ставить кастомный UI.
payment fails when upgrading with AmEx cardНе проходит апгрейд, если карточка — AmEx.Применимо для платных юзеров, чьи подписки созданы до 2019 года. Таких 1%.
apply new sorting logic to the old moduleВ новых модулях сделали элегантную сортировку, а в старом модуле оставили изначальное корявое решение, сделанное наспех.В старом модуле сортировка работает очень медленно, если записей больше 5000.
Добавить сортировку по еще одному столбцу очень сложно.
duplicate folders theme and theme_goldenКогда-то тема в приложении была одна, потом добавились другие темы, и дефолтную переименовали в Golden. В коде часть файлов от нее осталась лежать в папке theme, часть перенеслась в theme_golden.В эти папки приходится заглядывать в среднем два раза в неделю каждому фронтэндщику, и уходит лишних 20 минут, потому что непонятно, что где искать.

Дальше узнаем, что по роадмапе нужно делать:

  • onboarding for corporate clients;
  • generate annual reports in the old module, use CoolAPI.

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

IssueDescriptionContextDecision
update PrettyCharts libraryЛиба, которую используют для отрисовки графиков, устарела на две версии.В последней версии либы лучше производительность и есть два новых типа графиков.
Если нужен будет экспорт ежедневных отчетов, старая либа с ним не справится.
С текущей производительностью проблем нет, новые типы графиков и ежедневные отчеты пока не нужны. Старая либа не будет ни для кого головной болью. (Конечно, если апдейт — дело получаса, он просто берется и делается, но, допустим, это не наш случай)
an error when trying to setup custom themeУ всех юзеров, которые пытаются настроить кастомный UI, прилетает 500 с сервера, и настройки не сохраняются.Фича доступна только платным юзерам. По статистике, из платных юзеров 10% пробуют ставить кастомный UI.10% платных юзеров — повод задуматься, но это не core feature, юзерам работать баг не мешает, продукт они не забросят, разочарованные в саппорт писать не будут, и QA тоже может быть спокоен. Однако в роадмапе есть onboarding for corporate clients, а все корпоративные клиенты будут использовать кастомные темы, поэтому нужно чинить.
payment fails when upgrading with AmEx cardНе проходит апгрейд, если карточка — AmEx.Применимо для платных юзеров, чьи подписки созданы до 2019 года. Таких 1%.Очень маленькая вероятность, что кто-то попадет на этот баг, и даже если это произойдет, саппорт может сделать апгрейд вручную. Можно оставлять как есть.
apply new sorting logic to the old moduleВ новых модулях сделали элегантную сортировку, а в старом модуле оставили изначальное корявое решение, сделанное наспех.В старом модуле сортировка работает очень медленно, если записей больше 5000.
Добавить сортировку по еще одному столбцу очень сложно.
Максимальное количество записей у текущих пользователей — 3000, добавления сортировки по еще одному полю в планах нет. Фича generate annual reports с сортировкой не связана. Значит, с проблемой тоже никто не столкнется.
duplicate folders theme and theme_goldenКогда-то тема в приложении была одна, потом добавились другие темы, и дефолтную переименовали в Golden. В коде часть файлов от нее осталась лежать в папке theme, часть перенеслась в theme_golden.В эти папки приходится заглядывать в среднем два раза в неделю каждому фронтэндщику, и уходит лишних 20 минут, потому что непонятно, что где искать.С проблемой сталкиваются регулярно, поэтому здесь можно явно выиграть в скорости и поддерживаемости (если наведение порядка не потребует месяца, конечно).

По закрытии этих айтемов бизнес получает свой профит, потому что починили критический баг для corporate clients onboarding и сэкономили 5 часов девелопмента ежемесячно.

Контекст для рефакторинга/багфикса

При обсуждении важности айтемов спрашивайте себя (и других):

  • каких компонентов/фичей касается;
  • какую конкретно проблему создает текущая реализация;
  • какое преимущество дает переделка (например, будет легче вносить изменения, или можно будет переиспользовать код, или вынести в отдельный компонент, и тогда добавление новой такой же сущности будет занимать минуту);
  • планируется ли в ближайшее время разработка в этих компонентах;
  • какого сегмента пользователей коснется (скажем, нужна оптимизация под мобильные устройства, а с мобильных сидят только пользователи из региона Х, и они не являются target audience);
  • для багов — как часто встречается, для какого use case, есть ли workaround.

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

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

«Продаем» рефакторинг

Зная контекст и бизнес-цели на ближайшее время, девелопменту становится просто «продать» рефакторинг. И, с другой стороны, зная, какой именно impact будет от рефакторинга, менеджмент может выставить правильный приоритет. Грубо говоря, мы что-то улучшаем не для его самоулучшения, а чтобы упростить дальнейшее развитие продукта.

Например, «продадим» апдейт фреймворка, который займет существенное время (если апдейт быстрый, то он обычно делается без вопросов):

А. We need to update the framework because the longer we use the old one, the harder it will be to update it in the future.Ценности для бизнеса нет.

В. We need to update the framework. The new version has the methods to receive data in X format and this will allow us to sent instant messages to the customers. Also the performance of pdf exports will improve by 20%. Если бизнесу важны мгновенные сообщения и скорость экспорта, то апдейт фреймворка у вас «купят».

В варианте Адевелоперы обычно поднимают вопрос long-term поддерживаемости. Многие в своей практике сталкивались с продуктами, где обновлять зависимости/рефакторить было уже проблематично, и на ранней стадии было бы проще. Если есть аргументы, что апдейт однозначнопонадобится потом, поэтому лучше сделать его сейчас, то нужно их приводить, и вариант сводится к чему-то наподобие В.

Если это просто с запасом «на будущее», то высокий риск ненужного результата. Будущее может не наступить (проект не взлетит). Будущее может быть другим (появится другой более интересный фреймворк). Будущему может хватить и старого фреймворка для своих нужд, и в части случаев действительно придется обновлять фреймворк, уже когда слишком много на него завязано. Если на момент принятия решения вероятность последнего исхода или мала, или неизвестна, то ресурсы на него не выделят, потому что будут более приоритетные задачи, которые решают реальные и видимые на тот момент проблемы.

TL;DR

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

  • Само наличие legacy или багов не страшно: важно понимать, что из этого является реальной проблемой на данный момент.
  • Понимая бизнес-приоритеты и направление развития продукта, можно «продать» нужный рефакторинг/багфикс, от чего выиграют обе стороны. Бизнес получит быструю разработку, девелопмент — легко поддерживаемый продукт, а ключевые кастомеры будут иметь smooth experience.
  • Возвращайтесь к тому, что именно улучшится предлагаемым изменением. Важно ли это?
  • Если вы владелец бизнеса, делитесь своими планами с командой как можно чаще. Это поможет принимать более подходящие архитектурные решения и избежать накопления технического долга, а при его наличии — выплатить самый критический.
  • Если вы менеджер, добывайте и делитесь информацией о планах и о контексте рефакторинга/багфикса, но сначала сами убедитесь, что поняли, о чем речь =)
  • Если вы девелопер, спрашивайте о том, что сейчас важно продукту, помогайте сделать технический долг видимым и облегчайте понимание правильного контекста.

Готовый к продакшену Vue SSR: 5 простых шагов

$
0
0

Я работаю в компании Namecheap на позиции Senior Software Engineer. В нашей компании мы используем Vue.js с серверным рендерингом для некоторых наших страниц. Настроить SSRможет быть не так легко, поэтому я попытался описать этот процесс простыми шагами. Также, читая официальную документацию, можно подумать, что было бы полезно увидеть как приложение должно выглядеть в итоге. Поэтому я создал репозиторий с примером.

В этой статье мы рассмотрим, как настроить готовый к продакшену SSR для Vue-приложения, используя:

  • Webpack 4;
  • Babel 7;
  • Node.js Express сервер;
  • webpack-dev-middleware и webpack-hot-middleware для удобной разработки;
  • Vuex для управления состоянием приложения;
  • плагин vue-meta для управления метаданными.

Отмечу, что мы не будем останавливаться на деталях использования этих технологий, а сосредоточимся только на SSR. Надеюсь, это будет полезно. Поехали!

Шаг 1. Настройка webpack

Сейчас у вас, вероятно, уже есть какое-то Vue-приложение, а если нет, то можете использовать мой репозиторий в качестве отправной точки. Для начала взглянем на структуру наших папок и файлов:

Как видите, структура довольно распространенная, за исключением пары вещей, которые могут бросаться в глаза:

  • есть два отдельных webpack-конфига для клиентского и серверного билдов: webpack.client.config.jsи webpack.server.config.js;
  • есть две соответствующие точки входа: client-entry.jsи server-entry.js.

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

С клиентским конфигом, вероятно, вы уже имели дело. Он предназначен для сборки нашего приложения в простые JS- и CSS-файлы.

Серверный конфиг более интересен. С его помощью мы создадим специальный json-файл, который будет использоваться на стороне сервера для рендеринга простого HTML-кода нашего Vue-приложения. С этой целью мы используем vue-server-renderer/server-plugin.

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

Как вы могли догадаться, все общие настройки клиентского и серверного конфигов мы вынесли в базовый конфиг.

Шаг 2. Создание точек входа

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

Обратите внимание: вместо создания экземпляра приложения мы экспортируем фабричную функцию createApp(). Если бы приложение работало только в браузере, то нам не пришлось бы беспокоиться о том, чтобы пользователи получали новый экземпляр Vue для каждого запроса. Но поскольку мы создаем приложение в Node.js процессе, наш код будет инициализирован один раз и останется в памяти того же контекста. Поэтому если мы будем использовать один экземпляр Vue для нескольких запросов, это может привести к ситуации, когда один пользователь получит состояние приложения другого. Чтобы избежать этого, мы должны создавать новый экземпляр приложения для каждого запроса. По этой же причине не рекомендуется использовать синглтоны с состоянием во Vue-приложении.

Каждое приложение, скорее всего, будет иметь какие-то метаданные, например title или description, которые должны отличаться на разных страницах. Вы можете реализовать это с помощью плагина vue-meta. Чтобы узнать, почему мы используем параметр ssrAppId, перейдите по этой ссылке.

В клиентской точке входа мы вызываем createApp(), передавая начальное состояние, установленное сервером, и монтируем приложение в DOM, после того как роутер завершил начальную навигацию. Также в этом файле вы можете импортировать глобальные стили и инициализировать директивы или плагины, которые работают с DOM.

Серверная точка входа в значительной степени описана в комментариях. Единственное, что я хотел бы добавить в отношении коллбэка router.onReady(): если мы используем хук serverPrefetchдля предварительного получения данных в каких-то компонентах, он ждет, пока не зарезолвится промис, возвращаемый из хука. Мы увидим пример его использования чуть позже.

Хорошо, теперь мы можем добавить в package.jsonскрипты для сборки нашего приложения:

Шаг 3. Запуск Express-сервера с Bundle Renderer

Чтобы преобразовать наше приложение в простой HTML на стороне сервера, мы будем использовать модуль vue-server-rendererи файл ./dist/vue-ssr-server-bundle.json, который мы сгенерировали, запустив скрипт build:server. Давайте пока не будем думать о режиме разработки, обсудим это на следующем шаге.

Сначала нам нужно создать рендерер, вызвав метод createBundleRenderer()и передав два аргумента: бандл, сгенерированный нами ранее, и следующие параметры:

  • runInNewContext
  • Помните проблему с общим состоянием между несколькими запросами, которую мы обсуждали на предыдущем шаге? Эта опция решает проблему, но создание нового контекста V8 и повторное построение бандла для каждого запроса является дорогостоящей операцией, поэтому рекомендуется установить этот флаг в значение false из-за возможных проблем с производительностью и остерегаться использования в приложении синглтонов с состоянием.
  • template

Специальный комментарий <!--vue-ssr-outlet-->будет заменен на HTML, сгенерированным рендерером. И кстати, используя опцию template, рендерер автоматически добавит скрипт с объявлением глобальной переменной __INITIAL_STATE__, которую мы используем в client-entry.jsпри создании своего приложения.

Теперь, когда у нас есть экземпляр рендерера, мы можем сгенерировать HTML, вызвав метод renderToString()и передав начальное состояние и текущий URL для роутера.

Шаг 4. Настройка dev-окружения

Что нам нужно для комфортной разработки Vue-приложения с SSR? Я бы сказал, следующее:

  • запускать только один Node.js сервер без использования дополнительного webpack-dev-server;
  • регенерировать vue-ssr-server-bundle.jsonфайл при каждом изменении исходного кода;
  • hot reloading.

Чтобы реализовать все эти вещи, можно воспользоваться функцией setupDevServer() в server.jsфайле (см. предыдущий шаг).

Эта функция принимает два аргумента:

  • app — наше Express-приложение;
  • onServerBundleReady() — callback, который вызывается каждый раз при изменении исходного кода и создании нового vue-ssr-server-bundle.json. Он принимает бандл в качестве аргумента.

В файле server.js мы передаем callback onServerBundleReady() в виде стрелочной функции, которая принимает новый бандл и заново создает рендерер.

Обратите внимание: мы рекваерим все зависимости внутри функции setupDevServer(), нам не нужно, чтобы они занимали память процесса в production-моде.

Теперь давайте добавим npm-скрипт для запуска сервера в дев-моде с использованием nodemon:

"dev": "cross-env NODE_ENV=development nodemon ./server.js",

Шаг 5. Использование serverPrefetch()

Скорее всего, вам потребуется получать какие-то данные с сервера во время инициализации приложения. Вы можете сделать это, просто вызвав API-эндпойнт после маунта рутового компонента, но в этом случае ваш пользователь должен будет наблюдать спиннер — не самый лучший UX. Вместо этого мы можем получить данные во время SSR, используя хук компонента serverPrefetch(), который был добавлен в версии 2.6.0 во Vue. Давайте добавим тестовый эндпойнт в наш сервер.

Мы вызовем этот эндпойнт в экшене getUsers. Теперь давайте рассмотрим пример использования хука serverPrefetch() в компоненте:

Как видите, мы используем serverPrefetch()вместе с хуком mounted(). Нам это нужно в тех случаях, когда пользователь переходит на эту страницу с другого роута на стороне клиента, поэтому массив usersбудет пуст и мы вызываем API.

Также обратите внимание, как определяются title- и description-метаданные для конкретной страницы в свойстве metaInfo, предоставляемом плагином vue-meta.

Ну вот и все. Я думаю, что основные моменты настройки SSR для Vue.js рассмотрены, и надеюсь, что эти шаги помогли вам лучше понять весь процесс.


Применение GameplayKit Randomization и State Machine в iOS-проектах

$
0
0

В предыдущей статьебыло описано, как применять игровой 2D-движок SpriteKit для быстрого создания простых анимаций в iOS. В новой статье я хочу поделиться, как использовать GameplayKit в неигровых приложениях.

GameplayKit — это набор инструментов, который Apple представляет для быстрого конструирования игровых процессов и алгоритмов. Рассмотрим инструменты, которые применимы даже в UIKit/Appkit-проектах.

Randomization

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

Раньше чаще всего многие применяли метод random() или arc4random(), построенный на ARC4-алгоритмеи генерирующий числа между 0 и 4294967295. После выхода Swift 4.2 появились новые методы для генерации рандома:

let randomInt = Int.random(in: 0..<10)
let randomDouble = Double.random(in: 5.71838...6.15249)
let randomBool = Bool.random()

Обычно этих инструментов достаточно, если нам нужно просто сгенерировать случайное число, не задумываясь о последствиях. В таких случаях вы никак не сможете влиять на алгоритм рандомизации, последовательность и частоту выпадения определенных значений. А если попытаться влиять на этот процесс, производя генерацию несколько раз, чтобы получать нужный range значений, и еще это нужно делать на каждый кадр, то производительность работы может сильно пострадать. Такая ситуация обусловлена тем, что в современных играх часто происходит одновременная генерация нескольких случайных чисел за один кадр и, таким образом, чтобы поддерживать 60 кадров в секунду, придется несколько десятков, а иногда и сотен раз в секунду инициализировать генерацию и обработку случайных чисел.

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

Именно для этого и применяется Randomizationиз GameplayKit, позволяя сделать генерацию более детерминированной.

Random Source

Собственно, весь процесс рандома состоит из объекта-суперкласса GKRandomSource, который является источником рандомных чисел (Random Source), а также наследования от протокола GKRandom.

Сам протокол GKRandomпредставляет минимальный интерфейс для генерации случайных чисел и состоит всего из 4 методов:

let randomSource = GKRandomSource.sharedRandom()
// возвращает случайное значение Int32.min и Int32.max
// диапазон чисел от -2 147 483 648 до 2 147 483 647 
randomSource.nextInt()
// возвращает случайное значение Int между 0 и 9
randomSource.nextInt(upperBound: 10)
// возвращает случайное Float значение в диапазоне от 0.0 до 1.0
randomSource.nextUniform()
// возвращает случайное Bool
randomSource.nextBool()

GameplayKit предлагает один базовый и 3 альтернативных Random Source, которые являются детерминированными и могут быть сериализованы с использованием NSCoding, чтобы, к примеру, была возможность сохранить текущее состояние последовательности.

  • GKRandomSource — базовый генератор случайных чисел, от которого наследуются все последующие Random Source классы.
  • GKARC4RandomSource — генератор случайных чисел, реализующий уже привычный в iOS алгоритм ARC4 (arc4random). Особенность также состоит в том, что у этого источника есть метод dropValues(_:), который помогает отбросить определенное количество первых последовательностей, чтобы было сложнее предугадать вероятное следующее значение.
let arc4 = GKARC4RandomSource()
// Минимальное рекомендуемое количество отбрасываемых значений в последовательности
arc4.dropValues(768)
// Генерация случайного числа от 0 до 10
arc4.nextInt(upperBound: 11)
  • GKLinearCongruentialRandomSource — генератор чисел, реализующий алгоритм линейного конгруэнтного генератора, который быстрее, но менее случайный, чем стандартный ARC4. Основное преимущество его в том, что этот алгоритм есть в стандартных библиотеках некоторых языков программирования. Поэтому иногда его можно применять для создания одинаковой последовательности случайных чисел на разных платформах. К примеру, в Java этот алгоритм используется в java.util.Random. Также его стоит применять в том случае, если вы действительно делаете десятки или сотни генераций в секунду, иначе разница в производительности будет практически незаметна.
let linearCongruential = GKLinearCongruentialRandomSource()
// Генерация случайного числа от 0 до 10
linearCongruential.nextInt(upperBound: 11)
  • GKMersenneTwisterRandomSource — генератор случайных чисел, реализующий алгоритм вихрь Мерсенна, разработанный японскими учеными, который является более случайным, но и менее производительным, чем ARC4. Реализован в стандартных библиотеках: C++, Python, Ruby, PHP.
let mersenneTwister = GKMersenneTwisterRandomSource()
mersenneTwister.nextInt(upperBound: 11)

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

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

Random Distribution

Еще одним важным преимуществом рандомизации через GameplayKit является возможность формировать Random Source вместе с Random Distribution (методом случайного распределения).

Всего нам представлено 3 класса для Random Distribution:

  • GKRandomDistribution — распределение, где равномерная вероятность генерации любого числа в указанном диапазоне приблизительно равнозначна. Таким образом, исключается предвзятость в отношении любого возможного результата. Что приятно, этот класс имеет удобный интерфейс, чтобы сразу инициализировать аналог 6-гранногокубика, или 20-гранногокубика, или даже 100-гранногокубика.
// Это также можно сделать через GKRandomDistribution.d6()
let 🎲 = GKRandomDistribution(forDieWithSideCount: 6)
(1...10).forEach { _ in print(🎲.nextInt()) }
// 5 1 6 2 1 4 3 1 4 6
 
// Реализация 20 гранного кубика
let d20 = GKRandomDistribution.d20()
d20.nextInt() 
 
// Реализация 100 гранного кубика
let d100 = GKRandomDistribution(lowestValue: 1, highestValue: 100)
d100.nextInt()

Такой подход очень похож на использование Int.random(in:), но здесь основное отличие в том, что можно заранее инициализировать GKRandomDistribution, а затем заново использовать его сколько угодно, не задавая каждый раз необходимый диапазон чисел. В текущем примере при реализации распределения будет использоваться алгоритм ARC4 для генерации последовательности. Чтобы переопределить Random Source, достаточно просто инициализировать Random Distribution с указанием нужного источника.

let linearCongruential = GKLinearCongruentialRandomSource()
let 🎲 = GKRandomDistribution(randomSource: linearCongruential,
                                        lowestValue: 1,
                                        highestValue: 6)
🎲.nextInt()
  • GKGaussianDistribution — генератор, который реализует распределение Гаусса (нормальное распределение) по множественным выборкам. Если коротко, то такой алгоритм рандома позволяет чаще получать средние значения в указанном вами интервале минимального и максимального значения. Например, в приложении нужно пользователю ежедневно выдавать бонус за использование, и такой алгоритм подойдет, чтобы всегда предоставлять усредненное значение. Или в играх, когда необходимо генерировать юниты, которые почти всегда будут с усредненными характеристиками.
let random = GKRandomSource()
// В этом примере, представим что у нас 10 гранный кубик, чтобы лучше было видно разброс чисел
let 🎲 = GKGaussianDistribution(randomSource: GKRandomSource(),
                                  lowestValue: 1,
                                  highestValue: 10)
(1...10).forEach { _ in print(🎲.nextInt()) }  // Бросаем кубик 10 раз
// 7 8 5 4 5 7 6 5 5 4

Также здесь мы можем влиять на рандомизацию, изменяя ожидаемое среднее значение meanи шаг интервала deviation. Возьмем пример, где среднее ожидаемое значение кубика будет 3, а шаг интервала 1:

let 🎲 = GKGaussianDistribution(randomSource: GKRandomSource(),
                                  mean: 3,
                                  deviation: 1)
(1...10).forEach { _ in print(🎲.nextInt()) }
// 2 3 3 3 2 2 3 4 2 2

В итоге получается, что около 68% сгенерированных чисел находятся в пределах одного отклонения от значения mean, 95% — в пределах 2 отклонений и почти 100% — в пределах 3 отклонений.

  • GKShuffledDistribution — генератор чисел, которые равномерно распределены по множеству выборок, но где короткие последовательности схожих значений исключены. Таким образом, если у нас будет указана генерация чисел от 1 до 5, то значение 5 выпадет во второй раз только после того, как все остальные числа от 1 до 4 точно так же выпадут по одному разу. Чаще всего подобную реализацию мы можем встретить в плей-листах современных аудиоплееров.
// Альтернативная инициализация диапазона чисел как у 6 гранного кубика
let 🎲 = GKShuffledDistribution.d6()
(1...7).forEach { _ in print(🎲.nextInt()) }  // Бросаем кубик 7 раз
// 4 5 3 1 2 6 4

Как можно видеть, здесь значение грани с числом 4 повторяется только после того, как выпадут все остальные значения.

Что интересно, метод shuffle()распределения элементов в массиве, который был добавлен в Swift только в версии 4.2, все это время был доступен в GameplayKit Randomization еще с iOS 9: arrayByShufflingObjects(in:). Работают они, естественно, на одном алгоритме Фишера — Йетса. Но основное отличие между ними только в том, что GameplayKit возвращает новый массив, в то время как реализация в Swift перемешивает оригинальный.

Контроль последовательности рандома

Некоторые показанные мною примеры генерировали значения с использованием конкретного алгоритма и указанным способом распределения, но при этом можно еще влиять на последовательность этих случайных чисел. В итоге получается, что этот рандом будет не таким уж и рандомным :)

Это может понадобиться, когда необходимо сделать одинаковую последовательность рандома на разных платформах или когда тестировщикам требуется повторить определенную последовательность. Все показанные мною GKRandomSource-классы (кроме базового) используют свойство seed, которое доступно для изменения. Зная значение seed, вы можете узнать всю последовательность рандома.

let seed: UInt64 = 123
let randomSource1 = GKMersenneTwisterRandomSource(seed: seed)
let 🎲1 = GKRandomDistribution.d6()
(1...7).forEach { _ in print(🎲1.nextInt()) }
// 6 2 5 3 2 3 6
 
let randomSource2 = GKMersenneTwisterRandomSource(seed: seed)
let 🎲2 = GKRandomDistribution.d6()
(1...7).forEach { _ in print(🎲2.nextInt()) }
// 6 2 5 3 2 3 6

State Machine

В iOS уже давно была реализована State Machine, которую вполне можно применять, даже в обычных UIKit-проектах. И при этом не потребуется использовать Rx, NotificationCenter, OperationQueue или создавать огромные Enum’s.

State Machine в GameplayKit имеет простой интерфейс и состоит всего из 2 классов:

  • GKState — абстрактный класс, от которого мы наследуемся, чтобы создать отдельный объект конкретного состояния. Каждый такой класс определяет новое другое State-состояние, в которое он можете перейти.
  • GKStateMachine — сама State-машина, содержащая в себе объекты состояний, которые наследуются от GKState.

Создаем свою State Machine

В качестве примера использования UIKit в приложении я покажу, как это можно применить, например при загрузке какого-либо файла на сервер.

Всего будет 3 состояния: Uploading, Success, Failure.

Uploading State

final class UploadingDataState: GKState {
    private let viewController: UploadViewController
    init(_ viewController: UploadViewController) {
        self.viewController = viewController
    }
    override func isValidNextState(_ stateClass: AnyClass) -> Bool {
        // Здесь мы указываем, каким может быть следующий State
        return stateClass == SuccessfulState.self ||
            stateClass ==  FailureState.self
    }
 
// Метод который вызывается когда State Machine успешно перешла к этому состоянию
    override func didEnter(from previousState: GKState?) {
        // отображаем анимацию загрузки пока находимся в этом состоянии
        viewController.activityIndicator.startAnimating()
        
        // пример вызова какой-то реализации API запроса 
        API.fetchData { result in
            switch result {
            case .success:
                stateMachine?.enter(SuccessfulState.self)
            case .failure:
                stateMachine?.enter(FailureState.self)
            }
        }
    }
 
// Метод который вызывается когда State Machine переходит к другому состоянию
    override func willExit(to nextState: GKState) {
        // убираем анимацию загрузки когда покидаем состояние
        viewController.activityIndicator.stopAnimating()
    }
}

Successful and Failure State

final class SuccessfulState: GKState {
    private let viewController: UploadViewController
    init(_ viewController: UploadViewController) {
        self.viewController = viewController
    }
    override func isValidNextState(_ stateClass: AnyClass) -> Bool {
        return stateClass == UploadingDataState.self
    }
    override func didEnter(from previousState: GKState?) {
// Действия которые необходимо сделать когда успешно получили данные
    }
    
    override func willExit(to nextState: GKState) {
// Действия когда закончилось действие этого состояния
    }
}
 
final class FailureState: GKState {
 
    private let viewController: UploadViewController
    
    init(_ viewController: UploadViewController) {
        self.viewController = viewController
    }
 
    override func isValidNextState(_ stateClass: AnyClass) -> Bool {
        return stateClass == UploadingDataState.self
    }
    override func didEnter(from previousState: GKState?) {
// Действия которые необходимо сделать когда не удалось получить данные
    }
    
    override func willExit(to nextState: GKState) {
// Действия когда закончилось действие этого состояния
    }
}

В итоге получилась такая простая схема:

Чтобы запустить все эти состояния, достаточно инициализировать GKStateMachine и передать туда все созданные State-классы.

final class UploadViewController: UIViewController {
    @IBOutlet private(set) var activityIndicator: UIActivityIndicatorView!
    override func viewDidLoad() {
        super.viewDidLoad()
        let uploadingDataState = UploadingDataState(self)
        let successfulState = SuccessfulState(self)
        let failureState = FailureState(self)
        let stateMachine = GKStateMachine(states:
            [uploadingDataState, successfulState, failureState])
        // Сразу запускаем Uploading State
        stateMachine.enter(UploadingDataState.self)
    }
}

После запуска в UploadingDataState будет вызван метод didEnter(from:), активирован activityIndicator и отправлен запрос на сервер. В зависимости от ответа с сервера будет вызван переход к следующему состоянию, где мы уже сможем реализовать какую-либо другую логику. К примеру, можно будет легко написать реализацию, чтобы из состояния Failure мы вернулись в Uploading и повторили операцию. Также можно создать еще больше состояний, которые могли бы делать другие операции перед успешной загрузкой или после, например закешировать ее в файловой системе или сделать предварительно компрессию, прежде чем отправить на сервер. Таким образом, это может быть альтернативным вариантом, чтобы создать хорошую последовательность действий, которые будут существовать как отдельные классы, и тем самым избежать Callback Hell’a.

Посмотреть пример, предлагаемый Apple по применению GKStateMachine в виде игры, можно в архиве: Dispenser.

Заключение

У самого GameplayKit около десятка инструментов, которые помогают работать со SpriteKit. Но только некоторые из них могут пригодиться при разработке на UIKit. Здесь я рассмотрел те, которые использую чаще всего в разработке неигровых приложений. Конечно, большая часть статьи была посвящена системе рандома, потому что с ней мне чаще всего приходится иметь дело. Но дополнительно это хороший инструмент, который позволяет делать примитивно простую рутину с очень удобочитаемым кодом и минимальным интерфейсом, без использования огромного количества математических формул и магических чисел в своих собственных рандом-методах.

Если же вам интересно, как можно задействовать большую часть инструментов GameplayKit, то рекомендую посмотреть WWDC 2015 session 609, Deeper into GameplayKit with DemoBots.

Исходный код проекта, показанного на WWDC, вы может взять в Documentation Archiveили у меня в репозитории, где код полностью сконвертирован до Swift 5.

Як правильно поїдати чуже печиво: GDPR-аспект

$
0
0

Я Лідія Климків, старший юрист практики захисту персональних даних Axon Partners. І на жаль, зараз ми не будемо про «лизни, покрути, булькни в молоко». Я розповім про файли кукі та про те, як правильно одержувати згоду користувачів на їх установлення та оброблення зібраної ними інформації. Ця стаття буде цікавою тим, хто пригадує свій біль від порад юриста щодо їхнього кукі-банеру, а також тим, хто взагалі не здогадувався, що до цього банера можуть бути якісь серйозні правові вимоги.

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

Чому? Тому що юристи-GDPRники знають, як важко буває переконувати клієнта:

«Так, потрібно, щоб користувачі погодилися на використання кукі!»
«Так, така згода має бути надана ПЕРЕД установленням файлів кукі на комп’ютер користувача!»
«Ні, недостатньо лише дати знати, що кукі просто збираються».

І ще ж треба відбиватися від слушних зауважень клієнта про те, що «інші ж компанії такий „дикий“ банер, як ви радите, не публікують!».

Слава горішкам, авторитетний орган із захисту персональних даних у Великій Британії Information Commissioner’s Office (ICO) чи не вперше кинув світло на ці чутливі питання й додав горе-юристам трохи впевненості, яку вони часто втрачали, побачивши подив клієнта на рекомендації перебудувати звичний процес використовування кукі.

Розберімося в тому, які здогади юристів підтвердив ICO у своїх рекомендаціях.

Що таке кукі?

Зараз для тих, хто не в темі або ж призабув головних героїв цієї негастрономічної статті, я наведу речення з Privacy Policy, яке GDPRники нашої компанії можуть на автоматі пробубоніти, коли б раптом хтось розбудив їх посеред ночі та запитав про те, що таке кукі.

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

Бувають наполегливі кукі (такий переклад ґуґл-транслейту дуже влучно передає суть їхньої дії) — «persistent cookies», що зберігаються на комп’ютері користувача кілька хвилин, годин або днів і для використання яких майже завжди потрібна згода користувача.

Бувають також сесійні кукі («session cookies»), що видаляються, коли користувач закриває свій браузер.

Бувають кукі, які встановлює сам власник веб-сайту, а бувають такі, що належать третім особам і якими наш власник просто нашпиговує свій веб-сайт (для реклами, збирання аналітики, безпеки тощо). Наприклад, кукі player і vuid, що уможливлюють Vimeo одержувати інформацію про те, скільки часу користувач переглядав відос).

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

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

А можна без тої згоди якось обійтися?

Загальне правило надавання згоди для встановлення кукі звучить так: згода потрібна тільки тоді, коли збираються кукі, що не є на 100% обов’язковими для функціонування сервісу. Для тих кукі, які а) є необхідними для технічної мети передання інформації електронними мережами та б) є життєво важливими для функціонування сервісу, попередня згода на встановлення не потрібна.

Щоб використати підставу пункту а), треба, щоб передання інформації було неможливим без використання таких кукі.

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

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

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

Багато популярних онлайн-видань мають функцію залишання коментарів під статтями. Так, під актуальними статтями «Української правди» або The Guardian можуть розвинутися справжні холівари, а деякі не менш поважні видання не надають своїм читачам можливості коментувати статті (гляньте на The New Yorker).

Як гадаєте, можливість коментувати матеріал є необхідним компонентом інформаційної послуги, що її надає онлайн-видання, чи ні?

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

Аналітичні кукі

Окреме питання становлять аналітичні кукі (наприклад, ґуґлівські Universal Analytics Cookies _ga,_gali,_gat,_gid). Вони не є необхідними для надавання будь-яких інформаційних послуг, а мають лише допоміжне значення. Такі кукі показують власникові кількість відвідувачів; частини та вкладки сайту, що їх найбільше відвідують користувачі; час, протягом якого відвідувачі залипають на сайті. Якщо ж обробка інформації, що збирається через такі кукі, має низький рівень ризику для користувачів і якщо такі кукі не є кукі третіх осіб, то згоду одержувати не потрібно.

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

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

Форма згоди

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

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

Тобто для того, щоб правомірно використовувати інформацію, яку збирають кукі, треба:

  • повідомити користувача, які саме кукі встановлюються та для чого;
  • одержати згоду на їх установлення (якщо вони не підпадають під визначення тих кукі, згода на встановлення яких не потрібна).

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

NamePurpose and DescriptionLifespan
_hjIncludedInSampleSession-based cookie set to let Hotjar know whether that visitor is included in the sample which is used to generate funnelsExpires in 365 days

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

І ніяких там наперед проставлених галочок! Але про це правило ви вже, мабуть, знаєте.

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

Якщо ж він може працювати без деяких з них, треба дати змогу кукі-панікерові відмовитися від тих, від яких можна відмовитися без шкоди для функціонування самого сервісу (як з технічного боку, так і з боку надавання послуги). Найзручніше це робити через відсилання на окрему сторінку з описом необов’язкових кукі, від кожного з яких можна відмовитися. Отут уже варто ті 50 видів описати окремо.

Якщо ви прихильник мінімалізму та ергономічності сайту, вас також чекає дизайн-розчарування: банер з куками кислотно-зеленого кольору з додаванням миготіння — «самоє оно» в очах творців GDPR. Маленька стильна кнопочка у кутку сторінки не підходить, банер має бути помітним для користувача, — це вимога GDPR.

Разом з тим, творці GDPR та захисники privacy знають про проблему з банерами та про те, що, ніде правди діти, дуже мало хто робить ці банери «як має бути». З одного боку, їх зв’язують вимоги захисту приватності, з іншого — потреби бізнесу, яким ці вимоги щодо кук точно як кістка в горлі. Триває обговорення нової ePrivacy Regulation, яка має детально врегулювати встановлення кук на пристроях користувачів та обробки отриманої від них інформації. Цей документ усі чекають як звільнення від тягаря невизначеності кукіз-банерів. Зокрема, у цьому регламенті «мужі й панни» європейського data protection задумуються, а чи не закинути м’яч на поле цих користувачів інтернету. І нехай це вже буде їхня відповідальність за уміння користуватися браузерами (ну і самих браузерів, які будуть думати, що робити, якщо їх зобов’яжуть надавати користувачеві зручненький доступ до панелі управління всіма видами необов’язкових кук). Можливіть видаляти куки або забороняти їх встановлення уже є, однак ePrivacy Regulation може зробити, наприклад, так, що Chrome буде пропонувати нам позначати галочки про певні види кук перед кожним його запуском, або ж встановить цю миготливу кислотно-зелену кнопку про налаштування кук десь на його панелі.

Що ж буде, якщо не заморочуватися над цим банером?

Поки вказане вище звільнення у вигляді ePrivacy Regulation не зійшло на бізнес (а воно уже не перший рік не приймається, а тільки обговорюється), відповідь залежить від декількох факторів:

  • Поширення на вас GDPR. Якщо компанія зареєстрована в ЄС або ж місце реєстрації не ЄС, але компанія пропонує свої товари чи послуги покупцям з ЄС, на таку компанію поширюється GDPR. Однак навіть у випадку, якщо ваша діяльність пов’язана з іншими юрисдикціями, варто перевіряти вимоги щодо збирання даних у кожній з них.
  • Вплив, який може мати витік даних. Ніхто з органів ЄС не буде надсилати формальну претензію в українську компанію, що працює з ринком ЄС, про те, що на її веб-сайті немає банера на збирання аналітичних кукі. Однак якщо буде витік даних, за якими можна буде ідентифікувати особу, то така претензія прийде.
  • Добросовісність. Навіть якщо вам надішлють лист на фірмовому бланку з органу захисту персональних даних, ваша швидка реакція та, наприклад, опублікування нового банера чи направлення всім користувачам інформації про витік з рекомендаціями, як діяти далі (якщо витік даних таки стався), може вас уберегти від штрафних санкцій або істотно зменшити розмір штрафу.

А який той розмір? Не хочеться прив’язувати 20 млн євро або 4% від річного обороту в статті про правильний банер для кукі, але саме такий верхній поріг відповідальності встановлює GDPR для неналежно одержаної згоди на оброблення даних. Звісно ж, такий штраф за поганий банер ніхто не встановлюватиме, а будуть братися до уваги чинники, наведені вище. Ну і варто згадати, що банер — це тільки верхівка айсберга всіх заходів, які покладає на контролера чи оброблювача даних GDPR.

А тепе-е-ер — нумо, усі зацікавлені, на сайт ICO, бо там для новоприбулих користувачів якраз і розміщено новий банер для кукі! І — о боги!  — банер не дає користуватися сайтом, допоки ти не зробиш свій вибір.

Энциклопедия увольнений: 8 неочевидных причин ухода программистов

$
0
0

Я Валерия Козлова, автор технологии EQ Boost, преподаватель LvBS и основатель компании Corporate EQ. В своей работе мне часто приходится обучать тому, как создавать синергию в команде. Используя один из методов наблюдения за неочевидными вещами в поисках lean-решений к продуктивности команд, я увидела: многие командные процессы, которые нам видны, на самом деле лишь верхушка айсберга. То, что определяет решения и результат, часто скрыто глубоко «под водой». Уход из команды ключевых сотрудников — хорошая иллюстрация этого явления. Некоторыми из таких случаев я хочу поделиться с вами.

IT — особая сфера, где на специалистов высокий спрос и найти работу сегодня не представляет сложности. Это позволяет программистам менять компании, не особенно разбираясь в причинах своего ухода. И напрасно, ведь если проблема ухода для вас самих не до конца ясна, то очень высока вероятность повторения ситуации на новом рабочем месте.

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

Иногда достаточно знать настоящую причину увольнения, чтобы понять, что лучшим решением будет остаться, изменив условия на рабочем месте. А вдруг работа, с которой ты решил уйти, — это работа мечты? И вдруг сотрудник, которого ты хочешь уволить, поможет тебе перевернуть мир? Надеюсь, кому-то этот материал будет полезен.

Иллюстрации Дарины Скульской

1. Ошибка лидера

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

Ключ к решению проблемы был скрыт в настоящей причине ухода, поэтому мы начали работу с ее поиска. Это было непросто. В итоге мы установили: он захотел уйти после слов собственника, которыми тот объяснил, почему предложение по улучшению продукта не будет принято: «Мы с ребятами подумали, что твое решение не подходит».

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

Если посмотреть на ситуацию через концепт эмоционального интеллекта, становятся видны пути ее решения. В данном случае было нарушено правило: никогда не ставьте под сомнение принадлежность к команде ее члена.

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

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

Этот кейс — один из примеров того, как лидер разваливает команду.

Рекомендация владельцу.Никогда не противопоставляйте одного из сотрудников команде, но, несмотря на сложности и не экономя на этом время, инициируйте обсуждение всеми членами команды.

2. Изменение культуры компании

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

Как это распознать? Недовольство таких сотрудников нарастает, и они начинают обсуждать это не только во время кофе-брейков, но и в перепалках, особенно когда не все идет гладко. Они кидают фразы вроде: «нас не слышат», «нас не хотят понимать», «нам уделяют мало внимания и времени», «мы не понимаем, что происходит», «мы так не привыкли» и т. д.

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

Рекомендация для собственников.На встрече один на один объясните разницу между культурами компаний семейного и корпоративного типов и предложите специалисту самостоятельно принять решение.

3. Тайные эмоции

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

Что это может быть? В течение 5 лет, проводя интервью с амбициозными успешными разработчиками-сеньорами на тему их увольнений, я отметила: перед уходом из компании у них происходил провал в виде неудачи на проекте (один или несколько подряд).

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

Рекомендация для топ-менеджеров и собственников.Стыд — эмоция сложная. Я исследовала ее около 15 лет у клиентов с разными ситуациями и в жизни, и в карьере. Чтобы не переживать стыд, мы подменяем его другой эмоцией. Об этом я писала ранее в своей книге «Технологія EQ Boost: як використовувати емоційний інтелект у бізнесі та житті». Знание этих защит и само предположение, что провал может вызывать стыд, помогут предвосхитить увольнение сотрудника, помочь ему и дать возможность переосмыслить свой провал (например, получив какой-то проект, где он может реабилитировать себя). И вместо того, чтобы отпускать прекрасного сотрудника, который может принести компании много пользы, можно изменить стратегию и поддержать его, помогая решить эту проблему. Дело в том, что стыд — настолько токсичная эмоция, что справиться с ней одному очень и очень трудно.

4. Отсутствие современных технологий

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

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

В чем же дело? Видимая и объясняемая самим разработчиком причина, что, дескать, технология устарела, на самом деле не соответствует действительности. Настоящая причина заключается в том, что ключевую роль играет самооценка того, кто находит решение проблемы в сложные моменты на проекте. И если он долго не подпитывал свою уверенность тем, что участвовал в проектах с новыми технологиями, в сложный момент он начнет сильно сомневаться в себе и вместо того, чтобы искать решение, предпочтет уйти или перестанет верить в себя. Таким образом, технология может быть устаревшей, но это не более чем маскировка для того, чтобы не признаваться самому себе в страхе, что «я не смогу решить стоящую передо мной задачу». Человек твердо в это верит, и переубедить его сложно.

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

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

5. Непривлекательный концепт создания рабочего места

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

Откуда берется ожидание, что IT-специалист удовлетворится плохими бытовыми условиями? Например, плохой вентиляцией, отсутствием гигиенических норм или даже эстетического оформления офиса. Все это — понятия адекватных условий труда. В наше время экономить на них и при этом рассчитывать на лояльность сотрудников — это все равно что предложить европейцу гостиницу без горячей воды и очень удивиться, что он этим недоволен.

Время работодателей, которые хотят экономить на условиях быта, уходит в прошлое: уровень жизни вырос.

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

6. Стагнация компании

На определенном этапе многие компании достигают своего предела по количеству людей и проектов, и выйти на другой уровень или объем у них не получается: они замирают, и какое-то время ничего не происходит. Один из примеров: несмотря на старания собственников, компания длительное время не получает крупных заказов и перебивается, условно говоря, с одного мелкого проекта на другой.

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

Рекомендация.Необходимые действия связаны с поисками новых возможностей в мышлении самого собственника. Это та точка, в которой нужно остановиться и изменить себя и свое поведение. Применять мышление для компании численностью 100 человек во время строительства компании в 1000 человек не эффективно. Собственники часто не осознают, что причина заключается именно в этом. Что мешает? Иногда — страх, что «не потяну». Иногда — отсутствие собственного ресурса при том же количестве часов в сутки, ведь надо успевать сделать больше, потому что компания растет.

Я называю этот отрезок развития компании развилкой, когда точкой приложения усилий собственника должен быть он сам и его мышление, а не бизнес-процессы. Быстрее всего поможет изменить мышление ментор или коуч, но можно использовать и альтернативные варианты: поговорить с другими собственниками, которые расскажут о подобном моменте в своем бизнесе, прослушать курсы, прочесть книги и т. д. Если этого не сделать, само по себе новое мышление не появится, и развитие бизнеса будет, как я это называю, горизонтальным. То есть усилия будут прикладываться постоянно, а прорыва при этом не будет. Мои клиенты называют это состоянием стеклянного потолка.

7. Разрыв видения собственника и его команды

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

В чем причина? Ведь собственнику кажется, что он создает привлекательные и более интересные в плане возможностей условия. Это не может не интересовать, не может не вызывать желания помочь, быть рядом, с полуслова поддерживая новую стратегию, о которой он столь много, долго и самозабвенно рассказывает. Но причина в том, что для поддержки движения в будущее мне, как топ-менеджеру и тем более как рядовому сотруднику, важно видеть лично мою точку на карте этого будущего. Именно мою, а не всей компании. Хоть и в рамках будущего компании, но мою личную точку. На пояснение этих деталей собственнику, который рассуждает о стратегии, не хватает времени, сил, и, главное, он не видит в этом необходимости, думая, что все имеют такой же уровень выживания в неопределенности, как и он.

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

  1. Обсуждение стратегии собственника с топами для ее лучшего понимания и формулирования.
  2. Помощь в поиске конкретной точки на карте будущего для каждого члена команды.

Именно это я называю преодолением разрыва между видением собственника и его команды.

Если адекватно соблюдать баланс этих двух контекстов в коммуникациях — обсуждение стратегии и поиск твоего места на карте будущего в компании, — сотрудники не уволятся.

8. Конфликт ценностей

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

В этот момент к проектному менеджеру «прилетает» от заказчика дополнительная задача. И он тихонько добрасывает ее в скоуп задач, считая, что это сэкономит время, потому что он «не хочет отвлекать ребят». Однако, когда сотрудники обнаруживают это, продуктивность падает, а ребята чувствуют себя оскорбленными. Менеджер сэкономил время на проговаривании и убеждении взять еще одну задачу, но заплатил за это потерей продуктивности всей команды, а также уходом одного сотрудника посреди проекта.

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

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

Подводя итог

Даже если причина, по которой талантливый разработчик решает уйти из компании, на первый взгляд выглядит очевидной, она может оказаться не настоящей. За ней могут скрываться другие, малозаметные, но намного более важные, настоящие причины увольнения. Иногда для наилучшего разрешения ситуации бывает достаточно найти эти причины.

Советы для начинающего Java-разработчика. Подготовка к собеседованию — часть 3

$
0
0

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

Алгоритмы

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

У каждого собеседующего есть свой список «удачных» задач для проверки способности последовательно и структурировано мыслить. Иногда достаточно абсурдных и мало применимых к реальным ситуациям. И если повеселивший многих вопрос из предыдущей части статьи про разницу BeanFactory и FactoryBean в спринге имеет хоть какой-то, пусть и отдаленный, практический смысл, то лично мне сложно понять смысл вопроса про палочку, которую мы разламываем в двух местах на три части, и поиск вероятности составления треугольника из этих частей. Но пути мышления собеседующих неисповедимы, поэтому будем по традиции отталкиваться от статистических данных по задаваемым вопросам.

Что спрашивают часто:

  • Что такое сложность алгоритма? Практический вариант: сравните сложность двух решений одной задачи.

Вопрос, без которого не обойдется ни одно собеседование, поэтому остановимся на нем немного подробнее. Важно помнить, что помимо сложности по времени выполнения есть также сложность по расходуемой памяти. И не забывайте спрашивать собеседующего, важна ли она в данном случае. Это дает условный плюс в корзину претендента. А также то, что основных обозначений сложности, как функции зависимости объёма вычислений от размера входных данных, бывает несколько (tilde, big-O, big-theta, big-omega). Но спрашивают чаще всего либо про средний случай, либо про верхнюю границу выполнения — расчет для худшего случая. И какой вариант интересует собеседующего тоже нужно уточнять сразу.

  • Какие знаете сортировки, которые используются в стандартных механизмах Java?

Вопрос про QuickSort и TimSort, и их применение. Быструю сортировку желательно уметь реализовать в простом варианте для саморазвития.

  • Бинарный поиск. Мастхэв, элементарный алгоритм, много кто спрашивает. Сложность знать обязательно, так же как и уметь объяснить, почему она такая.
  • Структуры данных в Java, которые умеют сортировать под капотом. Для чего чаще всего используются? Что внутри, как происходит сортировка? При каком условии объекты, положенные внутрь, будут отсортированы правильно?
  • Почему иногда выбор худшей по сложности сортировки выгоднее?

С целью проверить общеобразовательный уровень могут спросить про двоичное дерево, двоичную кучу, графы. В 90% случаев всегда поверхностно: что это такое, где используются, какие бывают. Также подозрительно часто дают задачи на сортировку подсчетом.

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

Паттерны проектирования

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

Спрашивать любят про разделение паттернов на категории, по каждой из которых обычно просят назвать 2-3известных паттерна и рассказать о них. Есть сайтдля изучения основ на абстрактных примерах. Я не очень хорошо отношусь к абстрактным примерам после своей первой книги Head First Design Patterns, но refactoring guru неплохо поясняет теоретические аспекты и необходимость использования того или иного шаблона. Практику же можно параллельно просматривать вот здесь. Хороший ресурс для добавления в закладки и постепенного изучения после трудоустройства.

Если сроки поджимают, то вот небольшой список на изучение по каждой категории:

  • порождающие: фабричный метод, абстрактная фабрика, билдер, синглтон;
  • структурные: фасад, прокси, декоратор;
  • поведенческие: шаблонный метод, наблюдатель, стратегия;
  • дополнительно (но не менее важно): DAO, repository, MVC.

Из GRASP-паттернов можно ознакомиться с Low Coupling и High Cohesion как основополагающими принципами. Тем более, что в отличие от GoF, их можно интуитивно понять после первого же прочтения.

Системы контроля версий

Изучение VCS (на примере Git) очень рекомендую делать на практике по принципу «прочитал — выполнил — проверил результат». На первых порах достаточно будет выучить список основных команд и для чего они нужны: push (с опциями), pull, fetch, commit, merge, rebase, squash, revert. После проверки на практике вопросы вроде «как отменить несколько коммитов» или «как собрать несколько коммитов в один» должны перестать беспокоить. Хотя последние спрашивают уже от уровня крепкого джуна и выше. Тогда же спросят про Git workflow или жизненный цикл разработки. Недоджуну достаточно понимать общие принципы совместной работы с кодом и уметь подтягивать чужие изменения, коммитить свои и делать merge. Остальное рекомендую изучать уже после трудоустройства.

Сборка проекта

Самые популярные сборщики сегодня: Maven и Gradle. Вторым воспользоваться на реальном проекте мне так и не довелось, поэтому все дальнейшее будет относиться к мавену.

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

Что хотят услышать на собеседовании:

  • Что вообще такое процесс сборки проекта на Java? Для чего нужна сборка? Что имеем на выходе?
  • За что отвечает pom.xml и какая у него структура?
  • Как организована сборка многомодульных проектов?
  • Назовите стандартные жизненные циклы мавена и несколько фаз, которые к ним относятся.
  • Как мавен решает проблемы с транзитивными зависимостями?

Веб-технологии

Java, как язык для разработки server-side приложений, не может быть отделен от веба. Поэтому основы веб-технологий спросят всегда:

  • Что такое HTTP? какие у него альтернативы?
  • Какие есть HTTP-запросы? (назвать 4 основных будет достаточно) Какая между ними разница? Любимый вопрос у всех: чем GET отличается от POST?
  • Что такое REST? какие особенности RESTful-сервисов знаете? Про SOAP сегодня практически не спрашивают.
  • Назовите пару контейнеров для запуска веб-приложений на Java. Что они из себя представляют? Для сравнения можно рассмотреть популярные Tomcat и Jetty.

Тестирование

Требования к тестированию очень сильно отличаются от проекта к проекту. Где-то разделяют принципы TDD, где-то выделяют время только на минимальное покрытие тестами в силу приоритетов по другим задачам. Бизнесу виднее (почти сарказм). Знать заранее, как будет на следующем вашем проекте нельзя, поэтому сфокусируемся на базовых моментах. Самые распространенные для тестирования фреймворки на сегодня: JUnit для юнит-тестов и Mockito для имплементации заглушек. Оба элементарно подключаются к проекту и предельно просты в вопросе понимания необходимости их использования.

Что часто спрашивают:

  • Какие виды тестирования знаете и чем они отличаются? Разработчику достаточно назвать модульное, интеграционное и функциональное. Если назовете нагрузочное, то необходимо заранее посмотреть в сторону такого инструмента, как JMeter, чтобы было что отвечать на дополнительные вопросы без серьезного погружения в тему.
  • Основные аннотации в JUnit (test, before, after, beforeClass, afterClass, ignore) и их особенности.
  • Чем отличается Mock от Spy в мокито? Приведите пример использования первого и второго (крепкий джун+).
  • Что, если ожидаем от метода выброшенного исключения? Что, если метод не должен выполняться дольше определенного количества времени?
  • Какие модификаторы доступа у тестовых методов в JUnit?

У крепкого джуна могут также спросить про параметризированное/категоризированное тестирование (@RunWith аннотация). Или про нюансы тестирования методов, которые обращаются к БД.

Логирование

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

ALLЛогируются все сообщения
TRACEМелкое сообщение при отладке
DEBUGВажные сообщения при отладке
INFOПросто сообщение
WARNПредупреждение
ERRORОшибка
FATALФатальная ошибка

Если выставить уровень логирования в WARN, то все менее важные, чем WARN сообщения, будут отброшены (TRACE, DEBUG, INFO). Если нужно настроить, чтобы какие-то логи писались в файл, настраивается с помощью Appenders.

Дебаг

К сожалению, огромное количество претендентов на позицию джуна сильно недооценивают значимость такого инструмента разработчика, как отладчик. А уровень владения дебагом у среднестатистического стажера лежит в плоскости «вы знаете, я обычно просто добавляю System.out, чтобы посмотреть значение переменной». И очень мало, где пишут, что джун по факту проводит за отладкой и поиском ошибок не намного меньше времени, чем за разработкой. Отсюда рекомендация: обязательно разобраться в дебаге.

На примере IntelliJ IDEA: знать, какие функции в режиме отладки выполняют F7, F8, F9. Как посмотреть содержимое обрабатываемой коллекции в конкретный момент выполнения. Как изменить значение, которое передается в метод прямо в момент отладки. Попробуйте все это на практике: сложного ничего нет, а практической пользы очень много.

Методологии разработки

Так как работать разработчику приходится в команде, то и взаимодействие внутри нее всегда организовано в виде конкретного системного подхода. Сегодня балом правит Agile — набор гибких принципов, на основе которых строятся популярные методологии. Достаточно знать две самых распространенных из них: Scrum и Kanban.

Scrum основан на делении всего процесса на итерации, где в конце каждой команда готова предоставить результирующую демо-версию продукта с новым готовым функционалом.

У Kanban в основе визуализация процесса выполнения задач в виде трех колонок таблицы: To do, Doing, Done. Основная идея — уменьшать количество запланированных задач (куда уж банальнее) и постепенно перемещать их из колонки «To do» в «Done». Очень подходит для проектов, находящихся в стадии поддержки, где основной функционал уже разработан и остались минимальные доработки и багфиксинг.

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

Подготовка и процесс собеседования

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

По моему личному опыту, на позицию Middle они тоже не особо отличаются по сложности. Главное — понимать, что мидла от джуна отличает количество кода, который он сам писал и видел. Мидл задает на порядок меньше вопросов в процессе работы, быстрее «вкатывается» в проект, быстрее разбирается во внутренних зависимостях. Если вы считаете, что подучите чуть больше и можно попробовать себя на позицию мидла, немного приукрасив опыт в резюме, то это не так. И даже если получится пройти собеседование, то испытательный срок все покажет как есть. Помимо подтягивания теоретических навыков, на позицию мидла «с нуля» (с точки зрения опыта продакшена) можно прыгнуть только в случае работы над опенсорс проектами и самостоятельного изучения практических нюансов. Придется пережить этап, когда каждый первый ваш коммит в опенсорс будут отклонять как некачественный или незначительный.

На Junior-позицию очень часто дают тестовые задания. Чаще всего, чтобы увидеть, как в вашем коде будет организовано взаимодействие между классами и какая логика куда будет вынесена. И уже потом посмотрят на выполнение программой требуемых функций. Для некоторых задач не лишним также будет наличие тестов.

На джава-форумах и каналах иногда просят оценить структуру готового домашнего проекта, чтобы понять, насколько все плохо/хорошо. Я считаю это хорошим подходом. Также неплохая книга для понимания таких основ — Thinking in JavaЭккеля.

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

Один из качественных советов, который я получил на начальном этапе своей карьеры — самому вести разговор в ту тему, в которой разбираешься. И не давать тем самым повод собеседующему постоянно задавать ритм и направление разговора.

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

На вопросы предпочтительно давать развернутые ответы, так как проверяются также навыки коммуникации. Чаще всего, перед вами сидит человек, с которым вы будете работать в одной команде. И общаться, и отвечать уже на похожие вопросы, но по проекту. Этот человек присматривается, как это будет выглядеть на ежедневной основе. Поэтому данный пункт достаточно важен.

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

Если после собеседования у вас остались вопросы, то обязательно их задавайте. Например, на какой стадии разработки находится проект в данный момент? Какие технологии стоит подтянуть до выхода на работу? У эйчара можно спросить про условия отпусков и больничных, предполагаемый карьерный рост в компании, через какой период происходит пересмотр зарплаты. Естественно, будучи джуном, сильно торговаться на этот счет не получится, но по ответам можно понять отношение компании к своим работникам и принять правильный выбор.

В завершение

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

Дорогу осилит идущий. Удачи!


При возникновении вопросов, пообщаться со мной можно в телеграме: @liohamitec

14 типов менеджеров, которые бесят разработчиков

$
0
0

Статья написана в соавторстве с Дмитрием Ховричеми Мэри Ротарь, Co-Founder IAMPM.

Недавно мы с Дмитрием проводили вебинар о том, что же бесит разработчиков в проектных менеджерах. В статье расскажем реальные истории из своей практики.

Сперва пару слов о нас. Я Front-end Developer в DataArt, в профессии 7+ лет. Дмитрий Ховрич также больше 5 лет работает в коммерческой Front-end разработке.

Дисклеймер:проектные менеджеры нужны, важны, бывают очень крутыми ребятами, и без них работать было бы тяжело, а порой и невозможно. Но за 12 лет суммарного опыта у нас накопилась достаточно негативных кейсов, о которых сегодня и поговорим. Истории, написанные от первого лица, случались с кем-то из нас в далеком (или не очень) прошлом.

Наши супергерои — это не конкретные люди, а собирательные образы, воплощение деструктивных моделей поведения, которые присущи некоторым проектным менеджерам. Иногда в своем PM вы можете узнать сразу нескольких антигероев из статьи — или, если повезет, ни одного. В общем, все персонажи вымышлены, а совпадения случайны...

1. Митинг-мэн

Митинг-мэн — это менеджер, вся жизнь которого посвящена митингам. Он когда-то прочитал, что встречи помогают команде работать эффективнее, и возвел эту рекомендацию в абсолют.

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

Как-то работал с таким персонажем, и поводы для встреч иногда бывали просто абсурдными.

Утром мы собрались, обсудили на стендапе задачи на день, выпили кофе, пообщались, сели за работу — и спустя час-два получаем инвайт на митинг. На митинге спрашивают: «Ну, что ты успел сделать? А что тебе мешало сделать больше? Может, тебе что-то нужно от коллег?» Так и хочется сказать: «Ну если нужно, то я подойду к коллеге и спрошу!» Если каждого в команде 5+ человек поспрашивать на митинге — уже, считай, минус час-полтора времени, которое можно было потратить на разработку.

Бывали случаи, когда кто-то работал удаленно по причине плохого самочувствия. И даже если конкретно сейчас вопросов к коллеге не было, а его присутствие на митинге было излишне, такой менеджер все равно дозванивался до человека и заставлял зайти в скайп и включить камеру: «Чтобы мы тебя видели!» Это выглядит немного странно, но это тоже особенность Митинг-мэна — достать даже мертвого из могилы и добавить его на колл.

Еще один особый талант Митинг-мэна — не прерывать в процессе командной встречи диалог двоих разработчиков, которые решили углубиться в свои проблемы. Это же удлиняет митинг, ура! Нужно больше митингов богу митингов!

2. Инкогнито

Менеджер по факту не особо вникает в процессы. Общение идет напрямую по схеме «разработчик-клиент». Появляется Инкогнито, только когда какие-то вопросы решились в обход менеджера по причине его отсутствия на проекте или пинга длиною в вечность.

Я работал в проектах, где менеджер — что есть, что нет. Обычно это выглядит так: тебя знакомят с клиентом и менеджером, показывают все инструменты, дают доступы, все хорошо. Когда начинается работа, ты понимаешь, что клиент, как правило, пишет тебе напрямую. Ты, если нужно что-либо спросить, спрашиваешь клиента, потому что PM обязательно пропадает на три часа и появляется, когда ответ уже неактуален, потому что вы с клиентом успели обсудить все детали.

В итоге смысл феномена проектного менеджмента проявляется, только если на проекте что-то идет совсем не по плану — часто как раз из-за невключенности PM. В этом случае Инкогнито еще и недоумевает, почему с ним никто не советовался раньше. Да потому что работа стоит, тебя нет на связи, а ее надо делать! При знакомстве с менеджерами типа Инкогнито возникает вопрос: зачем они вообще нужны, если можно назначить главным лида, и все будет хорошо?

3. ХЗ-мэн

Это менеджер, который не знает, как правильно формулировать задачи и какие для них существуют критерии оценки. Под формулировкой задачи мы подразумеваем создание таска в Jira (или другой системе контроля задач) и его грамотное описание.

Практически каждый разработчик сталкивался с таской, которая состоит из одного title, например, «implement login». Смотришь на этот title и не понимаешь: что вообще нужно сделать?! Менеджер подразумевал фронтенд, бэкенд или вообще дизайн? Работа над такими задачами — это гадание по хрустальному шару.

К сожалению, ХЗ-мэны достаточно распространены. Поэтому, чтобы разработчики не впадали в ступор, когда они видят задачу, существуют такие проверенные временем подходы, как написание Acceptance Criteria и Definition of Done.

Кто-то может сказать, что DoD — это общие требования к качеству, а не обязанность менеджера, и тем не менее, позаботиться о том, чтобы этот список DoD был хотя бы прикреплен к задаче и формализован, а разработчик об этом попросту не забыл — все-таки должен PM. Если в компании DoD-a нет, PM-у стоит позаботиться об его организации. Менеджер может, как минимум, пнуть самого умного разработчика, чтобы он это сделал. Как бы то ни было, DoD на проекте должен быть, иначе работать сложно.

4. Задрот-мэн

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

Есть проект, довольно крупное мобильное приложение (количество пользователей исчисляется сотнями тысяч). Разработка ведется по Scrum: стандартные двухнедельные спринты, планирование, эстимейты — все, как положено в лучших домах Лондона и Парижа.

Внезапно в середине спринта ломается логин. Заказчик прибегает к менеджеру: «У меня 100К пользователей, и никто не может войти в систему, что делать? Давайте, ребята, почините». Менеджер: «У нас скрам! Все распланировано, мы не можем просто так взять и починить логин! Если ты хочешь, чтобы мы его починили, то давай сперва сядем, посмотрим бэклог, выберем задачу, которую выкинем из этого спринта, а вместо нее поставим задачу по фиксу логина».

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

Вывод: не стоит безоговорочно и неукоснительно следовать всем постулатам одной методологии как законам (особенно если вы поняли ее слишком буквально). Любая методология должна учитывать ситуации, когда что-то пойдет не так, и придется принимать быстрое решение.

5. Эстимейт-мэн

Разновидность Задрот-мэна. Такой менеджер просит эстимировать каждый чих и очень болезненно реагирует на любые отступления от оригинального эстимейта.

Чаще всего эти ребята встречаются на проектах с жесткой почасовой оплатой, где каждая таска должна быть оценена, потому что по этому количеству времени позже выставляется счет. Но проблема в том, что процесс разработки проекта (особенно большого и сложного), трудно прогнозируем, когда в каждой команде есть по N разработчиков (хотя бы пять фронтов, пять бэкендов и пара дизайнеров).

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

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

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

6. А давайте так-мэн

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

Всю прелесть работы с таким персонажем испытал на своей шкуре. Я тогда был новичком в компании и выполнял одну из своих первых тасок. Менеджер подошел ко мне и попросил показать конкретно в коде, что я сделал. Я показал код и объяснил, что мне нужно было создать еще одну таблицу в базе данных для хранения этих новых сущностей. Он мне говорит: «А почему ты создал новую таблицу? У нас же есть другая таблица». Я ответил, мол, эта таблица не подходит, потому что здесь немножко разные сущности. Менеджер начал утверждать, что сущности одинаковые. Спорили полчаса, пока я его не переубедил. Зачем я тратил свое время на этот спор, так и останется загадкой.

У моего товарища была ситуация, когда они полгода писали CRM-ку на Angular, в проекте были некоторые проблемы, которые менеджер планировал решить переписыванием всего на Vue через полгода разработки! Как это может решить проблему — непонятно, но команда была «в восторге».

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

У моих коллег был опыт с адекватным менеджером. Разработчики стояли перед выбором, как развивать проект, написанный на старом Angular. Пришел новый PM, предыдущий опыт которого был с командой, которая использовала Vue, поэтому он предложил: «Ребята, у нас в прошлой команде достаточно неплохо работал Vue. Давайте, может быть, тоже попробуем?» Общение шло в дружеском ключе, своего мнения он не навязывал. Разработчики подумали, попробовали и решили продолжать проект на Vue.

7. Криворукий джира-мэн

Практически в любом проекте есть какой-то таск-трекер (Jira, Trello), который за счет определенных инструментов позволяет выстроить flow разработки, тестирования и учета задач.

Трекер криворукого джира-мэна — один большой todo-шник с кучей тасок. Они не настроены: ни фильтров, ни категорий — ничего. Ты просто пытаешься хоть что-то откопать, зарываясь в эту кучу... тасок.

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

8. Да, конечно-мэн

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

Рано или поздно заказчик может сесть на шею и свесить ножки. Если он попадает на такого менеджера — ищите другой проект. Лечится проблема максимально подробным планированием задач.

9. Таска-мэн

Менеджер, который не в состоянии оценить сложность задачи и время на ее выполнение, а в качестве бонуса неравномерно распределяет задачи в рамках команды.

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

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

10. Додо-мэн

Однажды я работал в компании, у которой есть свой офлайн-бизнес, допустим, по производству тапочек. В один прекрасный момент они решают построить IT-отдел. Раз есть отдел — нужен РМ. Руководство чешет репу и решает назначить Васю, который до этого был начальником в ООО «Рога и копыта».

Вася проект не менеджил от слова «совсем». Не потому, что он — плохой человек, а оттого, что в душе не ведал, что такое IT и как с ним быть. Так и «работали» до момента, когда мне надоело, что человек не понимает, где он, что здесь делает, и фактически мешает нашей работе. Я напечатал на листике пункты, по которым мы принимаем в работу задачи, положил Васе на стол и ушел. После этого у нас с ним состоялся непродолжительный диалог-разъяснение содержимого листика. Благо, Вася понимал, что ни черта не разбирался в разработке, и после беседы решил алгоритмом воспользоваться. Но такие «менеджеры» сильно демотивируют, и это приводит к утечке кадров.

11. Excel-мэн

Историю рассказал мой товарищ, который работал в достаточно крупной компании со своим внутренним IT-отделом. Программисты разрабатывали для компании интернет-магазин, внутренние CRM-ки и прочие программные штуки, которые упрощают продажу и дистрибуцию товара.

Был у них в команде PM, который в силу каких-то своих убеждений не мог пользоваться Jira, Trello и другими таск-трекерами. Он создал Excel-ку, в которой были расписаны задачи и исполнители. А вместо того чтобы в Jira перенести таску в колонку «In Progress», нужно было подойти к менеджеру и попросить его внести изменения в таблицу.

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

12. Копипаст-мэн

Менеджер не заморачивается с описанием стори/тасок. Просто копирует текст от клиента из письма/мессенджера и вставляет в описание в Jira. Разработчики сами разберутся.

Одна из ролей менеджера — услышать клиента и привести услышанное в понятный для разработчиков вид, а этот менеджер не проверяет текст на понятность, выполнимость и отсутствие бреда. И конечно, снова никаких тебе acceptance criteria.

13. Контроль-фрик

В отличие от Эстимейт-мэна, заморачивается на предмет того, на что вообще разработчик тратит время.

Я сталкивался с менеджером, который просил в отдельной таске фиксировать время, потраченное на code review. С одной стороны, его можно понять. С другой стороны, мне вообще не хочется запоминать, сколько времени я потратил на код ревью, а сколько — на саму задачу, и фиксировать все это в разные тикеты. Это совсем не воодушевляет.

Еще один пример не настроенных от слова «совсем» процессов — когда ребята неделю работали, а в пятницу трекали четыре часа рабочего времени в специальную таску, которая так и называлась: «Трекинг».

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

14. Потому что-мэн

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

Реальный кейс: в компанию прособеседовали семерых кандидатов. В результате разработчики выдвигают свою кандидатуру, которая, по их мнению, больше всего подходит на указанную должность. А в один прекрасный момент менеджер непонятно почему (бюджет/диалог с клиентом/интуиция) предлагает взять другого. Почему? Потому что!

Чем менеджер руководствовался, предлагая такое решение — большой вопрос. В итоге кандидат PM-а не справился, так как просто не вытягивал этот уровень задач. Пришлось продолжить поиски.

Если есть объективные причины: «У нас ограниченный бюджет, нужно взять хоть кого-то» — это нормально. Но что мешает их озвучить команде — большой вопрос.

Я сталкивался и с другой, весьма специфической ситуацией, где лид-разработчик уходил с проекта, и ему долго не могли найти замену. Когда лиду оставалось работать пару дней, появился кандидат, который в принципе подходил на его роль. Не идеально, но подходил. А других не было. У менеджера был напряженный график: надо было зарелизить много фич, и сидеть без разработчика он себе позволить не мог. В этом кейсе менеджер вполне оправданно стал настаивать на замене, и все его поняли.

В завершение

Профессионализм еще никто не отменял: как со стороны разработчиков (привет, кривые эстимейты, после которых за овертаймы ты получаешь бесценный опыт вместо денег), так и со стороны менеджмента. На каждого хорошего специалиста найдется несколько антигероев, которые «посвятили свою жизнь скрамгайду» и вроде как делают все правильно... Но на деле оказываются глобальной катастрофой для команды. Эта статья — попытка показать наше отношение как разработчиков к тем или иным странным решениям менеджмента. Будем рады конструктивному диалогу в комментариях.

Union-find: алгоритм, применение и анализ сложности

$
0
0

Всем привет! Меня зовут Данил, и я Java-разработчик в компании TeamDev, занимаюсь написанием ПО для сетевых устройств.

Думаю, многие из вас читали Роберта Мартина, а может, и являются ценителями его идей. Мне же запомнилась одна его фраза из книги «Идеальный программист»: «Недостаточно выполнять свою повседневную работу и называть ее тренировкой». Тренировкой Мартин называет «применение своих навыков... с единственной целью совершенствования этих навыков».

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

Введение

Как узнать, связаны ли два человека цепочкой общих друзей? Где нужно построить новые дороги, чтобы город B был достижим  из города A? Какая часть людей должна быть восприимчива к болезни, чтобы стала возможна эпидемия?

Для решения подобных задач используют особую структуру данных (union-find), где элементы, будь то города или пользователи социальной сети, распределены на непересекающиеся множества.

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

Немного из теории множеств

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

Два множества могут пересекаться, образуя множество, состоящее из общих элементов (например, общие друзья), или объединятьсяв множество, содержащее в себе все элементы исходных множеств (например, целые числа и дроби образуют множество рациональных чисел).

Рассмотрим следующую задачу: имеется набор из N объектов, которые связаны между собой каким-то образом. Необходимо определить, существует ли путь, соединяющий выбранные объекты A и B через другие объекты. В теории графовданная задача определена как «задача о динамической связности» (dynamic connectivity).

Задача о динамической связности

Теперь предположим, что связанные между собой объекты — это элементы одного множества. Тогда, чтобы узнать, связаны ли выбранные объекты A и B, достаточно определить, принадлежат ли они одному множеству.

Такую структуру данных, где элементы распределены на непересекающиеся множества, называют системой непересекающихся множеств (union-find data structure).

Поскольку элементов в структуре данных может быть много, существует необходимость разработки эффективного алгоритма для выполнения операций над множествами. Для сравнения эффективности алгоритмов используют верхнюю оценку вычислительной сложности O(f(N)), которая оценивает наихудший по времени вариант выполнения алгоритма.

Правила и ограничения

Введем некоторые правила и ограничения, которые помогут смоделировать задачу о динамической связности и реализовать эффективный алгоритм для ее решения:

  1. Не имеет значения, что из себя представляют объекты. Для простоты можно сопоставить N объектам числа от 0до N  −  1.
  2. Не нужно определять, каким образом объекты связаны между собой, достаточно будет определить, принадлежат ли сопоставляемые им элементы одному множеству.
  3. Когда элементы непересекающихся множеств образуют связь, их множества объединяются.

Интерфейс

Итак, согласно первому правилу элементами множества будут числа от 0до N − 1. Для решения любых задач, использующих структуру данных union-find, будет достаточно определить следующие операции (здесь и далее примеры кода приводятся на языке Java):

    public interface UnionFind {
        void union(int p, int q);
        boolean connected(int p, int q);
    }

Немного подробнее о каждой из них:

  1. void union(int p, int q) — объединяет элементы pи q, а также множества, которым они принадлежат (правило 3).
  2. boolean connected(int p, int q) — проверяет, принадлежат ли элементы pи qодному множеству.

Жадный алгоритм

Рассмотрим первую реализацию алгоритма для решения задачи о динамической связности под названием Quick-find, которая относится к категории жадных алгоритмов.

Структура данных, используемая в алгоритме, — простой массив целых чисел (nodes[]) размера N, где индексы от 0до N  −  1сопоставляются элементам множеств, которые могут впоследствии объединяться. Два элемента с индексами pи qбудут принадлежать одному множеству, если их значения по индексу совпадают (nodes[p] == nodes[q]). Значением может быть любой элемент множества, поэтому его еще называют представителем множества.

Изначально каждый элемент системы непересекающихся множеств сам по себе рассматривается как синглтон (одноэлементное множество), поэтому каждый элемент является собственным представителем.

Конструктор выглядит следующим образом:

    public class QuickFind implements UnionFind {
        private int[] nodes;
        public QuickFind(int N) {
            nodes = new int[N];
            for (int i = 0; i < N; i++) {
                nodes[i] = i;
            }
        }
        public void union(int p, int q) { ... }
        public boolean connected(int p, int q) { ... }
     }

Возьмем для примера N = 10:

Вначале каждый элемент представляет собой синглтон

Чтобы выполнить операцию union, необходимо пройтись по всему массиву и заменить представителя одного множества представителем другого, объединив таким образом элементы двух множеств.

Алгоритм Quick-find

Теперь для того, чтобы определить, принадлежат ли два выбранных элемента одному множеству, достаточно сравнить значения по индексу: nodes[p] == nodes[q].

Ниже приведена реализация unionи connected:

    public void union(int p, int q) {
        int pNode = nodes[p];
        int qNode = nodes[q];
        for (int i = 0; i < nodes.length; i++) {
            if (nodes[i] == qNode) {
                nodes[i] = pNode;
            }
        }
    }
    public boolean connected(int p, int q) {
        return nodes[p] == nodes[q];
    }

Оценка сложности Quick-find

Очевидно, что поиск связи между элементами (операция connected) осуществляется за константное время: O(1).

Однако при объединении множеств нам придется пройти весь массив. В таком случае для Nэлементов операция union имеет линейную сложность: O(N).

Предположим, что для решения определенной задачи нам нужно построить систему непересекающихся множеств для Nэлементов и вызвать операцию unionдля каждого отдельного элемента. В этом случае сложность инициализации будет квадратичной: O(N²).

Алгоритмы с квадратичной сложностью редко находят применение на практике. Уже при N = 109поиск решения занимает часы, а при N = 1012 — годы.

Представление в виде деревьев

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

В предыдущей реализации мы представляли каждый элемент в качестве индекса i в массиве, а его принадлежность конкретному множеству — в качестве значения по индексу nodes[i]. У такого подхода есть недостаток: необходимо проходить массив каждый раз при объединении множеств.

Теперь мы будем хранить представителя множества в качестве корня дерева, а остальные элементы множества — в качестве узлов под ним.

Структура данных определяется следующим образом:

  1. Каждый элемент представляется в виде индекса массива nodes[]длины N.
  2. Родитель элемента i — это nodes[i].
  3. Корень iнаходится последовательной индексацией элемента: nodes[nodes[...nodes[i]...]] (пока nodes[i] ≠ i).

Операция union выполняется следующим образом: nodes[root(q)] = root(p). Визуально это можно представить, как будто корень элемента qподвязывается к корню элемента p.

Представление связей в виде дерева

Код алгоритма прост и лаконичен. Ниже приведена реализация root, unionи connected.

    public void union(int p, int q) {
        int pRoot = root(p);
        int qRoot = root(q);
        nodes[qRoot] = pRoot;
    }
    public boolean connected(int p, int q) {
        return root(p) == root(q);
    }
    private int root(int p) {
        while (p != nodes[p]) {
            p = nodes[p];
        }
        return p;
    }

Оценка реализации Quick-union

Не стоит забывать, что обозначение O(f(N))показывает верхнюю оценку сложности, то есть мы всегда рассматриваем худший по времени вариант выполнения алгоритма.

В указанной выше реализации мы не учитываем высоту дерева при подвязывании очередного элемента, а это значит, что теоретически дерево может иметь высоту N, то есть элементы могут образовать длинную цепочку, и поиск корня дерева будет занимать много времени. Поэтому верхняя оценка сложности операций unionи connected — O(N).

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

Взвешенные деревья

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

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

Объединение деревьев с учетом их размера

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

Возможна ли ситуация, когда дерево с меньшим размером (количеством элементов) будет выше дерева с большим размером?

Оказывается, что при таком подходе высота самого высокого дерева будет не более log(N), или, другими словами, ранг любого узла дерева не превышает log(N). Рангом узла будем называть расстояние (число ребер) от данного узла до корня дерева.

Итак, введем новую эвристику:

  1. Структура данных такая же, как и в алгоритме Quick-union.
  2. Вводится дополнительный массив sz[]для подсчета количества элементов дерева с корнем i.

Код операций rootи connectedостается прежним, меняется только union:

    public void union(int p, int q) {
        int pRoot = root(p);
        int qRoot = root(q);
        if (pRoot == qRoot)
            return;
        if (sz[pRoot] < sz[qRoot]) {
            nodes[pRoot] = qRoot;
            sz[qRoot] += sz[pRoot];
        } else {
            nodes[qRoot] = pRoot;
            sz[pRoot] += sz[qRoot];
        }
    }

Изменений в коде немного, однако скорость работы алгоритма существенно возросла. Этот факт будет несложно доказать.

Доказательство сложности log(N)

Утверждение.Ранг любого узла x не превышает log(N), где N — количество узлов.

Доказательство.Рассмотрим, при каких условиях ранг x возрастает.

Ранг xпосле слияния увеличивается на 1

Слияние двух деревьев всегда происходит за счет подвязывания корня меньшего дерева к корню большего. Это означает, что ранг любого элемента x, принадлежащего дереву T1, после слияния с деревом T2всегда увеличивается на 1, при этом |T2| ≥ |T1|. В результате слияния получим дерево с мощностью |T2| + |T1|.

В крайнем случае, когда |T2| = |T1|, мощность результирующего дерева после слияния увеличится вдвое. Другими словами, ранг xувеличивается на 1, когда количество элементов дерева растет не более чем вдвое. А это значит, что ранг x не превышает log(N).

Сжатие путей

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

Оптимизация может быть применена во время вычисления root. После того как мы нашли корень элемента p, мы можем сразу же подвязать узел к своему корню.

Сжатие путей

Код connectedи unionостается прежним. В реализации root мы добавляем всего одну строчку.

    private int root(int p) {
        while (p != nodes[p]) {
            nodes[p] = nodes[nodes[p]];
            p = nodes[p];
        }
        return p;
    }

Обратите внимание на строчку 3: мы поднимаем узел на уровень выше на каждой итерации цикла.

Финальная оценка сложности

Сложность операции unionпосле применения сжатия путей ограничивается функцией итерированного логарифма — O(log*(N)).

К сожалению, доказательство этого утверждения выходит за рамки статьи. Интересующиеся могут посмотреть подробный разбор здесь. Мы же рассмотрим только свойства данной функции.

Функция итерированного логарифмавозрастает неограниченно, но чрезвычайно медленно. Для всех мыслимых на практике аргументов ее можно было бы заменить константой, но для формул, определенных на всей числовой оси, такая запись будет ошибочной. Значения двоичного итерированного логарифма для всех практически интересных аргументов не превосходят 5 и приведены ниже:

nlog*(n)
(—∞, 1]0
(1, 2]1
(2, 4]2
(4, 16]3
(16, 65536]4
(65536, 265536]5

Это означает, что для объема данных, встречающегося на практике, операция unionвыполняется за константное время, и это было достигнуто всего одной строчкой кода!

Подытожим сложности всех операций для каждого алгоритма:

initializationunionconnected
Quick-findNN1
Quick-unionNNN
Weighted QUNlog(N)log(N)
Weighted QU + path compressionNlog*(N)log*(N)

Применение

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

Примером использования в физике является исследование теории перколяции. Звучит угрожающе, однако, по моему мнению, это очень наглядное и изящное применение данного алгоритма.

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

Сколько надо добавить медных опилок в ящик с песком, чтобы смесь начала проводить ток?

Смоделируем задачу в 2D для простоты вычислений и реализации:

  1. Представим материал в виде решетки N на N.
  2. Каждая ячейка может быть открыта с вероятностью pили закрыта с вероятностью 1 − p. Ток, соответственно, может проходить только через открытые ячейки.
  3. Протекание возникает тогда и только тогда, когда верх и низ решетки соединены открытыми ячейками.

Закрытые ячейки помечены черным цветом, открытые — белым, ток — синим

Обозначим открытую ячейку s0, а закрытую — s3. Тогда соотношение открытых ячеек к закрытым и есть вероятность p = s0 / s3.

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

Очевидно, что при p = 1ток будет протекать с вероятностью 100%, а при p = 0 — не будет. Однако нам необходимо определить более точное значение p, при котором решетка начинает проводить ток.

Самое интересное, что данная задача не решается математически. Определить приблизительное значение p, при котором ток будет просачиваться с вероятностью p* > 1/2, можно лишь эмпирическим путем.

Число pтакже называют порогом протекания, минимальной концентрацией элементов перколяционного кластера (в нашем случае — s0), при которой возникает протекание.

При каком pрешетка начнет проводить ток

На рисунке показано, что вероятности p = 0,4недостаточно для возникновения перколяции, а при p = 0,7можно уверенно сказать, что ток будет протекать через решетку. Сомнения возникают при p = 0,6, когда не всегда можно дать положительный ответ.

Реализация Percolation

Рассмотрим, как можно представить нашу задачу в виде системы непересекающихся множеств:

  1. Решетку N на N можно представить в виде массива размерности .
  2. Обозначим закрытую ячейку как 0, а открытую — 1. Изначально все ячейки закрыты.
  3. Последовательно открываем случайные ячейки.
  4. Если соседняя ячейка (сверху, снизу, справа или слева) также открыта, выполняем операцию union с каждой из них.
  5. Повторяем шаги 3–4,пока любая верхняя ячейка не будет связана с любой нижней. Проверка осуществляется с помощью знакомой нам операции connected.

Представление решетки N на N в виде массива элементов

Как видите, алгоритм предельно прост, однако шаг 5-йдостаточно ресурсоемкий. Нам придется выполнять connectedпоследовательно для каждой верхней ячейки с каждой нижней, то есть сложность этих вычислений составит O(N²).

Чтобы упростить последний шаг, можно пойти на небольшую хитрость. Мы введем 2 виртуальных элемента, pTopи pBottom, и свяжем их с верхней и нижней строкой соответственно. Тогда на 5-мшаге мы будем просто проверять connected(pTop, pBottom).

Виртуальные элементы pTopи pBottom

Вычисление порога протекания

Теперь у нас все готово для проведения экспериментов. Как говорилось ранее, нам необходимо определить минимальное количество открытых ячеек, при котором происходит перколяция, так называемый порог протекания. Вычислить его возможно лишь эмпирически и на большой выборке.

Традиционно для изучения случайных процессов воспользуемся методом Монте-Карло:

  1. Инициализируем решетку N на N закрытыми ячейками.
  2. Выбираем случайную ячейку и открываем ее.
  3. Повторяем шаг 2-й,пока решетка не будет в состоянии перколяции.
  4. Вычисляем порог протекания как отношение открытых ячеек к закрытым: p = s3 / s0.
  5. Повторяем шаги 1–4-й T раз.

Точность результата зависит от размера решетки Nи количества экспериментов T. В конце значения порогов усредняются и вычисляется среднеквадратичное отклонение. Пусть, xt — значение порога протекания в эксперименте t, тогда среднее значение xи среднеквадратичное отклонение определяются так:

В результате получаем заветное число — 0,593. Это означает, что концентрация медных опилок в ящике с песком должна превышать 50%, чтобы смесь была токопроводящей.

График вероятности перколяции

Выводы

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

Верхняя граница сложности O(f(N))отвечает на вопрос, с какой скоростью растет число операций алгоритма при увеличении N. То есть, к примеру, если мы удвоим количество элементов в алгоритме Quick-find, то объем работы для операции unionтакже удвоится.

Позднее мы доказали, что сложность unionможно свести к O(log*(N)), а это означает, что при любых объемах данных, применяемых на практике, операция unionбудет выполняться одинаковое время.

Безусловно, для важных научных исследований можно воспользоваться мощностью суперкомпьютера, производительность которого измеряется экзафлопсами (1012). Однако, если посчитать, это всего на 6 порядков выше производительности домашнего ПК (1018). Когда мы имеем дело с алгоритмом квадратичной сложности, суперкомпьютер обеспечит прирост объема входных данных всего в 1000 раз, чего может быть недостаточно для решения поставленной задачи за допустимое время.

Поэтому так важно правильно оценить сложность алгоритма и на основании полученной оценки выбрать самую оптимальную реализацию.

Благодарность

Выражаю благодарность профессору Принстонского университета Роберту Седжвику и доктору технических наук Кевину Уэйну за составление исчерпывающего курсапо алгоритмам «Algorithms, Part I, II» на сайте coursera.org. Также в свободном доступе можно найти их книгу Algorithms, 4th Edition.

Источники

  1. Sedgewick, Robert; Wayne, Kevin (2011). Algorithms. 4th ed. Addison-Wesley Professional. ISBN 978-0-321-57351-3.
  2. Sedgewick, Robert (2012). Union Find. Coursera.
  3. Disjoint-set data structure (2019) in Wikipedia: The Free Encyclopedia, Wikimedia Foundation Inc.

Станут ли микросервисы архитектурой будущего

$
0
0

Меня зовут Михаил Бродский, я Lead Software Engineer, Consultant в GlobalLogic (Харьков). В сфере IT уже более 7 лет. Занимался проектированием, разработкой информационных систем и их внедрением. Сейчас возглавляю проект, связанный с сетевой безопасностью. Занимаюсь повышением эффективности процесса разработки с помощью виртуализации, разработкой и анализом архитектурных решений, а также реализацией программной функциональности.

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

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

Начнем со следующего примера: представим себе систему продажи железнодорожных билетов несколько десятилетий назад. Каким образом можно было купить билет? Существовало несколько вариантов: пойти в кассу и отстоять очередь, заказать билет по телефону, приобрести его через знакомых либо через сервисный центр. Эта система работала отлично (если не брать во внимание длину очереди и скорость обслуживания): в любой момент времени доступ к системе имели несколько кассиров, обеспечивая безупречное функционирование этой модели.

Прошло время, и теперь мы можем приобрести билеты с помощью мобильного телефона на специальном портале, используя второстепенный сервис. Но сейчас у нас нет возможности контролировать доступ в произвольный момент, и мы не знаем точного числа желающих купить билет — мы потеряли этот доступ. Каким же образом мы сможем решить проблему с производительностью и доступностью подобной системы? Это стало возможно благодаря переходу от одного типа архитектуры (монолитной системы) к архитектуре на основе микросервисов.

Микросервисы

Благодаря микросервисам мы нашли решение этой проблемы. На мой взгляд, самое удачное определение: микросервисы — это декомпозиция крупной бизнес-системы на независимые элементы, которые легко развернуть и легко обслуживать, при этом каждый из них выполняет одну определенную задачу.

Высокоуровневая схема микросервисной архитектуры

Почему мы использовали именно микросервисы?

В первую очередь из-за повышения скорости работы модели. При разделении монолитной системы на независимые элементы такую систему становится легче разрабатывать, ее можно «расскейлить», распараллелить: несколько команд смогут работать над разными микросервисами, при этом каждый микросервис будет иметь свой pipeline, continuous integration, continuous delivery. Таким образом, скорость работы системы повышается.

Безопасность и стабильность. После распределения модели на несколько микросервисов появляются некоторые дополнительные возможности. Например, представим себе скоростной суперкар. Что произойдет, если мы не будем контролировать его скорость? Он разобьется. Если мы имеем дело с «умной» машиной, ее датчики и контроллеры помогут нам отследить скорость, контролировать ее, управлять транспортным средством. Это позволяет повысить безопасность работы.

Это же относится и к работе с микросервисами: мы можем применять некоторые паттерны стабильности. Например, паттерн Timeout: если один из микросервисов не отвечает, мы можем быстро отключиться по тайм-ауту, показав пользователю, что этот сервис недоступен. Можно также применить паттерн Circuit Breaker («Предохранитель») — здесь уместна аналогия с домашней сетью электроприборов: при резком скачке напряжения барьер, контролирующий сетевое напряжение, отключает систему на некоторое время и после тайм-аута проверяет, вернулось ли напряжение в норму, можем ли мы подключить устройства к сети. Если нет, после определенного периода покоя проверка выполняется снова. Также возможно применение паттерна переборок. При распределении монолита между несколькими микросервисами становится возможным независимое применение таких паттернов.

Таким образом, если у нас есть определенное число независимых элементов, используя облачное решение, мы можем настроить правильные метрики, и сервис можно будет очень легко масштабировать в каждом облачном решении (в AWS это CloudWatch).

В качестве примера приведу наш текущий проект. Мы собираем метрики одного из микросервисов при нагрузочном тестировании, чтобы понять, как именно этот сервис будет масштабироваться в рабочей среде в зависимости от нагрузки.

Три основные группы микросервисов

Существует три основные группы микросервисов:

  • Stateless — сервисы без сохранения состояния.
  • Persistence — сервисы, которые сохраняют свое состояние.
  • Aggregators — агрегаторы.

Stateless

Такие микросервисы не имеют никакой зависимости от storage (cache и прочее) и определяют очень простые действия. Пример — конвертация из одной валюты в другую. Очень быстрое действие, нет зависимости от других сервисов и от дискового пространства. Их легко заменить и легко масштабировать.

Persistence

Другой тип микросервисов — сохраняющие свое состояние. К ним относятся сервисы, которые сохраняют зависимость от storage, у них есть операции записи/чтения, их точно так же легко масштабировать, если есть зависимость от диска, если разделены операции, применив паттерн CQRS. В двух словах: у нас есть запрос на чтение и запрос на запись. Мы можем распределить эти модели — за каждую модель будет отвечать определенный микросервис. Таким образом, мы можем масштабировать такую модель на независимые микросервисы. В первую очередь при этом мы зависим от других сервисов. Если взять Amazon или Netflix, один сервис вызывает огромное количество других сервисов. Кроме зависимости от других сервисов, есть зависимость от сети. Появляется запись в базу данных и, конечно же, Disk I/O Dependence.

Aggregators

Рассмотрим пример архитектуры, которую мы применяли для реализации группы паттерна микросервиса «Агрегатор».

Задача состояла в следующем: мы работали с безопасностью сети и безопасностью клиентских точек (endpoints). В нашем распоряжении было определенное количество брандмауэров. Брандмауэр аналогичен роутеру, только намного «умнее»: существует программная оболочка, определенная логика, осуществляющая анализ сети, и в зависимости от повышения сетевой активности и появления атак мы можем ограничивать сетевой доступ для клиентских точек, а также их взаимодействие между собой. Необходимо было собирать телеметрию, логи данных устройств для последующей обработки и генерации уведомлений. На самом деле эта задача является подзадачей создаваемого нами огромного решения.

Изначально наша архитектура выглядела так:

Микросервис-агрегатор с блокирующим (синхронным) запросом

Было устройство — брандмауэр, использовался микросервис, ответственный за сбор телеметрии (Device Data Collector MS), микросервис, ответственный за обработку полученной информации (Device Data Processor), а также микросервис, ответственный за генерацию уведомлений (Alert Generator).

Почему это называется подсистемой? Причина в том, что все эти брандмауэры интегрировались в систему, доступ к которой можно получать из облака. Представим, что есть распределенная сеть, безопасность которой необходимо повысить. Есть dashboard, к которому подключены брандмауэры, находящиеся в разных локациях. Вы заказываете брандмауэр, приезжают администраторы, настраивают его, после чего перед вами встает задача: как же управлять этим оборудованием? Очень легко! Вы регистрируете его в нашей системе, можете управлять им через «админку» устройства из любой точки мира и настраивать систему. Вопрос: почему я не могу получить доступ к «админке», находясь в другом месте? Некоторые правила блокируются, определенная конфигурация доступна только при подключении к устройству. Как раз этот сервис реализовывал процесс сбора информации, генерации уведомлений и их отображения на центральном dashboard.

В нашей системе коммуникация между устройством и микросервисом, собирающим информацию, была синхронной — и это была самая большая проблема. Такой подход работал до момента, пока не поменялись требования.

Изначально мы должны были поддерживать 5000 устройств. Каждые 5 минут — не очень часто — каждое из этих устройств отправляло какую-то информацию о своей работе, и это составляло 17 запросов в секунду (тоже не очень много). За два часа работы собиралось 35 мегабайт, эту информацию мы сохраняли в базу данных, хранили ее 2 часа, и, если что-то произошло, запускалось задание, анализировалась информация, вызывался следующий микросервис, генерирующий уведомление, которое отображалось на доске уведомлений.

Все было отлично, пока не поменялись требования. Вместо 5000 устройств от нас потребовалось подключение 50 000. И тут мы поняли, что возникнут проблемы. Собрали все метрики, проанализировали информацию — проблема заключалась в том, что устройство блокировалось на время обработки всей цепочки сообщения. Как можно было решить эту проблему?

Микросервис-агрегатор с асинхронным ответом

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

И тут возникает несколько вопросов.

Первый.Что произойдет с системой, если сообщений будет очень много и очередь не будет справляться с этой нагрузкой? Существует несколько решений:

  • Заблокировать отправителя до того момента, пока не будет обработано сообщение.
  • Блокировать очередь либо при увеличении сохранять ее часть на жесткий диск.
  • Применить метод контролирования обратного потока (используется в TCP-протоколе): создается буфер складирования сообщений, при переполнении которого поступление сообщений блокируется.

Второй.Что произойдет, если «отвалится» сеть и очередь перестанет быть доступной? Можно кешировать сообщения, проверять доступность сети: если доступа нет, мы кешируем сообщения, а когда сеть появляется, накопленные сообщения отправляются в очередь и обрабатываются.

Третий.Что произойдет, если Device Data Processor не сможет выбирать сообщения (как мы описывали ранее)? А что, если устройству будет необходим результат обработки сообщения?

Один из вариантов решения: устройство отправило сообщение с ID, сообщение было обработано, и микросервис создает вторую очередь для ответа, о существовании которой будет «знать» только это устройство. Когда будет обработано сообщение из второй очереди (ответ), эта очередь будет удалена.

Если мы не хотим использовать асинхронную обработку — с очередями, брокерами сообщений и прочим, — существует еще один подход, о котором будет рассказано ниже.

Системы обработки сообщений

Рассмотрим основные понятия.

Message

Первое — сообщение. Можно провести аналогию: HTTP-запрос.

Message Broker & Message Queue

«Посредники» — брокер сообщений или очередь. К ним относятся TIBCO Enterprise Message Service, WebSphere, webMethods, RabbitMQ, ActiveMQ, HornetQ, NATS, Apache Kafka. Это нечто среднее между RPS и реляционной базой данных. Другими словами, это базы данных, адаптированные исключительно для работы с очередью.
Приведу несколько различий между этими двумя подходами.

Direct Communication

TCP, one-to-one

Один продюсер и один подписчик. Пример — TCP-протокол. Используется обработка контроля обратного потока. Посредник не используется. Если сообщение вдруг не было обработано, мы можем переслать пакет еще раз и обработать его.

UDP, ZeroMQ (over TCP), Webhooks (HTTP Callbacks)

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

Message Brokers

JMS, AMQP, RabbitMQ, ActiveMQ, HornetQ, Qpid, TIBCO Enterprise Message Service, IBM MQ, Azure Service Bus, Google Cloud Pub/Sub, SQS — их особенность в том, что при необходимости сообщить подписчику о нештатной ситуации (например, сообщение не было обработано, доставлено) используются посредники. Далее я расскажу, чем отличается Kafka от остальных существующих подходов.

Logs-Based Message Brokers

Посредники, работающие на основании логов.

HTTP Callbacks with Payload

Схема паттерна HTTP Callbacks with Payload

Этот метод объединяет посредника (Hub), подписчика (Subscriber), создающего сообщение, и издателя (Publisher). Например, подписчик заявляет, что хочет получать новости от определенного сервиса, и запрашивает ссылку на посредника (Hub): отправляет запрос, получает ссылку, отправляет подзапрос посреднику, происходит валидация подписчика. После этого, когда создаются дополнительные новости, посылается запрос на Hub о появлении новой информации, и посредник идентифицирует нового подписчика. Это стандартный паттерн — вы можете применить его, если нет необходимости использовать какого-то определенного посредника (например, Kafka).

Logs-Based Message Storage

Рассмотрим системы отправки сообщений на основании логов. К ним относятся Kafka, Distribute Logs от Twitter и реализация от Azure.

Схема работы систем сообщений на основе логов

У нас есть несколько очередей, несколько топиков, несколько разделов (Partitions). Есть продюсеры, которые создают сообщения и сохраняют их в очереди. Какую проблему решает этот подход?

Что произойдет с обработанным сообщением? Оно будет удалено из очереди. Новые подписчики не увидят сообщений, добавленных ранее. Что, если мы объединим два ранее упомянутых подхода? Мы сможем хранить сообщения некоторое время, делать запросы, кроме того, сообщения не будут удаляться из этих очередей. Допустим, надо протестировать нашу систему. Что для этого нужно? Необходимо подключить все устройства, сгенерировать информацию, загрузить ее в очередь и посмотреть, как будет происходить обработка. После того как обработка закончится, все сообщения будут удалены. На основании логов сообщения не будут удаляться из очередей — они будут храниться не постоянно, а в течение определенного времени (это не реляционная база данных). Мы можем не пересоздавать эти сообщения, а прогнать обработку и посмотреть на результат. Как это работает?

Итак, у нас имеются очереди, добавляются продюсеры и потребители (Consumers). Когда какой-то из потребителей считывает сообщение, присваивается сдвиг (Offset): сколько сообщений было прочитано и какое сообщение было прочитано. Допустим, если мы прочитали определенное количество сообщений в разделе 0, мы записываем, чему равен сдвиг для этого раздела (например, 6):

Offset for P0 = 6

Это означает, что клиент считал и обработал определенное количество логов (сообщений в очереди). Если приходит другой потребитель и пытается считать эти сообщения, посредник уже знает, что эта система не обработала ни одного сообщения, и отдает команду считать все соответствующие сообщения.

Объем релиза

В теории графов существует интересная формула, которая подсчитывает оптимальное число изменений в релизе: n — количество изменений (количество ребер в графе; соединения между ребрами — это изменения, зависимости) (рисунок 6). Политика Netflix — минимизировать число изменений, повысив частоту релизов. Если вы включаете в релиз большое число изменений, растет число дефектов, которые необходимо будет обнаружить и исправить. Например, при числе изменений n = 5 мы получаем 10 зависимостей. Минимизируя число изменений, мы уменьшаем число дефектов в системе.

Расчет оптимального релиз-скоупа

Выводы

В итоге на базе микросервисов мы создали асинхронный компонент, основная задача которого — сбор телеметрии от IoT-девайсов и создание необходимых оповещений (алертов) для уведомления пользователя. Каждые 2 часа мы получаем и сохраняем до 400 мегабайт информации.

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

  • получили практику предварительной оценки и разработки прототипов микросервисов;
  • с нуля создали асинхронный компонент, который позволил оптимизировать работу всей системы для большего количества подключенных устройств (до 50 000 устройств в одном регионе).
Что дальше? Мы смотрим в будущее с оптимизмом: переход от монолитной системы к микросервисам не только даст бизнесу и пользователям лучший user experience, но и позволит создавать целый набор различных сервисов, которые облегчат работу и жизнь.

Сейчас перед нами стоит задача поддержки и развития этого компонента, впереди еще много работы!

Хотите узнать больше или есть вопросы? Пишите в комментарии, в LinkedInи подписывайтесь на YouTube-канал.


Як у SoftServe втілили концепцію Mixed Reality, у якій віртуальні об’єкти можна відчути на дотик

$
0
0

У рубриці DOU Labsми запрошуємо IT-компанї ділитись досвідом власних цікавих розробок та внутрішніх технологічних ініціатив.

Привіт, я Тед Романус, Research Engineer у SoftServe в напрямку Human-сomputer interactions (HCI). Наша група в R&D працює над новими технологіями, що змінюють взаємодію людини з цифровими медіа — від віртуальної (Virtual) і доданої (Augmented) реальності до ефектів дотику (Haptics) та взаємодії через мову тіла й емоції (Affective computing).

Сьогодні я розповім про наш проект Touch My Heart — першу у світі голограму, якої можна торкнутися, яку можна штовхнути і яка передає такі легкі модуляції як серцебиття людини. Це демо, яке ми вже презентували на кількох найбільших HCI-конференціях у Великій Британії, США, Японії, Іспанії та Китаї, відкриває нові можливості природнішої й інтимнішої взаємодії з віртуальними об’єктами та дозволяє вже тепер почуватися героєм Blade Runner.

Виставка IoT World Expo 2018 в Барселоні

У цьому проекті ми поєднали:

  • AR-голограму, яку можна побачити через окуляри Magic Leap;
  • ефект дотику через ультразвукові хвилі (Ultrahaptics);
  • трекінг рук сенсором Leap Motion;
  • біосенсори.

Як наслідок, ми зреалізували концепцію Mixed Reality, у якій віртуальні об’єкти зливаються з реальним світом.

Ідея

Усе почалося з нашого знайомства з технологією Ultrahaptics, яка передає ультразвуковий імпульс у певну точку простору, що створює відчуття, схоже на фізичний дотик. Микола Максименко, R&D Director у SoftServe, давно знайомий з Орестісом Георгіу, Research Director в Ultrahaptics, і кілька разів запрошував його в Україну на конференцію IT Weekend Ukraine та виступити в Українському католицькому університеті. Орестіс Георгіу погодився на наше запрошення.

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

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

Наступний етап — генерація ідей, у якому ми брейнштормили всією R&D-командою. З’являлися різні думки — від забавок до чогось серйознішого. Нарешті, вирішили зробити проект, який не лише розкриє потенціал цієї технології, а й викликатиме емоції в аудиторії, якій ми демонструватимемо це демо на різних подіях. Так народилася ідея відтворити серце, що б’ється.

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

Робота над проектом

Спочатку розробляв проект (писав код, тестував) під окуляри Meta я, консультуючись з іншими R&D-фахівцями. У схожих дослідницьких проектах немає чіткого розуміння, чи вийде зреалізувати задумане, тож ми поступово розв’язували окремі технічні проблеми й розширювали кейс.

До окремих завдань долучались інші інженери. Наприклад, адаптували технологію до інших AR-окулярів або поліпшували 3D-модель R&D-інженер і дизайнер з нашої команди.

Спочатку ми мали зрозуміти, як саме відтворити дотик — які точки на руках стимулювати, яким чином, з якою інтенсивністю й з якою частотою. Моє початкове завдання полягало в тому, щоб дуже швидко (у межах кількох тижнів) зробити прототип і показати, у якому напрямку ми рухаємося та чи має це сенс. Це стандартний ресерч-процес у R&D. Коли це вдалося, можна було рухатися далі.

У комплекті з пристроєм Ultrahaptics іде SDK для розробки під Windows/Mac. Використовуючи його, ми змогли вивести анімацію серця на екран комп’ютера й створити відчуття дотику в просторі, тобто людина могла фізично відчувати те, що бачить на екрані комп’ютера.

Ми пішли далі й додатково використали окуляри Magic Leap, до яких розробили віртуальну модель серця (таку саму, яка відображається на екрані комп’ютера). Щоб користувач міг бачити серце через Magic Leap і одночасно торкатися його через ультразвукові хвилі, згенеровані Ultrahaptics, треба було поєднати системи координат цих двох пристроїв.
Це вже був значний крок уперед у використанні технології Haptic Feedback — доповнену реальність тепер можна було відчути фізично.

Ми вирішили не зупинятися й поставили собі наступну мету — зробити так, щоб серце здавалося живим. Для цього треба було створити коливання інтенсивності імпульсів, що передаються на шкіру. За основу взяли STM_Circle (один зі скриптів, які йдуть разом з Ultrahaptics SDK). Саме відчуття складається з точок, які бігають по колу радіусом 3 см з частотою 100 Гц (зважаючи на затримку опрацювання сигналів людським мозком, воно сприймається як ціле коло). Щоб одержати відчуття серцебиття на базі цього статичного відчуття, ми запропонували два підходи:

  • зміну інтенсивності імпульсу відповідно до нормалізованої сили даних про серцебиття, яку отримують з годинників Apple Watch чи MAWI;
  • зміну радіуса кола синхронно зі серцебиттям.

Насамкінець для яскравішої демонстрації ми взяли не якісь статичні дані, а відтворили ритм серцебиття реальної людини. Для цього я використав Apple Watch, підходить також годинник українського бренду MAWI, який дозволяє не лише міряти пульс (PPG), а й знімати кардіограму (ECG). Дослідженняпоказують, що Apple Watch вимірює пульс найточніше з усіх доступних на ринку фітнес-трекерів. MAWI практично міряє кардіограму, у якій значно більше даних, ніж у PPG (дослідження). Використовуючи такий метод, пульс визначаємо якнайточніше (саме з цим методом порівнюють усі інші).

Схема застосунку

Розробку вели в середовищі Unity, оскільки я маю найбільше досвіду роботи з ним і в ньому можна швидко прототипувати. А коли PoC було готове, вирішили не переписувати на інші платформи, а продовжити з Unity. Під час роботи використовували такі бібліотеки:

  • OpenCV вибрали саме тому, що на всіх нових платформах популярні image tracking фреймворки не мають імплементації, і ми не маємо доступу до параметрів камер. А в OpenCV є методи, з якими можна провести 3D-реконструкцію (тобто розпізнати прості патерни в 3D) на будь-яких камерах. Недавно в Magic Leap SDK додали свою імплементацію розпізнавання зображень, і ми переписали все на неї.
  • Ultrahaptics plugin, Leap motion plugin, Lumin SDK для інтеграції окулярів Magic Leap в Unity3D — потрібні речі для роботи, які не мають аналогів.
  • http-сервер для передачі даних про серцебиття — простий і кросплатформний спосіб для передачі інформації.

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

Ми поділилися результатом з Орестісом і виявилося, що таких рішень у світі ще немає, окрім відеоконцепту Ultrahaptics і дизайн-студії Nike. Тож уже разом з Ultrahaptics ми написали кілька матеріалів для конференцій з human-computer interaction.

З технічного погляду цей проект — насправді 3 окремі програми (для ноутбука, для Magic Leap, для Apple Watch), які треба запустити й протестувати. Бібліотеки, які ми використовували, мали досить скромну документацію, на StackOverflow узагалі порожньо (останнім часом для Magic Leap ця ситуація виправилася, для Ultrahaptics досі нічого загуглити не вийде). Щоб правильно засинкати всі системи координат, перетворення тощо, треба було ще розібратись у лінійній алгебрі й математиці 3D-перетворень, що теж забрало багато часу.

Перспективи

Перші версії демо Touch My Heart ми показували на маркетингових стендах, щоб побачити реакцію людей і, відповідно, удосконалити проект. Люди дуже емоційно реагують на такий новий спосіб взаємодії, найчастіше, це емоції захоплення й здивування. Цього року ми презентували його на кількох спеціалізованих міжнародних конференціях з Human-Computer Interaction, зокрема на CHI2019 у Ґлазґо й World Haptics Conference в Токіо, де дістали позитивний фідбек щодо новизни нашої ідеї та реалізації. Зокрема, наше демо в Японії помітив навіть засновник Magic Leap Роні Абовіц, а на Augmented World Expo ми потрапили до фіналу Auggie Awards в номінації Best Interactive Software.

Тепер ми працюємо над кількома новими ідеями, що матимуть практичніше значення, але водночас будуть цікавими з огляду новизни в HCI.

Загалом ця технологія має потенціал для практичного застосування в таких напрямках:

  • Хірургія — розширить можливості проведення дистанційних консультацій, що допоможе зменшити ризик виникнення ускладнень і підвищити точність проведення реконструктивного оперативного втручання.
  • Реабілітація — комбінація візуального й тактильного типу інформації допоможе пришвидшити й поліпшити якість процесу реабілітації.
  • Новий рівень тактильної взаємодії — можливість доторкнутися до того, що далеко, може широко використовуватися в комерційній, рекламній галузі; виводить на новий рівень комунікацію між людьми, коли можна відчути дотик на відстані.
  • Керування автомобілем — розпізнавання жестів (замість використовувати тачскрини та кнопки) для керування приладами, розміщеними в салоні автомобіля, допоможе сконцентрувати на дорозі.

Путешествие на планету Java. Мой опыт прохождения cертификации Java 11 Developer (часть 2)

$
0
0

Меня зовут Евгений Бережной, я — Java Developer в AB Soft, и речь в этой статье пойдёт о втором экзамене Java 11 Programmer II (1Z0-816). О первом экзамене и в целом о Professional: Java 11 Developer certificationчитайте первую часть. Второй экзамен существенно отличается от первого, но хочу вас порадовать: как по мне, в лучшую сторону.

Во-первых, экзаменаторы больше не пытаются подловить вас на невнимательности. Вы либо знаете, как работает код, либо нет.

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

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

Иллюстрации: Дмитрий Яценко

Чтобы получить сертификат, нужно сдать оба экзамена. К сдаче Java 11 Programmer II (1Z0-816) я советую подходить после сдачи Java 11 Programmer I (1Z0-815), хотя экзаменаторы этого не требуют и сдавать экзамены можно в любом порядке.

Если вы являетесь обладателем титула OCP 6...8, то вам надо сдать только один экзамен — Upgrade OCP Java 6, 7 & 8 to Java SE 11 Developer 1Z0-817, который очень похож на Java 11 Programmer II (1Z0-816) по затронутым в нем темам, поэтому информация вам тоже будет полезна.

Кстати, конкретно по этому экзамену коллега из дружественной Беларуси написал очень неплохой Study Guide.

Если же вы являетесь обладателем титула OCA 7, 8 то сдавать экзамен Java 11 Programmer I (1Z0-815) вам не надо, можете сразу покорять Java 11 Programmer II (1Z0-816).

Хорошая новость: у вас есть право на одну бесплатную пересдачу каждого экзамена. Детальнее об этом можно прочесть тут.

Темы экзамена

Java 11 Programmer II (1Z0-816) основан на старом экзамене OCP 8 (1Z0-809), список тем и сравнительная таблица приведены здесь.

Для подготовки я советую использовать книгу «OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide: Exam 1Z0-809» Boyarksy/Selikoffлибо «OCP Java SE 8 Programmer II Exam Guide (Exam 1Z0-809)» Sierra/Bates, в них детально описаны темы, которые перекочевали из OCP 8. В этой же статье я подробно расскажу о новшествах Java 9...11 и темах, которых раньше не было на экзамене.

Прошу обратить внимание, что некоторые темы из книг не будут подниматься на экзамене, но все равно пригодятся в повседневной работе. К примеру, вопросов по Fork/Join Framework и паттернам проектирования на экзамене уже нет.

Итак, начнем наш обзор новинок :)

Модульность

Модули — наше все! Разделяй и властвуй! Под этим девизом Oracle усиленно продвигает нововведение. Вопросов о модулях будет порядка 10, и, в отличие от первой части, эти вопросы будут практического характера.

Вас спросят, правильно ли написан module-info.java, включая корректное использование Service Provider Interface (SPI), который с появлением модульности обрел вторую жизнь. Зададут вопрос, правильно ли сделаны импорты и экспорты, должен ли быть хоть один провайдер сервиса во время компиляции и выполнения, а также массу других вопросов, узнать ответы на которые вам поможет только практика.

Поэтому я рекомендую взять книгу Шилданачиная с десятого издания, где приведены емкие примеры с пояснениями (всего 25 страниц). Освоив их на практике, вы получите ответы на 90% вопросов о модульности. Но помните: главное — «запачкать свои руки», а не просто полистать книгу.

Если есть желание окунуться в модульность с головой, советую книгу «Java 9 Modularity Book». В ней есть отличные примеры практического использования и стратегии миграции.

У меня на экзамене был только один вопрос касательно jdeps — очень неплохого инструмента для поиска зависимостей компиляции. Советую изучить его хотя бы поверхностно.

Вопросов о jmodи jlinkна экзамене не было.

Сериализация и безопасность

Новая и самая обширная тема на экзамене — это, конечно же, безопасность. Сериализация — крупная брешь в безопасности, и эти темы надо рассматривать вместе. Вопросов по ним будет много, порядка 10. Готовиться к этим темам, пожалуй, сложнее всего. Вопросы разные — начиная от чисто теоретических и заканчивая вопросами типа:

  • что надо сделать в коде, чтобы он считался безопасным;
  • когда нужно делать deep copy объекта для мутабельных классов;
  • когда надо делать copy constructor.
Кроме обязательного чтения нудных и сухих руководств Secure Coding Guidelinesи Chapters 1, 2, and 3 of Serialization Specification, рекомендую почитать горячо любимую мною «Effective Java»Джошуа Блоха. Там есть один раздел, посвященный сериализации, где рассматриваются вопросы безопасности.

Аннотации

Аннотация — одна из старых возможностей Java, которой раньше не было на экзамене, но без которой трудно представить современную разработку. На экзамене от вас потребуется знание базовых встроенных аннотаций, таких как @SuppressWarnings и @SafeVarargs, будут вопросы и по аннотациям @Repeatable.

Вы должны понимать, где и с какими аргументами они используются. Также надо уметь писать свои аннотации. Для освоения этих премудростей возьмите Шилдалибо официальный мануал.

Возможность использования зарезервированного типа локальных переменных var — еще одно нововведение Java 10. Начиная с Java 11 их можно использовать для параметров в лямбда-выражениях, как раз чтобы была возможность использовать аннотации для этих параметров. Знание этих новшеств в ходе экзамена у вас обязательно проверят.

JDBC

В разделе JDBC есть одна новая тема — использование CallableStatement. Мне вопросы по ней не попадались, но все остальные вопросы по JDBC были. Выше я советовал книги, где они хорошо описаны. О CallableStatement и их отличии от PreparedStatement можно почитать здесь.

Интерфейсы

Нововведение, о котором надо помнить: начиная с Java 9 методы в интерфейсах могут быть приватными. Приватные методы могут быть статическими и нестатическими. Методы не могут быть одновременно приватными и дефолтными. Эти методы используются в дефолтных и статических методах самого интерфейса, т. е. они введены как вспомогательные методы, позволяющие переиспользовать код, общий для других методов внутри интерфейса.

Эти методы подчиняются правилам, аналогичным для приватных методов класса:

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

Темы, перекочевавшие из OCP 8, и в целом о подготовке

Выберите одну из книг: Boyarksy/Selikoffлибо Sierra/Bates. Переключаться между ними не стоит. Возьмите себе за правило каждую неделю читать главу и проходить один мок-экзамен в конце главы. В результате через 2 с половиной месяца вы будете готовы по перекочевавшим из OCP 8 темам (IO, NIO 2.0, Concurrency и т. д.). Подготовиться по новым темам вам помогут советы из этой статьи.

Параллельно с прочтением книги пишите много кода, чтобы загнать это все в пальцы и понять, как использовать полученные знания. Самое главное — понять, почему оно работает именно так.

Хорошо разберитесь с внутренними классами, как их инициализировать, к каким элементам родительского класса у них есть доступ.

Особое внимание стоит уделить Stream API и лямбдам. На экзамене их будет очень много. Выучите наизусть методы, аргументы и возвращаемые значения базовых функциональных интерфейсов (Consumer, Supplier, Function, Predicate, UnaryOperator). Обязательно нужно понимать, как получаются производные интерфейсы. Также вы должны знать, как написать собственный функциональный интерфейс.

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

public class TestClass{
    public static int operate(IntUnaryOperator iuo){
        return iuo.applyAsInt(5);
    }
    public static void main(String[] args) {  
        IntFunction<IntUnaryOperator> fo = a->b->a-b; 
        int x = operate(fo.apply(20)); //2
        System.out.println(x);
    }
}

Первое, что пугает и бросается в глаза, — это выражение a->b->a-b, но недоумение немного поутихнет, если переписать фрагмент в таком виде: a->(b->a-b).

IntFunction — это функциональный интерфейс, который получает intи возвращает то, к чему он типизирован. В данном случае он приведен к IntUnaryOperator. Следовательно, IntFunction<IntUnaryOperator>принимает intи возвращает IntUnaryOperator.

Теперь, если вы посмотрите на fo = a->b->a-b, то увидите, что a — это аргумент типа int (т. к. он используется, чтобы получить IntFunction), а b->a-bформируют тело метода этого IntFunction, которое вернет IntUnaryOperator.

IntUnaryOperator — это функциональный интерфейс, который получает intи возвращает другой int. Он не может быть типизирован к чему-либо другому, т. к. и аргументы, и возвращаемое значение уже назначены как int.

То есть, когда вы вызываете fo.apply(20), вы устанавливаете a=20. Отсюда b->a-bвозвращает как IntUnaryFunction iuoравной b->20-b.

Затем вы вызываете iuo.applyAsInt(5), в которой значение bустанавливается равным 5, и в результате возвращается 20-5, т. е. 15.

Со стримами также очень много громоздких конструкций. Хорошо разберитесь с использованием методов groupingByи particioningBy, merge. Попрактикуйтесь, научитесь пользоваться ссылками на метод.

Также будут проверять знание новых фабричных статических методов для коллекций, которые появились в Java 9. Информацию по ним и примеры использования вы можете посмотреть здесь.

Если после выполнения всех рекомендаций у вас останутся сомнения в собственных силах, попробуйте мок-тесты Enthuware, посмотрите форум о сертификации на CodeRanch.

Итог

Как я ранее писал, экзамен длится 3 часа. Всего 80 вопросов, времени вполне хватает. Проходной балл — 63%.

Результаты экзамена придут в течение 15 минут на вашу почту.

В случае успешной сдачи (в которой не стоит сомневаться, если вы подготовились) через 48 часов появится возможность скачать с OracleCertViewсертификат и получить электронный бейдж, проверенный с использованием блокчейна (удивительно, как сюда AI еще не подкрутили :)

Электронный бейдж

При желании можно заказать бумажную копию, которая придет через 2-3недели по почте. Лично я не стал убивать еще одно дерево, думаю, в современном мире это будет лишним.

Так выглядит сертификат

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

В целом самое ценное, что вы получите от сертификации, — это знания, которые у вас могут забрать разве что люди в черном.

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

Да пребудет с вами сила! Удачи!

Security Sandwich: инструкция по приготовлению

$
0
0

Привет! Меня зовут Таня, и я все еще тестировщик. За то время, что мы с вами не виделись, я успела основать митап QA Amsterdam и дать интервью о том, как докатилась до такой жизни. А сегодня я хочу рассказать о Security Sandwich.

Кот Матроскин говорил, что бутерброд лучше есть маслом вниз: так вкуснее. О том, что такое бутерброд безопасности и как нужно его есть, чтобы не подавиться, эта статья.

Что же представляет из себя классический бутерброд безопасности

Начальная стадия, включающая в себя требования к безопасности, обновление инфраструктуры, соглашения и принципы реализации.

Разработка, включающая внедрение этого добра в итеративную аджайл-методологию, инсайты, основные элементы, постоянные требования и пересмотр.

Go-Live-стадия, включающая код ревью и тестирование на проникновение.

Начальная стадия: все хотят от чего-то защититься. Но от чего?

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

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

Но в целом, если кто-то получит доступ к нашим данным, то он получит все. Включая номера кредиток, имя и домашний адрес. И покупки, конечно же.

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

От кого. Враг может быть как внешним (взломщики всех мастей), так и внутренним (например, обиженный сотрудник).

Какмы защищаемся — военная тайна, конечно же. Но попытки получить доступ к информации у нас происходят постоянно. Из самых безобидных, о которых можно рассказать, — фишинг. Чаще всего это рассылка писем всем сотрудникам компании. Фантазия и осведомленность взломщиков не знает границ. Я всерьез восхищаюсь тщательностью работы, которую взломщики проводят перед тем, как отправить то или иное письмо.

Например, пару месяцев назад они отправляли e-mail в стиле «Привет! Сижу на совещании, не могу говорить, срочно пришли такую-то информацию. Рудольф». Отправлено с айфона.

Вроде бы ничего такого, вот только указанный Рудольф — это наш СЕО. Он в тот момент действительно сидел на совещании, и он действительно время от времени присылает с совещаний такие письма, используя свой айфон.

Когда мы выяснили вот это все, то решили определить стоимость провала: во сколько нам обойдется то, что мы «профакапим» то или иное действие. Обычно это оценивается с точки зрения вероятности, критичности и рисков.

Итак, что у нас должно быть результатом работы на первом этапе

Цели безопасности: определен круг запросов от бизнеса, юристов и регулятивный контекст (какие законы должны соблюдаться и пр.).

Сценарий«А что, если?..»: что произойдет, если наши поставленные цели будут нарушены?

Риски возникновения:берутся исходя из собственного опыта, или аналогичного происшествия у конкурентов, или из законодательных актов.

Разработка: когда же «происходит» безопасность

Традиционно путь к продакшену включает:

  • обсуждения (вербализацию функциональности);
  • требования (перенос того, что нам нужно, в эпики);
  • анализ (разделение эпиков на User Stories);
  • разработку (User Stories становятся функционалом);
  • тестирование (поставленный функционал проходит ревью);
  • деплоймент (функционал доступен пользователям).

На этапе анализамы устанавливаем Definitions of Ready.

Для этого нам нужно:

  • проанализировать имеющиеся активы: что именно мы затронем изменениями, какие новые компоненты будут в этом затрагивании участвовать, насколько критично то, что у нас сейчас есть и как все это вместе повлияет на текущую ситуацию;
  • смоделировать угрозы. Эта часть самая интересная. Она базово включает в себя вопросы о том, как мы можем быть взломаны и что будет при этом задето. Но моделирование угроз само по себе — один из моих любимых этапов. Модели бывают простые и известные типа STRIDE, а есть прикольные и замысловатые типа Persona non Grata. Я очень хочу с этой темой выступить на следующем митапе, но перед этим потренироваться. Если вы хотите присоединиться и послушать про моделирование угроз, то приходите на вебинар 27 ноября, в 20.00 (по Киеву) . N. B. Материал будет читаться на английском языке!
  • предусмотреть действия при взломах. Смягчить? Перенаправить? Избежать? Или принять?
  • предусмотреть обратную связь. Как мы защищались? Как отвечали на взлом? Как восстанавливалась система? Какие у нас могли бы быть альтернативы?

И конечно, теперь у нас появляется новый долг — security debt, за ним теперь тоже надо тщательно следить.

На этапе разработкимы облегчаем себе жизнь с помощью автоматизации, а также:

  • обращаем внимание на зависимости: действуем на упреждение, поддерживаем их в актуальном состоянии и активно тестируем;
  • используем CVE (Common Vulnerabilities and Exposures): списки с уязвимостями постоянно пополняются, и это можно и нужно использовать. Автоматическая настройка сканеров для библиотек и фреймворков никогда не повредит;
  • контейнеры: как ни странно, контейнеризация — это не панацея от всех бед. В них тоже есть уязвимости, и хорошо бы настроить и для них автоматическое сканирование.

Go-Live: знай свою систему!

Вся предварительно проведенная работа была бы бессмысленной, если бы мы не могли увидеть ее результаты. Поэтому после выпуска продукта (или нового функционала) мы обычно:

  1. Визуализируем текущее состояние системы. Это всяческие метрики и статистика в реальном времени, по одному взгляду на которые можно сделать вывод, хорошо ли все идет. Например, у нас в компании в комнате каждой команды установлены большие мониторы (а у менеджеров их и вовсе по несколько штук), на которые выведены дашборды с метриками системы. В любой момент каждый член команды может достоверно сказать, все ли идет как надо. Для этого достаточно поднять голову и посмотреть на монитор на стене.
  2. Делаем структурированные и понятные логи. Хорошим тоном тут считается не засовывать логи в стринги, а логировать нормальные, индексируемые данные. В идеале система логирования должна быть легко инспектируемой и коррелировать со всей системой.
  3. Определяем нормальное и не очень поведение. Мы должны уметь быстро фиксировать, что что-то пошло не так, и иметь стандартную процедуру поведения в таких ситуациях. Например, у нас один раз «кое-что» случилось. Это «кое-что» быстро устранили, но нервов потрепали немало, потому что, во-первых, «кое-что» случилось около полуночи, а во-вторых, процедуры на случай «кое-что» не было. Поэтому действовали по наитию и достаточно хаотично. После устранения «кое-что» провели работу над ошибками и сделали строго определенный регламент поведения на случай повторения, который разослали всем работникам компании: кому звонить первому, кому второму, по каким телефонам, каких клиентов и каким образом информировать и так далее.
  4. Применяем методологию безопасности Shift Left. Эта (и схожая с ней Shift Right) методология набирает все больше популярности, и вот она доползла до безопасности. Суть ее проста: если мы представим процесс разработки как прямую с планированием в точке ноль и выпуском готового функционала в крайней правой точке, то Shift Left — это сдвиг влево. То есть начинаем делать что-то как можно раньше. Так теперь и с безопасностью: раньше начнешь — меньше потеряешь. Поэтому стоит следить за Security Debt, внедрять коллективную ответственность за дыры безопасности в коде и прочие приятные штуки.

В качестве заключения

Security Sandwich кажется простой и незамысловатой вещью, тем не менее в процессе постоянно что-то теряется.

Но, как и с настоящим бутербродом, если убрать нижний слой хлебушка (стадия Go-Live), то весь сыр с колбасой будет постоянно проваливаться вниз, а поддерживать его пальцами практически нереально.

Когда же убираем верхний слой хлебушка (планирование требований, учет соглашений и пр.), то все вроде бы работает. Но если съесть колбасу с сыром недостаточно быстро, они обветрятся и будет уже не тот кайф.

Ну а убрав середину (анализ, разработка, тестирование), получим не сэндвич, а вообще какое-то хлебное недоразумение.

Готовьте ваш Security Sandwich правильно.

И приятного аппетита!

З данських теплиць до харківської IT-компанії. Історія механіка, який став програмістом

$
0
0

Привіт! Моє ім’я Євген Сагач, мені 22 роки. За фахом я механік сільського господарства, ще під час навчання скористався можливістю пройти закордонні практики за спеціальністю. Працював в теплицях, доглядав квіти. Така робота мені подобалася, але вона була сезонною і мала ліміти щодо часу перебування за кордоном. Коли постало питання пошуку майбутньої професії, розглядав різні варіанти. Звернув увагу на програмування. На другому місяці навчання на курсах я знайшов роботу. У мене було шість співбесід, в результаті яких я отримав чотири офери. У статті розповім, як це вдалося.

Данські теплиці і повернення додому

Ще навчаючись на механіка сільського господарства в Дніпровському аграрно-економічному університеті, я вирішив скористатися можливістю взяти участь у закордонній практиці. Мій університет відправляв на такі добровільні практики приблизно до 15 країн світу, налагодивши зв’язки з їхніми офіційними імміграційними органами. Був шанс спробувати себе в роботі у господарствах з вирощування свійської худоби, овочів, фруктів або квітів. Чи не єдина умова відбору — знати англійську на рівні, достатньому для проживання та роботи.

Уперше після третього курсу я поїхав до Польщі, до населеного пункту Olchowiec, але там не сподобалися умови: проживання з 64 іншими людьми в одному домі, по 16 осіб на кімнату, лише три газові плити та шість душових кабінок на всіх, що призводило до довгих черг. Та й збирати у полі лохину досить важко фізично. Наступного разу майже через рік поїхав до Швейцарії, працював у господарстві Brunner beeren неподалік Базеля. Там умови були кращими, жив лише з двома румунами, дуже смачне триразове харчування за рахунок фермера та легша праця на зборі малини (порівняно з Польщею). Повернувшись, вирішив, що знову варто кудись поїхати. Обрав Данію, місто Оденсе, за цією ж університетською програмою. Там один за одним відпрацював два контракти з фермером, тривалістю по півроку кожен.

Робота моя частково полягала в тому, щоб ремонтувати машини, мінітрактори, сівалки — власне, всю наявну в господарстві техніку. Але більшість часу я опікувався квітами, які й складали основу господарства: гвоздиками, петуніями, жоржинами та іншими. Висаджував їх, поливав, упаковував. Господар постачав квіти у кілька найбільших торгових мереж Данії, а також збував на експорт до Швеції, Німеччини та Нідерландів.

Мені працювалося легко і подобалося з кількох причин. Передусім, така праця не вимагала від мене надмірних фізичних зусиль, я не надто втомлювався. Ймовірно, ще й тому, що робочий день у Данії коротший, і за його дотриманням стежать, навіть якщо ти тимчасовий сезонний робітник. Починали працювати о 7 ранку, а о 16.00 я був уже вільний — іноді не помічав, як збігає час. Також праця гідно оплачувалася: 71 крона на годину до вирахування податків для працівника, який працює на умовах стажера, як я (приблизно 284 грн). Для порівняння: мінімальна платня, яку в Данії отримують за цей час, складає 110 крон. Мене цілком влаштовував такий заробіток, його вистачало, аби покрити поточні потреби та й поза тим забезпечити собі певну якість життя. Скажімо, з данських заробітків я придбав собі та дівчині кілька гаджетів (телефони, ноутбук), міг вихідними поїздити Європою, та ще й привіз солідну суму додому. Цей аспект подорожей мені теж подобався, як і загалом життя у незвичній для себе країні, спілкування з новими людьми.

Умови проживання в будинку фермера теж були пристойними, якщо порівнювати з тією ж Польщею. Усі восьмеро працівників мешкали у двоповерховому будинку, кожен у власній кімнаті, мали спільну кухню, два душі та дві вбиральні на всіх. Кімната була просторою, близько 30 квадратних метрів, як теперішня однокімнатна квартира, яку я винаймаю. Платили по 1500 крон за кімнату.
Утім, я розумів, що працювати так все життя мені не вдасться. Хоча й не був проти того, аби лишитися, якби це було можливо. Справа у тому, що у статусі практиканта таких контрактів можна відпрацювати лише два, а я вже вичерпав свій ліміт. За контрактом звичайного робітника можна було відпрацювати вісім років, щоб отримати дозвіл на проживання, та моєму шефові було невигідно брати постійних робітників: по-перше, їм слід платити на 25 відсотків більше, ніж інтернам. По-друге, через яскраво виражену кількамісячну сезонність не так багато часу відводилося на працю.

Тож останніми місяцями свого перебування в Данії, навесні цього року, я почав розмірковувати про те, ким працюватиму далі. Викладачем англійської? (Гарно знав мову, для поїздки до Данії належало скласти мовний тест КЕТ. Також уже в Данії почав глибше вивчати англійську з репетитором — у чужій країні хочеться знати мову на такому рівні, щоб не потрапляти до ситуацій, коли всі жартують, а ти не розумієш, про що йдеться). Це можливо, та особливих задатків педагога я не мав. Ще в університеті я добре розв’язував різні логічні завдання, навіть допомагав одногрупникам із математикою. Коли перебирав ймовірні варіанти, збагнув, що IT може бути опцією для мене.

Співбесіда і початок навчання

Мій друг мав бажання повчити Python і запропонував зробити це разом. Почали вивчати ще за два місяці до закінчення контракту в Данії в післяробочий час, спочатку пройшли курс Python for everybody, потім почали читати Learning Pythonавторства Mark Lutz. У результаті йому не зайшло, а мені сподобалося, тож вирішив занурюватися в тему. Почав читати профільні ресурси, різні статті на ДОУ, якось побачив статтю про Mate Academy. Мене зацікавив їхній підхід до навчання: якщо на звичайних курсах платиш гроші наперед, вони тебе навчають, але ніхто нічого не обіцяє, то тут я мав гарантію, адже плачу гроші лише у разі успішного працевлаштування. Подумав собі: навіть якщо, в найгіршому разі, нічого не вийде, то максимум, що втрачу, — це кілька місяців життя. Коли ж усе складеться — спробую себе в новій професії.

З таким настроєм ще в останні дні свого перебування в Данії вирішив податися, написав їм з проханням дати мені тестове завдання. Склав вступний тест: він був з JavaScript (досить легкий, на розуміння базових принципів роботи з масивами). Для тих, хто зовсім не мав відповідного досвіду (а я був саме таким, знав лише синтаксис Python, міг розв’язати на ньому суперпрості задачки), організатори пропонували скинути навчальні матеріали завчасно (мені, наприклад, порадили пройти курс на freeCodeCamp), а за два тижні, яких би мало вистачати на їхнє опрацювання, надсилали задачки.

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

Початок навчання

Навчання відбувалося онлайн у групі з 30 осіб (зідзвонювалися в Zoom-і). Я вибрав напрямок фронт-енд, оскільки поставив собі за мету стати фул-стек розробником, а досвідчені знайомі порадили в такому разі починати з фронту. Зранку о восьмій годині нам розсилали задачки на JS — така собі розминка мозку перед лекцією. Потім розпочиналася двогодинна лекція.

Уже з перших днів навчання я зрозумів, що значно відстаю від групи, і мені доведеться працювати більше, ніж решті. Можливо, не всі мали бекграунд, але я помічав, що одногрупники швидше засвоюють інформацію. Зразу себе на це налаштував: щодня прокидався о восьмій ранку і засинав о першій ночі. Весь день проводив за комп’ютером. Будь-яке соціальне життя тоді було відсутнє — я суто навчався. Навіть переїхав жити до батьків, аби не гаяти часу на приготування їжі та домашні клопоти. Для більш поглибленого вивчення час від часу просив викладача або одногрупників дати посилання на якісь цікаві статті стосовно тем, які ми розглядали.

І це дало свої результати. Інколи ми маленькими групками зідзвонювалися з учасниками, щоб обговорити певну тему. Якоїсь миті стало зрозуміло, що під час таких розмов у мене найчастіше питають поради. Мені писали, дзвонили, прохаючи щось пояснити. Як на мене, секрет тут очевидний: у кількості часу, який я присвячував навчанню. Хоча кожен виділяв багато часу на навчання, люди, що працюють або навчаються у ВНЗ, все одно можуть присвячувати цьому по 6 годин щодня максимум. Я ж міг собі дозволити всі 16. Було трохи складно підтримувати такий ритм протягом тривалого періоду, але я не та людина, яка здається на півдорозі.

Шість співбесід, чотири тестових і три офери

Так сталося, що я працевлаштувався після двох з половиною місяців, ще не закінчивши повний курс навчання. Отримав три офери — і всі три були не на позицію React девелопера. Один — на Vue.js девелопера, другий — на Angular девелопера, а третій трохи стосувався Реакту, але з більшим нахилом у бек-частину розробки (такий собі фул-стек :).

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

У CV я вказував абсолютно всі технології, якими володів, навіть якщо рівень мав не надто високий. В cover letter потрібно було описати, чому саме ти «perfect fit» для даної вакансії, а також вчергове наголосити на своїх перевагах порівняно з іншими кандидатами. Більшість ейчарів писали мені на Djinni, куди я просто додав своє портфоліо з трьох проектів, які ми виконували в академії (два лендінги та SPA TODO app).

Я одразу був готовий до переїзду, тож розглядав вакансії у різних містах. На моє здивування писати стали часто — якимось дивом я за тиждень потрапив на 12-темісце в топі у Дніпрі (з-поміж 200 кандидатів). У Києві ж мій рейтинг був значно скромнішим — я тримався на 160 місці. Зауважив, що роботодавцям подобалося моє знання англійської — вони наголошували на ньому під час співбесід. Згодом щойно запитували про знання іноземної, я сам пропонував нею говорити, оскільки зрозумів, що це моя перевага.

За результатами надісланих резюме мені відповіли три компанії з Одеси, Києва та Дніпра (BIIR, E-consulting та LoopMe). Співбесіди було заплановано зі всіма трьома, але встиг пройти лише з компанією, яка відгукнулася з Дніпра (оскільки з двома іншими співбесіди мали відбутися наступного тижня). У ході співбесіди зрозумів, що вони потребують не звичайного джуніора, а людини з досить великим об’ємом знань (як мені здалось, можливо, навіть на рівні мідла). Тестовим завданням було написати код, який би збирав інформацію про поведінку користувачів на сайті та виводив цю інфу у вигляді теплової карти для перегляду адміном. На виконання цього завдання давався тиждень — у принципі, достатньо часу, аби розібратися і зробити карту. Але водночас я розумів, що іншому, досвідченішому кандидату це ж завдання може датися простіше, а я, вникаючи в деталі, лише вб’ю тиждень часу і залишуся ні з чим, і разом з тим не матиму змоги виконувати інші тестові. Тож відмовився.

Мені за декілька днів написало досить багато ейчарів на Djinni, яким я навіть не надсилав своє CV. З багатьма з них я мав інтерв’ю, але виділю лише три, від яких отримав офери.

У компанію зі Львова RestTech треба було написати SPA, який би працював з Spotify API, був би схожий на Spotify та мав подібний функціонал. Успішно впорався за вихідні і отримав офер. Ще два офери були з Харкова, в обох випадках для компаній був дуже важливий problem solving skill. У першій flow.ai (фул-стек позиція) я мав лише співбесіду, на якій перевірили мої технічні здібності та те, як себе поводжу під тиском, шляхом психологічного пресингу під час співбесіди. Наприклад, мені задавали питання, які не стосувалися моєї спеціалізації, і при цьому підганяли з відповіддю. Після цієї співбесіди я одразу ж отримав офер. У другій компанії Ukad, що в Харкові (позиція Angular розробника), я спочатку виконав тестове завдання на JS (задача на логічне мислення), а потім пройшов співбесіду з CTO, тімлідом та ейчаром компанії, в якій також багато уваги приділялось тому, як я вирішую поставлені завдання. Отримав офери від обох компаній, але вибрав останню, оскільки там мені запропонували досить гарні умови розвитку як спеціаліста, а ще я об’єктивно не був готовим до роботи на позиції фул-стека.

Переїзд до Харкова та плани на майбутнє

Якщо підсумувати досвід співбесід, які я пройшов, то запитання завжди були різними, і те, що не питали на одній співбесіді, могло бути дуже важливим на іншій. Але все ж спільні запитання траплялися, і їх можна умовно поділити на дві групи: запитання стосовно HTML/CSS/JS стеку, що є досить очевидним, адже це основи, і друга група запитань стосувалася побудови логічного ланцюжка з вирішення тієї чи іншої проблеми (наприклад, як би я реалізував кешування в додатку, схожому на Інстаграм, пояснити, чому саме таке рішення, в чому його плюси та мінуси та чи я бачу можливі шляхи оптимізації цього рішення).

Від себе хотів би порадити тим, хто лише почав подаватись на вакансії, бути наполегливими та в жодному разі не здаватися після того, як відмовлять 10-20або й більше разів. Також для мене спрацювало те, що я наголошував на своїх перевагах, особливо якщо це англійська (всі компанії, в яких я проходив співбесіди, хотіли кандидата з дуже гарним рівнем англійської). Ще одне загальне спостереження: не варто хвилюватися на співбесідах, адже якщо вас запросили, то ви потрібні цій компанії не менше, ніж вона вам ;)

Так, я зібрав речі і переїхав до Харкова. Наразі працюю на зарплатні, яка приблизно на третину вища за середню по місту у розробників з тими самими даними, що й у мене (згідно зі статистикою ДОУ). Втім, вона очевидно менша за ту, яку я отримував в Данії на квітах. Проте важливим фактором для мене тут є стабільність, можливість вирішувати, в якому напрямку будувати кар’єру в майбутньому. Не можу стверджувати, де житиму і чим займатимуся протягом наступних років (я досить молодий, і в мене багато чого попереду), але зайнятість у IT відкрила переді мною нові перспективи та розуміння того, що я принаймні можу спробувати себе в Україні. На роботі я знайомлюся з цікавими людьми — подекуди вони нагадують мені мешканців Данії з їхньою відкритістю до світу та приязним спілкуванням. Загалом, спілкуючись із колегами та клієнтами, які приїжджають з-за кордону, я утверджуюся в думці, що у нас не все так погано, і є можливість реалізовувати себе вдома.


Дякуємо за допомогу у підготовці статті Ярославі Тимощук.

Ищем причины овертаймов в команде: чек-лист для менеджера

$
0
0

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

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

Процесс составления/обновления расписания проекта

Возможно, самая первая область для анализа. Когда вы думаете о сверхурочной работе, это всегда вопрос контроля выполнения проекта и, как следствие, расхождения между планом и фактом. Так почему бы не начать с точки создания этих самых планов?

Логично, что менеджер проектов должен разбираться не только с метриками и информацией, но и с процессом как таковым. Ниже представлен ряд вопросов для проверки:

  • Кто участвует в сессиях планирования?
  • Кто предоставляет оценки длительности работ?
  • Существует ли сессия планирования как таковая? Если да, можно ли оценить подход и агенду?
  • Какие единицы измерения используются командой для оценки? Все ли понимают их масштаб одинаково?
  • Что команда показывает клиенту в качестве результата процесса составления расписания?

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

  • Технический лидер команды оценивает работу, которую должны будут выполнить менее опытные члены команды.
  • Не используются сессии планирования, встречи по запуску проекта или любые другие точки синхронизации общего понимания сложности проекта.
  • Не используется управление рисками.
  • Менеджер проектов путает понятия «оценка работ» и «расписание проекта».
  • Используются техники оценки работ, не отвечающие запросам проектной среды.
  • Масштаб оценок понимается по-разному в команде проекта.

Пример из практики.Небольшой проект на 500 человеко-часов. В проект я пришел на половине расписания, с удивлением обнаружив команду в мыле. Оказалось, что расписание составлено путем деления выделенных на дисциплину часов на 8 и на количество людей в дисциплине. Я остановил выполнение проекта и немедленно провел сессию планирования. На этой сессии команда перепланировала оставшиеся задачи, мы расставили их зависимости между собой, оценили технические риски по задачам и на уровне всего проекта. Клиенту был предоставлен расширенный проектный отчет со всеми возможными вариантами поставок по датам, содержанию и бюджету.

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

Проработка содержания проекта

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

Если брать управление изменениями в проекте в целом, то именно изменения в содержании проекта, как правило, влекут за собой перепланирование проекта в целом или, как минимум, значимых его частей (риски, бюджет, расписание и прочее). Что интересно, подход, который исповедуется в проекте, практически никак не страхует команду от сверхурочной работы. Предиктивные подходы формируют давление жесткими ограничениями, тогда как для гибких подходов характерна некорректная трактовка «гибкости», что может вести буквально к ежедневным изменениям работ в проекте.

Если вы сталкиваетесь с проблемой проработки содержания, можно воспользоваться следующими вопросами:

  • Существует ли процесс управления изменениями в проекте?
  • Осведомлены ли все участники проекта о том, каким образом обрабатываются изменения в проекте?
  • Есть ли на проекте steering committee? Прописана ли его роль в разрешении конфликтов, связанных с изменениями в содержании?
  • Как выглядит сессия product backlog refinement, если она есть?
  • Каковы обязанности и роль владельца продукта, если таковой имеется?

Основываясь на своем опыте, выделю наиболее часто встречающиеся проблемы:

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

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

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

Управление требованиями

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

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

  • Всем ли вовлеченным сотрудникам известна цель проекта/видение продукта?
  • Используются ли гибкие цели при построении дорожных карт? Как они формулируются?
  • Какая документация используется для трассировки требований?

Я выделил управление требованиями отдельным разделом, так как считаю, что именно при работе с требованиями ключевой проблемой является отклонение от первоначально поставленных целей или видения. Маппинг изменений требований на цель проекта, спринта, видение продукта делает дискуссию конструктивной для всех участников и позволяет найти компромисс вместо раздувания рабочих часов.

Управление вовлечением заинтересованных сторон

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

Я неоднократно становился свидетелем «мотивирующих» диалогов директоров или собственников компании с командами в духе «Ребята, я же знаю, что вы молодцы/звери/машины». И ребята, разумеется, не могут подорвать веру начальства в себя каким-то отказом посидеть до 10 вечера над срочной поставкой клиенту. Я не буду в тысячный раз пересказывать все возможные последствия переработок, скажу лишь, что последствия такой тактики выжженной земли впоследствии ложатся на плечи именно проектного менеджера, который вынужден будет работать с выгоревшей и уставшей командой над проектом, которому все желают скорейшей смерти.

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

  • Возникают ли ситуации, когда клиент ходит к вашему начальству с просьбой «продавить» изменения в проекте?
  • Является ли проектный менеджер конечной точкой контактов с клиентом? Если нет, какие решения принимает аккаунт-менеджер?

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

  • Существует ли список всех заинтересованных сторон проекта?
  • Существует ли градация заинтересованных сторон проекта? На что она влияет?
  • Используются ли продвинутые модели анализа стейкхолдеров (матрицы, когнитивные карты)? Если да, каким образом эти артефакты обновляются?
  • Каким образом собирается обратная связь от заинтересованных сторон?
  • Каков сейчас уровень удовлетворенности разных стейкхолдеров от проекта? Какие последние действия предприняты для изменения этого показателя?

Наиболее распространенные практические проблемы:

  • Команда не знает всех стейкхолдеров, кроме спонсора проекта («Мы работаем вот с этим владельцем продукта»).
  • Взаимосвязи между разными группами стейкхолдеров не анализируются.
  • Репортинг осуществляется путем добавления всех заинтересованных лиц в копию письма (более 15 человек).
  • Обратная связь по проекту или его результатам собирается только с малой части заинтересованных сторон, чаще всего с одного человека.

Пример из практики.После каждого демо по проекту команда несколько дней оставалась работать сверхурочно. Причиной этого явления было то, что на демо приходили высокопоставленные стейкхолдеры, мнения которых о продукте не спрашивали ни разу, кроме как на самих демо. Никакая работа с ними не велась. Решением стал сбор общего steering committee, обсуждение ролей и интересов каждого стейкхолдера, маппинг стейкхолдеров (более 10 человек) на матрицу «влияние — интерес». Например, несколько человек приходили на демо, потому что это был их единственный источник информации о проекте.

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

Взаимные уступки

Взаимные уступки (лучший перевод trade-offs, который мне удалось придумать) могут относиться ко всем вышеперечисленным областям. В широком смысле я отношу взаимные уступки к части работы с заинтересованными сторонами, так как самый распространенный trade-off — это соотношение бизнес-задач и технических задач. Вспомните, например, как определяется длина спринта в Scrum: одним из критериев является как раз trade-off между бизнесом (которому нужно побольше и побыстрее) и технологией (нужно подольше делать и поменьше распыляться).

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

Воспользуйтесь следующими вопросами:

  • Используется ли на проекте понятие технического долга? Все ли ознакомлены со смыслом?
  • Каким образом команда проекта управляет техническим долгом (визуализация, мониторинг, репортинг и прочее)?
  • Включена ли работа над техническим долгом в повестку сессий планирования?
  • Каким образом ведется приоритизация задач с учетом накопленного технического долга?
  • Каким образом технические задачи включаются в список работ? Насколько сильно сопротивляется бизнес и насколько команда способна коммуницировать потребности?
  • Включают ли дорожные карты проекта работу над техническими enablers?

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

Например, возникли вопросы к быстродействию системы. Вместо создания бессмысленных карточек типа «я, как система, хочу работать быстрее» (да-да, такое, как оказалось, на проекте бывало) внесли пометки, чтобы отличать задачи, связанные с техническим долгом. Во-вторых, немного позже разработали и утвердили definition of done, отдельным пунктом которого стало: «Не создано технического долга, или создан элемент технического долга со сложностью не более 5 стори-пойнтов». Команда перестала работать над ним сверхурочно и сделала большой шаг на пути к zero debt policy.

Система метрик

Множество копий сломано и еще будет повреждено в спорах на тему того, нужны ли метрики в проектах. Практикующим менеджерам ответ понятен: наличие системы метрик позволяет настроить так называемую «приборную доску» проекта, уменьшить количество избыточных коммуникаций, быстро и точно репортить статус проекта как внутренним, так и внешним заинтересованным сторонам. Проблемы начинают возникать, когда система метрик начинает напрямую касаться членов команды. Подстегиваемые жесткими предельными значениями метрик, сотрудники будут впахивать, работая на метрики больше, чем на успех проекта. Ну или же просто сменят обстановку.

Предлагаю обратить внимание на следующие аспекты:

  • Влияют ли проектные метрики на сотрудника напрямую (пересмотр зарплаты, получение отпуска и прочее)?
  • На какие области проекта направлены метрики? Направлены ли они на сотрудника, команду, проект в целом?
  • Кому и как репортятся проектные метрики?
  • Какие решения принимаются на основании проектных метрик?
  • Кто имеет доступ к проектным метрикам?

На практике часто встречаются следующие случаи:

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

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

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

Вместо послесловия

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

Viewing all 2421 articles
Browse latest View live