Quantcast
Channel: Найцікавіше на DOU
Viewing all 8482 articles
Browse latest View live

Чи є життя після macOS, або Як я переїхав на Linux десктоп і не шкодую

$
0
0

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

Початок

З 2007 по 2015 я працював на Windows. На роботі в мене спершу був десктоп з Windows NT 2003, здається. Потім я переїхав на ноутбук ThinkPad. NT 2003 оновили до Windows 7. На той час я 100% працював з Java, тому проблем у мене не виникало.

У 2015 я змінив роботу, і там отримав MacBook Pro 13″ 2015 у мінімальній комплектації, з 128 GB SSD та 8 GiB RAM. Я досить швидко освоївся та нарешті збагнув, чому всі розробники на конференціях використовували макбуки та писали про них в статтях, туторіалах тощо. Це ж юнікс для людей! Жодних проблем зі встановленням усіляких SDK, бібліотек, інструментів. Жодних проблем з компіляцією того, що для Windows потребувало б якого-небудь Cygwin або MinGW. Чудовий UI, наявність усіх необхідних програм. Усе круто, я був задоволений, мені подобалось користуватися моїм ноутбуком. Особливо тачпадом — він не люфтив, точно передавав усі рухи та жести. Спочатку я продовжував за старою звичкою користуватися мишею, та потім відмовився від неї взагалі.

Минали роки. Пам’ять SSD засмічувалася XCode, образами емуляторів, кешами Gradle та npm. Швидкодія знижувалась, оперативної пам’яті для IntelliJ майже завжди не вистачало, система йшла у своп, але я це все терпів. Тому що зручно, тому що звик і тому що тачпад.

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

У 2017 я почав замислюватися про апгрейд, адже вже тоді стало очевидно, що 8 гігабайт пам’яті абсолютно недостатньо для комфортної розробки та існування. Проте Apple почала подавати тривожні знаки: макбук 2016 року випустили без портів, без MagSafe та, як виявилося за певний час, ще й з поганою клавіатурою. Функціональні клавіші замінили на беззмістовний тачбар.

Незважаючи на те що я був готовий витратити 2k+ баксів за оверпрайснутий шматок алюмінію з нульовою ремонтопридатністю та апгрейдабельністю, зламані клавіатури мене зупинили, тож я вирішив чекати. Спочатку покладав надії на 2017 рік, потім на 2018, потім на 2019.

Сумніви

У роки очікування я щомісяця читав на HN пости про те, як все погано у нових моделях, клавіатурине покращуються, процесори перегріваються та тротлять, порти вбивають пристрої, шлейфи переламуються, тачбар не потрібен — і взагалі, схоже, що Apple більше не цікаво виробляти якісну техніку. Люди скиглили, проте продовжували їсти кактуси. Хтось писав про свій досвід переїзду на Linux або Windows, хтось наважувався купити новий ноутбук та страждав. Я ж продовжував абияк існувати зі своїм улюбленим, але таким повільним макбуком та мріяти про той день, коли за три куски я зможу придбати якісну техніку.

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

Увесь цей час у мене під столом стояв десктоп із Windows. Нічого особливого — core i7 4770, 16 GiB RAM, AMD RX 570. Там я грав у Counter Strike, писав гітару та голос (адже macOS не підтримує мою досить стару звукову картку, а Windows 7 — підтримує). Час від часу мене накривало, і я думав про те, щоб оновити цей десктоп новим залізом і поставити туди хакінтош, але всі ці рухи якось не надихали. Замолоду я полюбляв порпатися з кряками та іншим варєзом, але зараз хотілося просто натиснути одну кнопку та отримати робочу систему.

Я навіть розглядав придбання старого відра (Mac Pro), але абсолютно неадекватна вартість ($3k) купи застарілого брухту мене зупинила. Моноблоки теж не радували вартістю, mac mini — швидкодією. До macOS я вже звик, та змінювати щось не хотілось абсолютно. Проте регулярне користування вінодвсодекстопом, де все працювало дуже швидко, почало мене підточувати, і зерна сумнівів дали серйозний урожай.

Я замислився про те, щоб поставити на десктоп лінукс і працювати за ним. Люди ж якось живуть? Та й 2019 рік надворі, прогрес не стоїть на місці. Коли моя шхуна ще ходила океанами аутсорсу, всі наші розробники працювали за лінукс десктопами — в когось Mint, в когось Ubuntu — і почували себе чудово. Урешті-решт я вирішив спробувати. Вирішальним фактором виявилось те, що для хакінтоша потрібна була флешка на 16 гігабайт, а в мене була тільки на 4. Шукати чи купувати нову флешку я не хотів, тож пішов на DistroWatchі почав роздивлятися, що там зараз у тренді.

Муки вибору

Я звузив коло дистрибутивів до deb-based, адже, на мій суб’єктивний погляд, вони значно популярніші за RPM та інші арчлінукси і генту. З CentOS я працював багато, та, як правило, імовірність знайти вирішення своєї проблеми на Stack Overflow для CentOS нижча. Тож я навіть не дивився у бік не Debian-based дистрибутивів (окрім Manjaro). Отож, наслухавшись мудрих порад з DOU та ще раз переглянувши рейтинги DistroWatch, я вирішив почати з MX.

Завантажив дистрибутив з офіційного сайту, завантажився з флешки, за 5 хвилин встановив. Я вже не пам’ятаю точно, що не запрацювало, можливо, застарілі версії деяких потрібних мені пакетів (MX базується на Debian), але з якоїсь причини MX мене не влаштував. Далі я перейшов до активно рекомендованого на DOU Manjaro. Завантажив варіант з Xfce, встановив. Після старту виявилося, що не працює Wi-Fi — ніяк не хотів підключатися до моєї домашньої мережі. Порпатися з пошуком необхідних драйверів не було жодного бажання, тож я перезавантажився у Windows та пішов шукати інший дистрибутив.

Я дещо засмутився, адже мені здавалося, що периферія 10-річноїдавності мала б 100% працювати. На секунду я подумав, що насправді лінукс на десктопі такий самий, яким був раніше — без колупання в конфігах нічого не працюватиме, і нічого не змінилося. Тож я вирішив взяти найпопулярніший дистрибутив, тобто Ubuntu.

Ubuntu було завантажено та встановлено, здається, все запрацювало, і я навіть почав налаштовувати SDK, оточення і таке інше, але потім зненацька зрозумів, що GNOME або ж Unity, чи як в них називається графічна оболонка, мені зовсім не до вподоби. Тобто взагалі не подобається. Вони там ще напхали якихось зондів, рекламу і місцевий апстор, коротше кажучи, якось воно взагалі не зайшло, і хоча я вже встановив IntelliJ, налаштував RVM та викачав проекти, все одно вирішив відмовитися.

Я знову засмутився. Невже доведеться купувати флешку на 16 гігабайт та ставити хакінтош? Чи апгрейдити макбук? Але щойно я його відкрив та запустив IntelliJ, то знову сповнився рішучості спробувати лінукс ще раз. Загадавши, що у трьох розробників з моєї шхуни було встановлено Mint, я вирішив дати йому шанс. Як завжди, інсталяція закінчилася за 5 хвилин, і тут — о диво! — під час старту системи я почув звуки привітання!

Невеличке пояснення — чому це мене так здивувало? Річ у тому, що колонки та навушники в мене під’єднано до звукової картки M-Audio Fast Track Ultra. Виробника вже давно купив AVID, картку не підтримують з 2012 року, драйверів на новий Windows та macOS вище Snow Leopard нема і не буде. А тут Mint підхопив її, більш-менш коректно сконфігурував входи-виходи і встановив як аудіопристрій за замовчуванням. Моє серце розтануло. Автоконфігурація звукової картки означала, що я тепер можу жити в одному оточенні — працювати, грати на гітарі та в CS:GO, без перезавантажень, реєстрації та СМС.

Зовнішній вигляд оболонки Cinnamon мене теж дуже потішив — із всіх протестованих (GNOME, KDE, i3) ця виявилась найгарнішою.

Робоче оточення

Коли я ще ходив під вітрилами на своїй шлюпці, то бачив, що один з кофаундерів, який працював якраз на Mint, мав проблеми зі Skype — MS чи то не підтримував десктопну версію, чи підтримував її погано, одним словом, йому доводилося працювати у Web-клієнті.

Виявилося, що зараз завдяки тому що весь софт Electron-ізовано та запаковано, проблем з програмами для лінуксу немає жодних. Майже в усіх виробників, програмами яких я користуюсь, є версія для Linux, яка функціонально нічим не відрізняється від інших платформ. Тож з точки зору програм переїзд був простим та безболісним. Зупинюся на задачах, аби було приблизне розуміння, що мені потрібно: щодня я займаюся розробкою на Java, Ruby on Rails, Python, Node.js та трішки фронтендом. Отож, що я використовував на macOS та що так само використовую на Linux:

  • IntelliJ IDEA — основний інструмент, який годує мене вже десяток років. Працює, звісно, без проблем, тому що JVM.
  • Telegram, Skype, Slack, Viber, Zoom — месенджери та відеоконференції теж всі працюють без проблем, що нативні, що з-під електрону.
  • Браузери — Firefox, Firefox Developer Edition, Firefox Beta, Firefox Nightly, Iridium. Я навіжений і для кожного замовника чи проекту тримаю окремий браузер, щоб не перетиналась пошта, акаунти для браузерів тощо. Тут теж все зрозуміло — працює як треба. На macOS я теж користувався Firefox. Так, я знаю про профілі, але вони мені не подобаються.
  • Steam — пограти в Counter Strike: Global Offensive (який працює під лінуксом нативно).
  • Discord — працює ок, але крашиться раз на годину. Проблему маю не лише я. Жити можна.
  • Postman, VS Code (майже не використовую) — абсолютно аналогічні тому, що є під Windows aбо macOS. Слава електрону.

Ось і весь десктопний софт, який я використовую щоденно. Міграція минула без проблем, буквально за один вечір. MS Office в мене не встановлено, вистачало Numbers. Натомість в Linux є LibreOffice, ніби норм, але я ним не дуже користуюсь — немає потреби. Фотошоп мені не потрібен та не був встановлений на macOS. iTerm успішно був замінений місцевим терміналом. Я не користувався особливостями iTerm, тому мені норм. Зверху поставив Oh My Zshз такими самими плагінами та темами, як і на macOS. Крім того, звісно, було встановлено купу софту для розробки: перш за усе RVM, потім Node, Pyenv, Docker, нативні бібліотеки для PG/MySQL/Redis і т. д., те, що під macOS не завжди встановлюється без нюансів (хоча команда brew працює круто, тут жодних заперечень).

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

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

Система

Найболючішим питанням при зміні оточення для мене виявилася зміна хоткеїв, до яких я звик. На лінуксах вони, звісно, досить сильно відрізняються від macOS. Я вирішив спробувати переналаштувати клавіші під ті, які мав на macOS. Для цього я замінив місцями клавіші Win та Alt (клавіатура у мене з Windows-розкладкою, HyperX Alloy FPS на MX Red), перебив Alt+Tab на Win+Tab, вихід з програм на Win+W, одним словом — влаштував собі macOS для бідних :) Все це можна було зробити через UI, без редагування конфігурації.

Також вирішив питання з розкладкою. На macOS я користувався модифікованою розкладкою Іллі Бірмана, яка містила третій шар для російських букв ы э ъ ё, таким чином для набору текстів кирилицею мені не доводилося переключатися між українським та російським варіантами клавіатури. Приблизно тиждень я не поспішаючи шукав таке ж рішення, врешті-решт знайшовта підправив від себе (тут довелося трішки попоратися з конфігами). Переключення локалі по Caps Lock налаштовується через UI.

Аналог f.luxназивається Redshift, хоча виглядає він не так гарно (а радше — взагалі не виглядає, для GUI треба встановлювати окрему програму). Для музики є досить адекватний Rhytmbox. Система оновлює себе нашим улюбленим apt-get update && apt-get upgrade — взагалі без проблем. Ті, хто мали справу з побудовою докер-образів, не пропадуть. Томи з NTFS автоматично підхоплюються на запис без додаткових налаштувань. Wi-Fi працює як треба, хоча деколи (раз на тиждень, або ще рідше) відвалюється та потребує перезапуску. Профілі для VPN можна встановлювати відразу у .ovpn форматі і відкривати через мережеві налаштування — не потрібно ставити ніяких TunnelBlick!

На жаль, не всі програми можуть підхопити мою круту звукову картку з не менш крутим конденсаторним мікрофоном як пристрій введення. Виведення — так, тут без проблем. А ось введення — ні. Я гадаю, що це якось вирішується, але поки що не хотів витрачати на це час. У мене є веб-камера з хорошим мікрофоном (яка, до речі, теж запрацювала з коробки). Але на macOS звукова картка взагалі не працювала, тому до лінуксу тут в мене претензій жодних. Хоча може якось знайду час, зберу докупи всі ці Jack, ALSA, PulseAudio та інші штуки — і радуватиму співбесідників оксамитовим голосом.

Зі шрифтами та згладжуванням у мене проблем немає. Працюю я за тим самим екраном, який підключав до макбука як зовнішній (Dell U2415, 16:10, 1920×1200), тож різниці не помічаю. Додаткових налаштувань я не робив. Suspend/resume працює без проблем. Кажуть, що на ноутах з цим негаразди, підтвердити чи спростувати не можу. На десктопі аптайм кілька тижнів стабільно. Перезавантажуюсь у Windows лише для звукозапису.

Ось як виглядає мій десктоп. Основні інструменти — IntelliJ IDEA та купка браузерів. CS:GO у віконному режимі, щоб розбавити воллпапер, граю я у фулскріні, звісно.

Проблеми

Декілька проблем з софтом та системою, які я так і не зміг вирішити або вирішив не інвестувати в них час:

  1. Відсутність ⌘+c/⌘+v. За роки роботи я вже настільки до цього звик, що змінити м’язову пам’ять було складно. В терміналі можна налаштувати цю комбінацію, але для всієї системи — зась. Доводиться пам’ятати, де ти зараз знаходишся, та натискати відповідні клавіші.
  2. Cinnamon чомусь вважає ок вішати на F10 системний хоткей (виклик меню). Довго не міг зрозуміти, чому в мене не закривається mc. Як відключити цю поведінку для всієї системи, не лише для терміналу, не знайшов.
  3. Те саме, тільки для Alt+клац мишкою. На macOS в IntellIJ таким чином працювало блочне виділення, а тут викликається якийсь системний менеджер вікон — абищо, коротше кажучи.
  4. Неможливо нормально відрегулювати швидкість миші. У мене миша Razer Deathadder, там досить висока роздільна здатність та, відповідно, висока швидкість курсору. Мінімальна швидкість для мене все одно занадто висока. Спробував щось там конфіжити через XInput, проте не допомогло. Урешті-решт просто змирився і забив, проблем руками буде менше. CS:GO вміє читати сирий потік з миші, тож там можна відрегулювати все як треба.
  5. В IntelliJ не працює мапінг клавіші win для хоткеїв, тобто не можна собі зробити ⌘+n для пошуку класу, потрібно CTRL+N натискати. Вже звик.
  6. Середня кнопка миші працює як CTRL+V, ще не знаю, як це відключити, але й не надто шукав.
  7. Спелчекер в FF якось дивно перемикає мови. Іноді не перемикає взагалі та детектить англійську як кирилицю і навпаки.
  8. За відчуттями, FPS в CS:GO дещо нижче, ніж під Windows, 100 проти 150-200,десь так. Хоча я все одно не перезавантажуюся та катаю з хлопцями під лінуксом. Драйвери на відекарту AMDшні.

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

Ітогі падведьом ©

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

Доки писалася та версталася ця стаття, Apple випустила 16″ макбук з фізичною кнопкою Esc та виправленою клавіатурою, що не ламається від крихт та пилу. Носити такого велетня у рюкзаку я не хочу, та й за macOS я, чесно кажучи, не надто сумую. Тачбар не потрібен, USB-C не потрібні — ну ви зрозуміли.

Також запропонували новий Mac Pro за космічним прайсом (з люто оверпрайснутою RAM), але віддавати $6k за залізо, яке, за відчуттями, навряд буде швидшим за мій десктоп, щось не хочеться. Та й, загалом, $6k для мене — це надто багато за залізо (навіть якщо це не включало оверпрайс за яблуко, а було лише ціною власне комплектних деталей). Я, на жаль, ще не маю такого рівня статків.

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

...

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

Тепер я можу зробити однозначний висновок — лінукс на десктопі живе. Можливо, ви маєте свої вимоги до софту, який є винятково під Windows або macOS, але я особисто вважаю, що для бекендера/дата-саєнтіста/фронтендера/андроїд-розробника Linux є відмінним вибором та повноцінною заміною macOS.

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

Швидкість та апгрейдабельність

А ось що мене тішить у новій робочій станції понад усе — то це швидкість її роботи. Я неодноразовописавпро важливість хорошого робочого заліза, швидкості збірок та компіляцій для щоденної роботи. У мене старий процесор — core i7 4770, лише 16 гігабайт пам’яті, дешевий SSD Crucial (адже матплата в мене теж стара та не вміє завантажувати систему NVMe, до того ж немає m.2 слоту), і все це працює суб’єктивно просто в рази швидше за макбук (на якому, між іншим, процесор на кілька поколінь старший та й SSD, напевно, не гірший). Настільки швидше, що я не чекаю, доки відкриється проект в IntelliJ, браузери відкриваються моментально, збірка Webpack навіть не встигає підняти оберти штатного вентилятора, і взагалі все гаразд.

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

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

Тепер я знаю, що якщо завтра мені потрібно буде додати потужності, то я зможу просто купити новий процесор або матплату + процесор. Поставити одне замість іншого, і життя знову заграє швидкістю. Не потрібно думати про мотлох на диску — якщо треба буде збирати товсті образи або перемелювати бігдату, я просто прикуплю SSD за $50 і буду щасливий.

Я ніби повернувся назад у дитинство, коли за браком коштів доводилось лише дивитися на прайс-листи, огляди та рекламні проспекти у журналах «Компьютерное обозрение» та CHIP, тільки тепер можна купити все, що там продають, і зовсім не потрібно чекати, доки Apple поверне модель 2015 року, з нормальними портами, магсейфом та можливістю проапгрейдити або відремонтувати пристрій.

Якщо ти, читачу, все ще сидиш за старим макбуком, я гадаю, що ти тепер знаєш: за межами macOS життя є.

Fin.

Якщо вам сподобалося, як я пишу, то долучайтеся до мого телеграм-каналу.


«Зарплата інженера-програміста в оборонній сфері — $600-700». Як працюють військові розробники в Україні

$
0
0

Наскільки схожа робота IT-фахівця у приватному секторі й робота того, хто працює в лавах Збройних сил? Чи можливо застосовувати новітні підходи в розробці у сфері, яка доволі забюрократизована й закрита для цивільних спеціалістів? Чи можуть наші військові програмісти конкурувати з закордонними?

Про те, як це — бути розробником програмних рішень, які безпосередньо впливають на обороноздатність країни в умовах війни, військовослужбовці з підрозділу розробки Міністерства оборони України Єлизавета Бойко та Сергій Гальчинський розповіли в інтерв’ю DOU.

Сергій Гальчинський та Єлизавета Бойко (по центру) на Хакатоні НАТО у 2017 році, де українська команда виборола два перших місця

Баланс між навчанням і фізпідготовкою

Єлизавета Бойко:Після школи я захотіла стати програмістом і подала документи до різних вишів включно з Військовим інститутом телекомунікацій та інформатизації, на той час — Військовим інститутом при КПІ. Він, зокрема, набирав абітурієнтів за напрямком «Комп’ютерні науки». Я вступила й туди, й на кілька факультетів Київського політехнічного інституту, але обрала військовий, адже він мав непоганий рейтинг і фізичну підготовку на рівні.

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

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

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

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

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

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

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

Єлизавета Бойко у 2018 році на Coalition Warrior Interoperability eXercise — щорічних багатонаціональних навчаннях НАТО та країн-партнерів

Специфіка роботи й зарплата тих, хто служить

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

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

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

Наш стек технологій варіюється від низькорівневих речей, де потрібно інтегрувати специфічні рішення, до розробки на Spring Framework для наших сервісів. І через це доводиться читати величезну кількість ресурсів. Плюс — специфіки додає те, що ми працюємо з речами, які в принципі можуть бути не задокументовані. Це, наприклад, натівські розробки, які передбачають, що ти підписуєш NDA з вендором, який її винайшов. Він ділиться внутрішньою документацією під своїм грифом, а тому, коли ти стикаєшся з проблемами в реалізації, банальний пошук в Google тебе не врятує, адже така інформація взагалі не циркулює в мережі.

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

Наразі середня заробітна плата, наприклад, інженера-програміста в оборонній сфері — це приблизно 600-700 доларів.Тобто можна зрости до Senior developer’a й все одно отримувати ці гроші.

Проблема в тому, що для того аби стати військовим розробником, потрібно обов’язково мати звання військового й бекграунд Computer Science. У нашому випадку ми беремо на службу курсантів — студентів військових вишів. Та лише одиниці з них ідейно мотивовані, залишаються і продовжують роботу.

Існує значний відтік кадрів — люди, які залишаються після випуску військових вишів, бачать зарплату і йдуть.

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

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

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

Робочі завдання та переможні хакатони НАТО

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

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

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

Українська команда комбінованого змагання Хакатону 2018

Єлизавета:У 2017 році Україну як партнера НАТО вперше запросили на Лондонський хакатон, де команди змагалися у трьох напрямках: «Програмування», «Моделювання» та «Комбінація». Україна брала участь у двох напрямках: «Програмування» та «Комбінація». Це був прецедент — ми поїхали на натівський хакатон вперше і вибороли два перших місця.

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

А у 2018 нас запросили до Чорногорії на наступний хакатон. Там ми представили три команди, але розподіл місць був трохи інший: перше, друге і третє відповідно.

Команда, яка брала участь у напрямку «Моделювання», посіла третє місце. Їм треба було проаналізувати вимоги до об’єднаних місій НАТО та запропонувати варіант застосування хмарних обчислень усіма учасниками місії. Для прикладу, питання, які поставали в межах челенджу:

  • Що краще: Cloud On Premise на рівні місії чи використати IaaS/PaaS?
  • Якщо якась з націй надає IaaS, то як здійснювати регулювання?
  • Якщо декілька націй надають IaaS, то як керувати цим?

Рівень цього хакатону був набагато вищим за попередній. Було багато представників з індустрії, а також з державного сектору європейських країн (Великобританії, Данії). Наша команда хоч і посіла третє місце, але я вважаю, що цим можна пишатися, бо, наприклад, друге місце посіла команда від Microsoft.

У моєму напрямку, комбінованому змаганні, потрібно було створити з використанням платних або безкоштовних технологій інструмент, який допоміг би обмінюватися документами всередині структур НАТО, редагувати їх, а також налаштувати інтеграцію, наприклад, у чаті, відео- або телеконференції. Така необхідність виникла, оскільки в НАТО, як не дивно, досі використовують лише імейл. Якщо потрібно, наприклад, знайти якусь стару копію документів, це стає проблемою, адже вони надсилають документ, завантажують його, редагують, надсилають знову... І фахівці не можуть користуватися чимось на кшталт Google Docs — їм потрібно було щось не на базі відкритих ресурсів, а таке, що можна просто розгорнути, а всі нації змогли б користуватися. Наше рішення вибороло перше місце. Команда представила макет. Ми використали open source модливості й створили на базі Nextcloud рішення, яке є ізольованим і закриває усі потреби.

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

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

Хакатони фактично подарували шанс поспілкуватися з людьми, які присвятили останні 15-20років життя розвитку інформаційних систем НАТО. Це спеціалісти, які були авторами протоколів обміну міжнаціональних інформаційних систем, і вони мають надзвичайний досвід, яким готові ділитися. Вони мотивують, зміцнюють патріотизм і бажання дати все найкраще своїй нації. З технологічної точки зору — це люди, які зекономили нам дуже багато часу, вказавши на можливі проблеми та шляхи їхнього уникнення, і подарували бачення кращих практик. Ми доволі обмежені в ресурсі, у нас невелика команда, яка займається розробкою, тож за це їм велика подяка.

Українські програмісти отримали нагороди за перемогу в Хакатоні 2018 від Начальника Генерального штабу

Підготовка послідовників

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

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

Єлизавета:Загалом проєктам, якими ми займаємося, 3-4 роки,тобто вони побудовані на найновіших технологіях. Тож маємо можливість давати курсантам щось актуальне, а не те, що викладають 20 років в інституті.

Хоча програма Військового інституту не надто відрізняється від КПІ. Вони вчили Pascal, C++, і ми його вчили. Я не вважаю, що наші курсанти не такі розвинуті, як студенти КПІ. Вони отримують той самий набір знань, але мають розуміти, в якому напрямку вони себе бачать, і шукати доступ до новіших технологій.

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

Мотивація йти далі

Єлизавета:Як правило, ми працюємо з 8:00 до 17:00. Але я вважаю, що робочий день у нас плюс-мінус схожий на день звичайного програміста, того, який знаходиться поза армією. Оскільки ми працюємо за Agile, спрінти розраховані на два тижні. У понеділок ми плануємо завдання, щодня маємо мітинг, а в п’ятницю, коли дедлайн, презентуємо демо.

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

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

Єлизавета:Ми зібрали класичну команду: Front-end розробників, які працюють з React, Back-end, які пишуть на Java, тестувальника, DevOps, системних адміністраторів, тобто маємо стандартний набір. Крім того, налаштований CI/CD. Звичайно, не одразу все стало гаразд, ми довго до цього йшли, але зараз, з постійним зворотним зв’язком від користувачів, маємо реліз, як правило, кожні два тижні, хоча іноді трапляється і рідше.

Я не впевнена, що підписуватиму наступний контракт, але впевнена, що ці п’ять років не минуть даремно.

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

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

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

Єлизавета:Я тут зайду трохи з іншого боку. Здається, що наше фінансове становище посереднє, якщо порівнювати зі звичайним програмістом. Проте, наприклад, 30 днів своєї відпустки на рік я завжди проводжу в іншій країні. Якщо вміти розпоряджатися фінансами, то все можливо. Мені 24, і я вже знаю, що зробила для своєї країни, бо моя робота вплинула на її рівень. Наша команда виграла хакатон — це 100% не минуло просто так. Люди поглянули на Україну інакше!

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

Асинхронность в C#. Разрушение легенд

$
0
0

Всем привет! Меня зовут Влад, я — старший разработчик в компании DataArt. Статья будет посвящена асинхронному программированию на C#, а именно — нюансам работы с TAP (Task-based Asynchronous Pattern) — паттерном асинхронного программирования, основанным на задачах. Статья довольно обширная и разбита на пять разделов:

I. Асинхронность: как и зачем это использовать.

II. Взгляд вовнутрь через популярные заблуждения.

III. Проблемный код и лучшие практики.

IV. Сторонние библиотеки и тулинг.

V. Что еще почитать/посмотреть.

I. Асинхронность: как и зачем это использовать

Что такое асинхронность и зачем она нужна?

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

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

Однако многопоточность и асинхронность можно также классифицировать по типам многозадачности, как ее формы:

  • Вытесняющая (Preemptive)многозадачность — вид многозадачности, когда система выделяет каждой задаче некоторый квант времени — реализуется через механизм потоков и Task, выполняющий свой код в многопоточных контекстах.
  • Кооперативная (Cooperative)многозадачность — вид многозадачности, когда система выделяет задаче время до тех пор, пока задача не завершится. Похоже на асинхронные вызовы в однопоточном контексте синхронизации, например UI-поток WinForms или работу движка V8 для выполнения JavaScript.

Изучая асинхронные подходы в .NET, я плохо понимал, как все устроено изнутри. Это не позволяло решать ряд проблем, связанных с асинхронностью.Также слышал разные истории коллег, которые сталкивались с аналогичными проблемами и не всегда знали, как их решить: например, дедлоки или «нелогичное» поведение асинхронного кода. В статье рассмотрим механику работы и лучшие практики TAP: как это устроено изнутри и какие ошибки лучше не совершать.

В .NET-фреймворке исторически сложилось несколько более старых паттернов организации асинхронного кода:

  • APM (IAsyncResult, они же коллбеки) (.NET 1.0).
  • EAP — события, этот паттерн все видели в WinForms (.NET 2.0).
  • TAP (Task Asynchronous Pattern) — класс Task и его экосистема (.NET 4.0).

Сейчас рекомендованный и самый мощный паттерн — TAP. В C# 5 он был дополнен механизмом async/await, помогающим избежать блокирующего исполнения кода, в более новых версиях языка появилось еще несколько нововведений.

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

  • CPU Bound — блокировка, когда поток занят непосредственно вычислениями. Здесь необходимо позаботиться о том, чтобы длинная операция не блокировала потоки пула потоков .NET (ThreadPool), а работала отдельно и синхронизировала возврат результата.
  • IO Bound — блокировка, ожидание результата от устройств ввода-вывода — тут асинхронный подход имеет максимальный эффект, так как, по сути, мы занимаемся ожиданием, и наши потоки могут выполнять пустую работу.

Async/Await идеально решает проблему IO Bound, с CPU Bound можно использовать средства Parallel или неявного создания отдельных потоков, но об этом позже.

Какая бывает асинхронность?

Лично я для себя условно разбил асинхронные подходы на три группы, включив реализации из JavaScript и Golang для примеров.


Классификация подходовПаттерныИмплементация в JSИмплементация в GolangИмплементация в C#
Императивные Saga и ее вариации, коллбеки Redux-saga
ES7 async/await,
передача колбеков
Передача коллбеков,

Select + Channels
async/await, передача коллбеков
ОбъектныйDTO
Объектно-ориентированное представление статуса о выполненной задаче
Promise-Task
РеактивныеObserver/Observable
(pub/sub), Builder
RxJS
Observable
EventEmitter
MobX
ChannelsEvents
Rx.NET

JavaScript, как язык, еще имеет дополнительные средства, генераторы, которых нет в C#, для организации асинхронных операций.

В C# бэкенд разработке нативно меньше реактивных подходов. Основными методами являются либо запуск и менеджмент объектов Task и их неблокирующего ожидания с помощью await, либо коллбеки. Реактивность же чаще используется в UI-разработке.

Однако можно использовать и имплементацию библиотеки Rx под C# для работы с источником событий как с потоком (стримом) и реакций на них.

В этой же статье мы поговорим о нативных способах работы с асинхронностью в C#.

TAP (Task Asynchronous Pattern)

Сам паттерн состоит из двух частей: набора классов из пространства имен System.Threading.Tasks и конвенций написания своих асинхронных классов и методов.

Что нам дает асинхронный подход в контексте TAP:

  1. Реализации фасадов по согласованной работе с задачами, а именно:
    • Запуск задач.
    • Отмена задач.
    • Отчет о прогрессе.
    • Комбинация цепочек задач, комбинаторы.
    • Неблокирующие ожидания (механизм async/await).
  2. Конвенции по именованию и использованию асинхронных методов:
    • В конец добавляем постфикс Async.
    • В аргументы метода можем передавать или не передавать CancellationToken & IProgress имплементацию.
    • Возвращаем только запущенные задачи.

Если хотите подойти к изучению более фундаментально, посмотрите whitepaper на 40 страниц от Microsoft, как это работает. Скачать документ можно тут.

Как создать и запустить задачу

Условно я разделил возможные пути создания задач на четыре группы:

1. Фабрики запущенных задач

Task.Run(Action/Func)
Task.Factory.StartNew(Action/Func)
3. Конструктор

var t = new Task(Action/Func);
t.Start();
2. Фабрики завершенных задач

Task.FromResult(Result)
Task.FromCanceled(CancellationToken)
Task.FromException(Exception)
Task.CompletedTask
4. Фабрики-таскофикаторы

Task.Factory.FromAsync (APM)
TaskCompletionSource (EAP, APM, etc)
  1. Фабрики запущенных задач. Run — более легкая версия метода StartNew с установленными дополнительными параметрами по умолчанию. Возвращает созданную и запущенную задачу. Самый популярный способ запуска задач. Оба метода вызывают скрытый от нас Task.InternalStartNew. Возвращают объект Task.
  2. Фабрики завершенных задач.Иногда нужно вернуть результат задачи без необходимости создавать асинхронную операцию. Это может пригодиться в случае подмены результата операции на заглушку при юнит-тестировании или при возврате заранее известного/рассчитанного результата.
  3. Конструктор. Создает незапущенную задачу, которую вы можете далее запустить. Я не рекомендую использовать этот способ. Старайтесь использовать фабрики, если это возможно, чтобы не писать дополнительную логику по запуску.
  4. Фабрики-таскофикаторы.Помогают либо произвести миграцию с других асинхронных моделей в TAP, либо обернуть логику ожидания результата в вашем классе в TAP. Например, FromAsync принимает методы паттерна APM в качестве аргументов и возвращает Task, который оборачивает более ранний паттерн в новый.

Кстати, библиотеки в .NET, в том числе и механизм async/await, организуют работу по установке результата либо исключения для таск с помощью TaskCompletionSource.

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

Как отменить задачу

За отмену задач отвечает класс CancellationTokenSource и порождаемый им CancellationToken.
Работает это приблизительно так:

  1. Создается экземпляр CancellationTokenSource (cts).
  2. cts.Token отправляется параметром в задачу (ассоциируется с ней).
  3. При необходимости отмены задачи для экземпляра CancellationTokenSource вызывается метод Cancel().
  4. Внутри кода задачи на токене вызывается метод ThrowIfCancellationRequested(), который выбрасывает исключение в случае, если в CancellationTokenSource произошла отмена. Если токен был ассоциирован с задачей при создании, исключение будет перехвачено, выполнение задачи остановлено (так как исключение), ей будет выставлен статус Cancelled. В противном случае задача перейдет в статус Faulted.

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

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

Асинхронные контроллеры в ASP.NET могут инжектить экземпляр CancellationToken прямо в метод контроллера, вызываться же отмена токена будет по разрыву соединения с сервером. Это позволит значительно упростить инфраструктуру поддержки обрыва ненужных запросов. Если этот токен будет вовремя обрывать операции, результата которых уже не ждут, производительность может заметно повыситься. Далее два примера согласованной отмены.

Пример #1 кода согласованной отмены:

//Подготовка
var cts = new CancellationTokenSource();
var token = cts.Token;
token.Register(() => Console.WriteLine("Token works"));

//Получаем задачу
var t = Task.Run(async () =>
{
      //производим отмену на CancellationTokenSource
      cts.Cancel();
      //в Delay попадет уже отмененный токен, что выбросит исключение
      await Task.Delay(10000, token);

      //Возвратом задачи делаем из async void метода -> async Task метод
      return Task.CompletedTask;
}, token);

try
{
    //неблокирующее ожидание задачи
await t;
}
//В данном случае выбросится TaskCanceledException
catch (TaskCanceledException e)
{
      Console.WriteLine(e.Message + " TaskCanceledException");
}

В этом случае мы получаем в консоль:

Token works
A task was canceled. TaskCanceledException

Пример #2

В случае же работы с опросом токена исключение будет иное

(такой же код инициализации, как и выше)

//Получаем задачу
var t = Task.Run(async () =>
{
      //производим отмену на CancellationTokenSource
      cts.Cancel();
      //выбрасываем исключение на отмененном токене
      token.ThrowIfCancellationRequested();

     return Task.CompletedTask;
}, token);

try
{
     await t;
}
//В данном случае выбросится OperationCanceledException
catch (OperationCanceledException e)
{
     Console.WriteLine(e.Message + " OperationCanceledException");
}

В этом случае мы получаем в консоль:

Token works
The operation was canceled.OperationCanceledException

Обратите внимание, что Task.Delayвыбросит TaskCanceledException, а не OperationCanceledException.

Более детально о согласованной отмене можно почитать тут.

Как следить за прогрессом выполнения

TAP содержит специальный интерфейс для использования в своих асинхронных классах — IProgress<T>, где T — тип, содержащий информацию о прогрессе, например int. Согласно конвенциям, IProgress может передаваться как последние аргументы в метод вместе с CancellationToken. В случае если вы хотите передать только что-то из них, в паттерне существуют значения по умолчанию: для IProgress принято передавать null, а для CancellationToken — CancellationToken.None, так как это структура.

//Не используйте такой код в продакшене :) написано с целью демонстрации
//Код считает до 100 с определенной задержкой репортуя прогресс
public async Task RunAsync(int delay, CancellationToken cancellationToken, IProgress<int> progress)
{
      int completePercent = 0;

      while (completePercent < 100)
      {
        await Task.Run(() =>
        {
            completePercent++;

             new Task(() =>
             {
                 progress?.Report(completePercent);
             }, cancellationToken, 
                TaskCreationOptions.PreferFairness).Start();

        }, cancellationToken);

        await Task.Delay(delay, cancellationToken);
      }
}

Как синхронизировать задачи

Существуют такие способы объединять задачи в логические цепочки друг за другом или же ожидать группы задач по определенному принципу:

Комбинаторы задач

Task.WaitAll (list of tasks) -> Task
Task.WaitAny (list of tasks) -> Task
Task.WhenAll (list of tasks) -> Task
Task.WhenAny (list of tasks) -> Task
Метод расширения ContinueWith для экземпляров задач с опциями реакции на исключения, отмену или удачное завершение предыдущей задачи

t.ContinueWith( res=>{ код продолжения }, TaskContinuationOptions )
Метод расширения ContinueWith для экземпляров задач с опциями продолжения синхронно или асинхронно, установкой другого планировщика задач

t.ContinueWith( res=>{ код продолжения }, TaskContinuationOptions )
Метод расширения ContinueWith для экземпляров задач с опциями присоединения к времени выполнения родительской задачи (дочерняя задача не сможет завершиться до завершения родительской)

t.ContinueWith( res=>{ код продолжения }, TaskContinuationOptions )

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

Всего у TaskContinuationOptions 15 значений, и они могут комбинироваться.ContinueWith оборачивает задачу еще в одну задачу, создавая Task<Task<... >>. Но не стоит злоупотреблять или имплементировать сложную логику, основанную на этом методе.

Более подробно об особенностях такого поведения и подводных камнях можно почитать в блоге Stephen Cleary.

Как извлечь результат из задачи

До появления await извлекать результат из задач можно было такими блокирующими способами:

  • t.Result(); — возврат результата / выброс исключения AggregateException.
  • t.Wait(); — ожидание выполнения задачи, выброс исключения AggregateException.
  • t.GetAwaiter().GetResult(); — возврат результата / выброс оригинального исключения — служебный метод компилятора, поэтому использовать его не рекомендуется. Используется механизмом async/await.

После появления async/await рекомендованной техникой стал оператор await, производящий неблокирующее ожидание. То есть если await добрался до незавершенной задачи, выполнение кода в потоке будет прервано и продолжится только с завершением задачи.

await t; — возврат результата / выброс оригинального исключения.

Следует заметить, что для t.GetAwaiter().GetResult(); и await будет выброшено только первое исключение, аналогично манере поведения обычного синхронного кода.

Выброс исключения в вызывающий поток тоже результат.

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

Философия async/await

Основная идея async/await в том, чтобы писать асинхронный код в синхронной манере и не задумываться, как это работает. Но в этом и основной подводный камень — незнание начинки может породить неожиданные сайд-эффекты, о которых мы не задумывались.

Следующий код:

async Task<ResultType> funcAsync()
            {
                var result1 = await LongOperation1(null);
                var result2 = await LongOperation2(result1);
                var result3 = await LongOperation3(result2);
                return result3;
            }

ResultType funcResult = await funcAsync();

Логически представляет собой следующий код:

public static void CallbackFunc(Action<ResultType> resultCallback)
{
   LongOperation1(arg: null, onCompleted: (result1) =>
   {
      LongOperation2(arg: result1,  onCompleted: (result2) =>
      {
          LongOperation3(arg: result2,onCompleted: (result3) =>
           {           
               resultCallback(result3); 
           });
      });
    });
 }

CallbackFunc(result =>
{
   ResultType funcResult = result;
 });

где LongOperation1, LongOperation2, LongOperation3 — принимают аргумент и коллбек-функцию, выполняющуюся по завершении и принимающую результат операции.

Добавив немного инфраструктуры, мы бы изобрели самый старый асинхронный паттерн, APM.

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

Как использование async/await дополняет работу с TAP

Все, что могло ожидаться, блокируя поток, теперь может ожидаться, не блокируя поток, например:


БылоСталоЗачем нужно
task.Waitawait taskОжидать завершения Task’а
task.Resultawait taskПолучить результат завершенного Task’а
Task.WaitAnyawait Task.WhenAnyОжидать завершения одного (любого) Task’a из коллекции
Task.WaitAllawait Task.WhenAllОжидать завершения всех (последнего) Task’a из коллекции
Thread.Sleepawait Task.DelayЖдать заданный период времени

Что нового появилось в TAP начиная с C# 5

C# 5.0 / .NET 4.5

  • async/await;
  • Progress<T>.

C# 6.0

  • await в Catch/Finally блоках, в C# 5 так делать было нельзя;
  • Упрощенный синтаксис Task.Run(DoThings) вместо Task.Run(() => DoThings()).

C# 7.0 — 7.3

  • ValueTask<T> — структура-таск, повышающая производительность в некоторых случаях;
  • async Main method для консольного приложения.

C# 8 / .NET Standard 2.1 — (.NET Core 3, Mono 6.4)

  • AsyncStreams — асинхронные стримы, пока недоступны в .NET Framework, только для платформ, входящих в .NET Standard 2.1 +. Если вкратце — дают возможность на уровне языка реализовывать неблокирующие ожидания между чтениями из потока.

II. Взгляд вовнутрь через популярные заблуждения

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

Task — это облегченный Thread

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

  • Обслуживание статуса (выполнена, выполняется, отменена, ошибка) логической задачи — списка инструкций, объединенного в метод либо анонимный метод.
  • Фабричные статические методы по запуску логических задач с установкой параметров исполнения, также конструктор, позволяющий вручную создать задачу и затем ее запустить.
  • Создание инфраструктуры по согласованной отмене логической задачи, поддержки цепочек вызова задач.
  • Извлечение результата либо исключения в вызывающий поток.

Если вы программировали на JavaScript, то аналогом Task является объект Promise.

Лично я вижу класс Task как реализацию таких паттернов.

Фасад: Task не управляет выполнением задач и не имеет стратегии их планирования в потоки, это скорее интерфейс-абстракция, имеющая билдеры (ContinueWith), статические методы-фабрики создания задач и вариант создания задачи с помощью конструктора.

DTO (Data transfer object): Task отвечает за перенос состояния выполнения и результата связанного с ним кода. Причем установкой результата или исключения Task на низком уровне занимается TaskCompletionSource.

За планирование выполнения кода в потоках отвечает класс TaskScheduler, который имеет две реализации:

  • ThreadPoolTaskScheduler (неявно установлен для всех задач);
  • SynchronizationContextTaskScheduler.

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

  • ThreadPoolTaskScheduler выполняет код в потоках из ThreadPool. В виде исключения существует использование опции при создании задачи LongRunningTask — для таких задач ThreadPoolTaskScheduler создает отдельный поток.
  • SynchronizationContextTaskScheduler использует поведение текущего контекста синхронизации (установленного для потока либо по умолчанию). Контекст синхронизации является наследником класса SynchronizationContext. Получить этот TaskScheduler можно с помощью вызова TaskScheduler.FromSynchronizationContext(); в текущем потоке.

Async await — синтаксический сахар

Это утверждение отчасти верно, но только отчасти. Механизм async/await действительно не имеет реализации в CLR и разворачивается компилятором в довольно сложную конструкцию, указывающую, какую именно часть метода вызывать (стейт машина). Но вы не сможете реализовать async/await через механизм, например, тасок. Async/await — не синтаксический сахар вокруг тасок, это отдельный механизм, использующий класс Task для переноса состояния выполняющегося куска кода.

Await запускает операцию асинхронно

Оператор Await не запускает операцию асинхронно, он либо:

  • вызывает метод синхронно, если возвращенная им задача уже была завершена;
  • производит неблокирующее ожидание (отпускает поток) результата задачи, возвращая управление из метода вверх по иерархии await’ов, когда мы дошли до вложенного await, который возвращает незавершенную Task.

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

Кстати, Task не единственный класс, который может работать с оператором await. С ним может работать любой класс, реализующий метод GetAwaiter(), в случае с Task — TaskAwaiter.

Продолжение метода после await будет выполнено в пуле потоков

Это утверждение верно, но не всегда. Я выше упомянул класс SynchronizationContext, так вот, он необходим для механизма работы async/await. Наследники класса SynchronizationContext устанавливаются той средой, где выполняется код, в свойствах потока.

Для ASP.NET Core, Console Application, созданных вручную потоков — SynchronizationContext не будет выставлен явно. Это означает, что async/await будет использовать ThreadPool SynchronizationContext (контекст по умолчанию), запуская продолжение методов в случае, если возвращаемая ими задача не завершена, в ThreadPool.

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

То же самое и для WinForms-приложений: UI-поток имеет установленный WindowsFormsSynchronizationContext, планирующий продолжение только в единственный UI-поток.

Можете провести простой тест. Если вы запустите Task из метода-обработчика события UI-контрола в WinForms-приложении, он выполнится в пуле потоков. Однако если вы сделаете это с помощью Task.Factory.StartNew и передадите ему в параметр TaskScheduler — TaskScheduler.FromCurrentSynchronizationContext, то задача выполнится в UI-потоке.

Кстати, метод configureAwait, вызываемый на классе Task, возвращает пропатченный TaskAwait’er, в котором сбрасывается текущий контекст синхронизации и заново устанавливается по умолчанию. В этом случае продолжение отработает в пуле потоков.

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

Будет очень неожиданно, если кто-нибудь додумается синхронно (t.Result / t.Wait() ) получить результат из асинхронного метода вашей библиотеки в однопоточном контексте синхронизации (WinForms, ASP.NET). Единственный поток будет заблокирован незаконченной задачей, а закинуть в него продолжение задачи и завершить эту же самую задачу вы не сможете. И получите классический дедлок.

Все вышеописанное можно подытожить в таблице:


ПотокКонтекст синхронизации по умолчаниюГде выполнится продолжение метода после await в случае возврата незавершенного Task
Собственный потокSynchronizationContextThreadPool
Console ApplicationSynchronizationContextThreadPool
ASP.NET Core SynchronizationContextThreadPool
Original ASP.NETAspNetSynchronizationContextТот же поток
WinFormsWindowsFormsSynchronizationContextЕдинственный UI-поток
WPFDispatcherSynchronizationContext Единственный UI-поток

Флаг async без вызовов await внутри никак не поменяет метод

Это не так. Async — флаг компиляции, он — не часть сигнатуры метода и может не быть объявлен в интерфейсах. Видя метод как async, компилятор уже все равно создаст из него state-машину, пускай даже с одним состоянием. Исходя из этого оставлять методы с async без await внутри — плохая практика.

Async await и ContinueWith у Task — одно и то же

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

await Task.Run(() => { })
                .ContinueWith(async prev =>
                {
                    Console.WriteLine("Continue with 1 start");
                    await Task.Delay(1000);
                    Console.WriteLine("Continue with 1 end");
                })
                .ContinueWith(prev =>
                {
                    Console.WriteLine("Continue with 2 start");
                });

В консоли мы получим:

Continue with 1 start
Continue with 2 start
Continue with 1 end

Такое поведение обусловлено особенностью механизма async/await — после прерывания метода из него возвращается незавершенная задача, что интерпретируется механизмом ContinueWith как завершение метода.

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

Если хотите другие объяснения, то я поднимал этот вопрос на Stack Overflow.

TaskScheduler — то же самое, что SynchronizationContext, только новее

На самом деле, SynchronizationContext был представлен в .NET гораздо раньше, чем TaskScheduler.

  • Наследники обоих классов отвечают за планирование асинхронных операций.
  • Оба наследника работают с пулом потоков (класс ThreadPool) в реализациях по умолчанию.
TaskScheduler

  • Появился в .NET 4.0.
  • Высокоуровневая абстракция для работы с Task.
  • Позволяет планировать выполнение Task и продолжений.
  • Имеет две реализации по умолчанию:
    ThreadPoolTaskScheduler
    и SynchronizationContextTaskScheduler.
Где используется:

  • Любые операции с Task API, явно или неявно.
SynchronizationContext

  • Появился в .NET 2.0.
  • Низкоуровневый класс, позволяет запускать делегаты в нужных потоках.
  • Используется для работы await.
  • Имеет множество реализаций в зависимости от типа окружения.
Где используется:

  • Продолжение метода после await.
  • TaskScheduler.FromCurrentSynchronizationContext().
  • Запуск обработчиков в WinForms.

III. Проблемный код и лучшие практики

Проблемный код

Async void problem

Не используйте void вместе с async, если только это не написание обработчиков WinForms/WPF. Метод, отмеченный как async, будет запущен в пуле потоков, но у него нет механизма отлова исключений. Также вы не сможете отследить прогресс его выполнения, так как объекта Task, отвечающего за статус, здесь нет. Опасность отсутствия механизмов отлова исключений в том, что в случае падения такой метод завершит работу домена приложения, а если он единственный — то и работу всего приложения.

Кстати, анонимный лямбда-метод — async Action, а Action имеет результат void. Поэтому, вернув в async лямбде результат Task, компилятор автоматически выберет нужную перегрузку метода Task.Run, возвращающий async Task — и проблем не будет.

Deadlock problem

В однопоточных контекстах синхронизации (Original asp.net, WinForms, WPF) возможны дедлоки из-за необходимости добавлять продолжение метода в уже занятый поток. При этом освободить поток нельзя из-за незаконченности задачи. Чтобы было проще понять, о чем я, давайте посмотрим на такой код:

public static async Task<JObject> GetJsonAsync(Uri uri)
{
  using (var client = new HttpClient())
  {
	//await ожидает освобождения потока, чтобы запланировать запуск продолжения метода
    var jsonString = await client.GetStringAsync(uri); 
    return JObject.Parse(jsonString);
  }
}

public string Get(){
    var jsonTask = GetJsonAsync(...);
//поток заблокирован с помощью Result, ожидается завершение Task
    return jsonTask.Result.ToString();
}

Если он будет вызван на старом ASP.NET или на WinForms/WPF-приложении, результатом будет дедлок.

По порядку:

  1. Выполнение заходит в метод GetJsonAsync.
  2. Выполнение доходит до оператора await, возвращая вверх по вызову незаконченную Task.
  3. На незаконченной Task запускается блокирующее ожидание результата свойством Result.
  4. После прихода await однопоточный контекст синхронизации планирует продолжение в единственно возможный поток, который ждет окончания Task. Но Task не закончится, пока не отработает продолжение.

Еще один пример:

Блокирующие операции

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

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

Потерянные исключения

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

Запустите этот код в ASP.NET Core консольном приложении:

#if DEBUG
            Console.WriteLine("Please, switch to Release mode");
#endif
#if RELEASE
            TaskScheduler.UnobservedTaskException += (s, e) =>
            {
                Console.WriteLine("Unobserved exception");
            };
#endif

  Task.Factory.StartNew(() => throw new ArgumentNullException());
  Task.Factory.StartNew(() => throw new ArgumentOutOfRangeException());

  Thread.Sleep(100);
  GC.Collect();
  GC.WaitForPendingFinalizers();
      
  await Task.Delay(10000);

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

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

Ambient objects

  • Никогда не используйте ThreadLocal-хранилище в асинхронном коде, вместо этого был создан класс AsyncLocal.
  • При использовании TransactionScope помните об опции AsyncFlow, без нее работа транзакций не будет корректной. Я не сторонник использования TransactionScope в своих приложениях, однако при рефакторинге строго кода — вы вполне можете все сломать.

Работа асинхронных методов и IDisposable

В следующем коде:

public async Task<Result> GetResult()
{
      return await service.get();
}

public Task<Result> GetResultWrapper()
{
      using(var serviceContext = new ServiceContext())
      {
            return serviceContext.GetResult();
      }
}

Если вызывать async метод конструкцией await внутри в синхронном using, то Dispose для serviceContext отработает перед тем, как завершится метод GetResult.

Причина такого поведения в том, что после первого же await внутри метода GetResult нам вернется Task, исполнение кода продолжится, и по выходу из using будет вызван Dispose.

Затем придет продолжение после await внутри метода GetResult, но будет поздно.

Производительность

await в цикле

Если у вас есть код, где каждому элементу необходимо независимо от других сделать await, выполнение в цикле будет очень долгим. С логической точки зрения, если в основе вызываемых методов лежит IO Bound блокировка ожидания, то нет смысла вызывать их последовательно. С точки зрения конечного автомата внутри механизма async/await, это будет некоторый оверхед.

Гораздо лучше собрать все таски — и вызвать Task.WhenAll для всех сразу. ThreadPool сам поймет, как лучше оптимизировать их работу.

Dynamic & try/catch в async-методах

Если в вашем приложении каждая миллисекунда имеет значение, помните, что использование try/catch внутри async-метода значительно его усложнит. То же самое — с await dynamics-результата. Стейт-машина станет в разы сложнее, что замедлит выполнение кода.

ValueTask

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

Лучшие практики

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

Если упростить:

  • Не используйте async void, за исключением обработчиков WinForms/WPF.
  • Если начали, делайте все приложение асинхронным.
  • Не используйте блокирующие конструкции, используйте await.
  • Выбирайте неблокирующее ожидание await > ContinueWith.
  • Используйте ConfigureAwait(false) в коде вашей библиотеки.
  • Возвращайте только запущенные задачи.
  • Используйте конвенции именований.
  • Используйте флаги задач, если это необходимо.
  • Используйте асинхронную версию SemaphoreSlim для синхронизации доступа к ресурсу.

IV. Библиотеки и тулинг

Неблокирующие коллекции

Non-blocking dictionary — усовершенствованный по перфомансу словарь.

Immutable collections — стандартный набор неизменяемых коллекций. Примеры использования и кейс можно найти в этой статье.

Анализаторы кода

AsyncFixer — анализатор-расширение для Visual Studio для проблемных мест, связанных с асинхронностью. Ненужные await, async void методы, использование async & using, места, где можно использовать async-версии методов, обнаружение явных кастов Task<T> к Task.

Ben.BlockingDetector — библиотека-помощник обнаружения блокировок в вашем коде.

Демистифаеры стек-трейса

Ben.Demystifierпозволяет получить более приятный стек-трейс в вашем приложении.

V. Что почитать/посмотреть

Можете глянуть мой доклад «Асинхронность в .NET — от простого к сложному»по этой теме. По структуре материала он похож на эту статью.

Довольно интересный доклад Игоря Фесенкопро работу асинхронности и многопоточности, скрытые проблемы и методы их решения.

Блог Stephen Cleary, автора Concurrency in C# Cookbook (2nd ed).

Блог непосредственно разработчиков асинхронных средств Pfx team: async/await, Tasks in-depth.

TAP Pattern whitepaper.

ILSpy/DotPeek, чтобы посмотреть все самому :) Если хотите посмотреть код, генерируемый для async-методов — в настройках вашей reverse-engineering tool необходимо включить соответствующую настройку.

Еще пара книг по этой теме, которые мне показались вполне понятными: Алекс Дэвис «Асинхронное программирование в C# 5.0», Richard Blewett, Andrew Clymer Pro Asynchronous Programming with .NET.


Если у вас есть вопросы, замечания или пожелания, можете писать мне на Facebook.

Также если вы начинающий или опытный разработчик в поиске работы/в процессе изучения технологий, можете вступить в мое комьюнити в Telegram. Участвуйте в обсуждениях, задавайте вопросы — или просто поговорим с вами за жизнь!

Синхронізація в Go: горутини, тести, варіанти

$
0
0

Привіт, мене звати Ярослав, займаюсь розробкою в компанії Evrius. Ця стаття про синхронізацію результатів від паралельно виконаних підзадач, призначена для спеціалістів-початківців та тих, хто планує перейти на Go.

На початку 2019 року, маючи досвід з Go, шукав нову роботу. Під час більшості співбесід ставили запитання, як розпаралелити виконання завдання. Приблизний опис завдання: є список посилань, треба за ними перейти, отримати результат та синхронізувати. Вирішення було достатньо для проходження технічної частини в пару аутсорс-компаній.

Вартість горутини

Кожен розробник, який використовує Go, знає, що горутини дешеві. Трохи менше знають, що розмір мінімального стека горутинизмінювали в ранніх версіях Go, у версії 1.13.

_StackMin = 2048

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

package benchmarks

import (
	"sync"
	"sync/atomic"
	"testing"
)

func BenchmarkGoroutineCost(b *testing.B) {
	var value uint32
	var wg sync.WaitGroup

	wg.Add(b.N)

	for i := 0; i < b.N; i++ {
		go func() {
			atomic.AddUint32(&value, 1)

			wg.Done()
		}()
	}

	wg.Wait()

	if value != uint32(b.N) {
		b.Errorf("expected %d, got %d", b.N, value)
	}
}

go version

go version go1.13.3 linux/amd64

go test./benchmarks/... -v -bench=BenchmarkGoroutineCost -benchmem

BenchmarkGoroutineCost-4 3437931 351 ns/op 0 B/op 0 allocs/op
PASS
ok gitlab.com/go-yp/go-sync/benchmarks 1.563s

~350 наносекунд на створення, виконання, завершення горутини.

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

package benchmarks

import (
	"runtime"
	"sync"
	"sync/atomic"
	"testing"
)

type goRuntimeMaxCount struct {
	mu    sync.Mutex
	value int
}

func (c *goRuntimeMaxCount) update() {
	var value = runtime.NumGoroutine()

	c.mu.Lock()
	if value > c.value {
		c.value = value
	}
	c.mu.Unlock()
}

func (c *goRuntimeMaxCount) get() int {
	return c.value
}

func BenchmarkGoroutineCostDump(b *testing.B) {
	var (
		value          = uint32(0)
		wg             = new(sync.WaitGroup)
		goRuntimeCount = new(goRuntimeMaxCount)
	)

	b.Logf("before goroutine count %d", goRuntimeCount.get())

	wg.Add(b.N)

	for i := 0; i < b.N; i++ {
		go func() {
			atomic.AddUint32(&value, 1)

			goRuntimeCount.update()

			wg.Done()
		}()
	}

	wg.Wait()

	if value != uint32(b.N) {
		b.Errorf("expected %d, got %d", b.N, value)
	}

	b.Logf("after goroutine count %d for b.N = %d", goRuntimeCount.get(), b.N)
}

go test ./benchmarks/... -v -bench=BenchmarkGoroutineCostDump -benchmem

BenchmarkGoroutineCostDump-4 3223651 366 ns/op 0 B/op 0 allocs/op
before goroutine count 0
after goroutine count 904 for b.N = 1000000
before goroutine count 0
after goroutine count 3160 for b.N = 3223651
PASS
ok gitlab.com/go-yp/go-sync/benchmarks 1.562s

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

func BenchmarkGoroutineCostOne(b *testing.B) {
	var value uint32
	var wg sync.WaitGroup

	for i := 0; i < b.N; i++ {
		wg.Add(1)
		go func() {
			atomic.AddUint32(&value, 1)

			wg.Done()
		}()
		wg.Wait()
	}

	if value != uint32(b.N) {
		b.Errorf("expected %d, got %d", b.N, value)
	}
}

func BenchmarkGoroutineCostOneOverhead(b *testing.B) {
	var value uint32
	var wg sync.WaitGroup

	for i := 0; i < b.N; i++ {
		wg.Add(1)
		atomic.AddUint32(&value, 1)
		wg.Done()
		wg.Wait()
	}

	if value != uint32(b.N) {
		b.Errorf("expected %d, got %d", b.N, value)
	}
}

go test ./benchmarks/... -v -bench=BenchmarkGoroutineCostOne -benchmem

BenchmarkGoroutineCostOne-4 1488328 841 ns/op 0 B/op 0 allocs/op
BenchmarkGoroutineCostOneOverhead-4 32435746 34.6 ns/op 0 B/op 0 allocs/op
PASS
ok gitlab.com/go-yp/go-sync/benchmarks 3.229s

Тести проводив на домашньому Intel® Core™ i5-4210U CPU @ 1.70GHz, що показали вартість горутини ~800 наносекунд.

Для порівняння: знаходження максимального елементу в масиві з 1024 елементів ~1400 наносекунд.

Атомарність

Ми вже використовували пакет atomic, потрібний для паралельних операцій, щоб гарантувати їхню успішність.

Якщо з попередніх тестів забрати atomicі використовувати просте додавання:

func TestParallelPureIncrement(t *testing.T) {
	const n = 1000000

	var (
		value uint32
		wg    = new(sync.WaitGroup)
	)

	wg.Add(n)
	for i := 0; i < n; i++ {
		go func() {
			value++ // same sa "value = value + 1"

			wg.Done()
		}()
	}

	wg.Wait()

	if value != n {
		t.Errorf("expected %d, got %d", n, value)
	}
}

Отримаємо:

=== RUN TestParallelPureIncrement
--- FAIL: TestParallelPureIncrement (0.35s)
expected 1000000, got 851804
FAIL
FAIL gitlab.com/go-yp/go-sync/benchmarks 0.353s

Очікували 1 000 000, отримали 851 804, через відсутність синхронізації між горутинами.

На основі пакета atomicґрунтуються інші структури в Go, що використовують для синхронізації. Так, у тесті замість WaitGroup.Wait, ми можемо використати циклічну перевірку:

func TestParallelPureAtomic(t *testing.T) {
	const n = 1000000

	var value uint32

	for i := 0; i < n; i++ {
		go func() {
			atomic.AddUint32(&value, 1)
		}()
	}

	for atomic.LoadUint32(&value) < n {
		// NOP
	}
}

=== RUN TestParallelPureAtomic
--- PASS: TestParallelPureAtomic (0.42s)
PASS
ok gitlab.com/go-yp/go-sync/benchmarks 0.425s

і додати перемикання на інші горутини runtime.Gosched()

for atomic.LoadUint32(&value) < n {
		runtime.Gosched()
	}

Проте ліпше використовуйте sync.WaitGroup.

Синхронізація результатів від горутин і перегони даних (data race)

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

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

Знайдемо функціонал, що розробили в однопотоковому варіанті й зі збільшенням завдань — розпаралелили.

Наприклад, візьмемо сторінку bestofjs.org/projects, де навпроти кожного проекту бачимо число зірок на GitHub-і.

Раз на день ці числа треба оновлювати, а в базі всього 20 репозиторіїв.

Є функція, щоб отримати число зірок за ID репозиторію:

func fetchRepositoryStarByID(id int) int {
	// emulate slow http request by sleep
	time.Sleep(100 * time.Millisecond)

	// emulate response
	var stars = id % 32

	return stars
}

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

package main

import (
	"fmt"
	"time"
)

const repositoryCount = 20

type repository struct {
	id        int
	starCount int
}

func main() {
	var startTime = time.Now()

	var ids = getRepositoryIDs()
	var repositories = fetchRepositoryStarsByIDs(ids)

	updateRepositoryStars(repositories)

	var duration = time.Since(startTime)

	fmt.Printf("fetch %d from %d repositories by %d \n", len(repositories), repositoryCount, duration)
}

func getRepositoryIDs() []int {
	return make([]int, repositoryCount)
}

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var result = make([]repository, 0, len(ids))

	for _, id := range ids {
		result = append(result, repository{
			id:        id,
			starCount: fetchRepositoryStarByID(id),
		})
	}

	return result
}

func fetchRepositoryStarByID(id int) int {
	// emulate slow http request by sleep
	time.Sleep(100 * time.Millisecond)

	// emulate response
	var stars = id % 32

	return stars
}

func updateRepositoryStars(repositories []repository) {
	// NOP
}

Програма виконується за 2 секунди.

Опублікували React, Vue, Svelte й розширення до них, тепер у базі 100 репозиторіїв і програма виконується за 10 секунд.

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

Вирішили розпаралелити з використанням горутин і WaitGroup.

Тепер fetchRepositoryStarsByIDsмає такий вигляд:

package main

import (
	"fmt"
	"sync"
	"time"
)

const repositoryCount = 100

// ... same

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var (
		length = len(ids)
		result = make([]repository, 0, length)
		wg     = new(sync.WaitGroup)
	)

	wg.Add(length)

	for _, id := range ids {
		go func() {
			result = append(result, repository{
				id:        id,
				starCount: fetchRepositoryStarByID(id),
			})

			wg.Done()
		}()
	}

	wg.Wait()

	return result
}

виконується за 100 мілісекунд, але в консолі бачимо, що тільки частину репозиторіїв оновлено:

fetch 81 from 100 repositories by 112999451

Запустимо з флагом -race

go run -race main.go

й отримаємо повідомлення, у яких рядках коду є помилки (вивів тільки частину повідомлення):

WARNING: DATA RACE
Read at 0×00c00009a020 by goroutine 8:
main.fetchRepositoryStarsByIDs.func1()
gitlab.com/go-yp/go-sync/main.go:41 +0×91

У цьому коді відразу дві помилки з data race.

Перша помилка data race:змінна id змінюється в основній горутині, де виконується цикл for і читається зі створених горутин.

Ось приклад, що покаже цю помилку:

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	var ids = []int{1, 2, 3}
	var wg = new(sync.WaitGroup)

	wg.Add(3)
	for _, id := range ids {
		go func() {
			time.Sleep(time.Millisecond)

			fmt.Printf("id is %d\n", id)

			wg.Done()
		}()
	}

	wg.Wait()
}

id is 3
id is 3
id is 3

Варіанти розв’язання:

for _, id := range ids {
		go func(id int) {
			time.Sleep(time.Millisecond)

			fmt.Printf("id is %d\n", id)

			wg.Done()
		}(id)
	}
for _, id := range ids {
		id := id

		go func() {
			time.Sleep(time.Millisecond)

			fmt.Printf("id is %d\n", id)

			wg.Done()
		}()
	}

Друга помилка data race:це append, що змінює SliceHeaderчерез append з багатьох горутин.

Є три відомі мені варіанти розв’язання проблеми data race під час збереження результатів від горутин.

У першому: ми ініціалізуємо slice, і кожна горутина пише у свій індекс:

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var (
		length = len(ids)
		result = make([]repository, length)
		wg     = new(sync.WaitGroup)
	)

	wg.Add(length)

	for i, id := range ids {
		go func(i, id int) {
			result[i] = repository{
				id:        id,
				starCount: fetchRepositoryStarByID(id),
			}

			wg.Done()
		}(i, id)
	}

	wg.Wait()

	return result
}

Після запуску отримаємо очікуваний результат 100 зі 100 й без помилки data race.

fetch 100 from 100 repositories by 113026518

Якщо переглянути документацію — кожний елемент масиву як окрема змінна і в цьому прикладі з fetchRepositoryStarsByIDs кожна горутина працює зі своїм індексом (змінною), а отже, немає data race:

Structured variables of array, slice, and struct types have elements and fields that may be addressed individually. Each such element acts like a variable.

Це саме питання про запис у різні індекси є на stackoverflow.

Другий: обернути append в sync.Mutex:

package main

import (
	"fmt"
	"sync"
	"time"
)

const repositoryCount = 100

// ... same

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var (
		length = len(ids)
		result = make([]repository, 0, length)
		wg     = new(sync.WaitGroup)
		mu     = new(sync.Mutex)
	)

	wg.Add(length)

	for _, id := range ids {
		go func(id int) {
			var starCount = fetchRepositoryStarByID(id)

			mu.Lock()
			result = append(result, repository{
				id:        id,
				starCount: starCount,
			})
			mu.Unlock()

			wg.Done()
		}(id)
	}

	wg.Wait()

	return result
}

Після запуску отримаємо очікуваний результат 100 зі 100 й без помилки data race (так само).

Жодної переваги перед першим варіантом.

Діє таке саме правило, що й у циклах:

  • Якщо дію можна винести за цикл, так ліпше й зробити.
  • Якщо дію можна винести за mutex, так ліпше й зробити.

Наприклад, написавши такий код:

go func(id int) {
	mu.Lock()
	var starCount = fetchRepositoryStarByID(id)

	result = append(result, repository{
		id:        id,
		starCount: starCount,
	})
	mu.Unlock()

	wg.Done()
}(id)

Програма буде заблокована під час виконання важкої операції fetchRepositoryStarByID і стане послідовною з часом виконання 10 секунд.

Третій: писати результати в канал, це стандартне рішення, бо канали створені для можливості писання й читання з багатьох горутин, без помилки data race:

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var length = len(ids)
	// can also use channel with length, in this case result will be same
	// var resultChan = make(chan repository, length)
	var resultChan = make(chan repository)
	var wg = new(sync.WaitGroup)

	wg.Add(length)

	for _, id := range ids {
		go func(id int) {
			resultChan <- repository{
				id:        id,
				starCount: fetchRepositoryStarByID(id),
			}

			wg.Done()
		}(id)
	}

	go func() {
		wg.Wait()
		// close chan and break read loop
		close(resultChan)
	}()

	var repositories = make([]repository, 0, length)
	// read loop, while resultChan is open
	for result := range resultChan {
		repositories = append(repositories, result)
	}

	return repositories
}

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

Є ще один варіант — комбінація першого й другого:

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var (
		length = len(ids)
		result = make([]repository, length)
		wg     = new(sync.WaitGroup)
		index  = int32(-1)
	)

	wg.Add(length)

	for _, id := range ids {
		go func(id int) {
			newIndex := atomic.AddInt32(&index, 1)

			result[newIndex] = repository{
				id:        id,
				starCount: fetchRepositoryStarByID(id),
			}

			wg.Done()
		}(id)
	}

	wg.Wait()

	return result
}

Throttling (rate limiting)

Проект із зірочками зростає і вже має 1000 репозиторіїв.

GitHub (або інший сервіс) починає повертати HTTP status 429 (too many requests)або HTTP Timeout замість зірок, коли є багато одночасних запитів.

У нашому прикладі ми додамо додатковий time.Sleep(time.Second)у fetchRepositoryStarByID, щоб емулювати затримку HTTP Timeout:

package main

import (
	"fmt"
	"runtime"
	"sync"
	"time"
)

const repositoryCount = 1000

// ... same

func fetchRepositoryStarByID(id int) int {
	// emulate timeout
	if runtime.NumGoroutine() > 250 {
		time.Sleep(time.Second)
	}

	// emulate slow http request by sleep
	time.Sleep(100 * time.Millisecond)

	// emulate response
	var stars = id % 32

	return stars
}

Запустимо:

go run main.go

fetch 1000 from 1000 repositories by 1232180912

Як бачимо, тепер код виконується за секунду.

Тепер обмежмо число одночасних запитів за раз до 200.

Розгляньмо теж 3 варіанти (якщо комбінувати з попередніми, то, звісно, буде більше).

Найпростіший варіант — через канали (можна також пошукати за словом semaphore):

package main

import (
	"fmt"
	"runtime"
	"sync"
	"time"
)

const (
	repositoryCount = 1000
	requestLimit    = 200
)

// ... same

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var (
		length = len(ids)
		result = make([]repository, length)
		wg     = new(sync.WaitGroup)

		// WE ADD THIS
		throttler = make(chan struct{}, requestLimit)
	)

	wg.Add(length)

	for i, id := range ids {
		// WE ADD THIS
		throttler <- struct{}{}

		go func(i, id int) {
			result[i] = repository{
				id:        id,
				starCount: fetchRepositoryStarByID(id),
			}

			// WE ADD THIS
			<-throttler
			wg.Done()
		}(i, id)
	}

	wg.Wait()
	close(throttler)

	return result
}

go run -race main.go

fetch 1000 from 1000 repositories by 535724238

За півсекунди.

Ми пишемо в канал 200 разів і запускаємо 200 горутин, запустити наступну зможемо тоді, коли хтось прочитає з каналу.

Варіант через запуск воркерів (workers).

Запускаємо N воркерів (де N — наша константа request Limit), що з одного каналу читають завдання, а в інший пишуть результат:

package main

// ... same

func workerFetchRepositoryStarByID(wg *sync.WaitGroup, requestIdChannel <-chan int, responseRepositoryChannel chan<- repository) {
	// read while requestIdChannel open
	for id := range requestIdChannel {
		var starCount = fetchRepositoryStarByID(id)

		responseRepositoryChannel <- repository{
			id:        id,
			starCount: starCount,
		}
	}

	wg.Done()
}

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var (
		length      = len(ids)
		result      = make([]repository, 0, length)
		workerCount = requestLimit
	)

	if workerCount > length {
		workerCount = length
	}

	var (
		requestIdChannel          = make(chan int, workerCount)
		responseRepositoryChannel = make(chan repository, workerCount)

		workerComplete = new(sync.WaitGroup)
		readComplete   = new(sync.WaitGroup)
	)

	workerComplete.Add(workerCount)
	for i := 0; i < workerCount; i++ {
		go workerFetchRepositoryStarByID(workerComplete, requestIdChannel, responseRepositoryChannel)
	}

	readComplete.Add(1)
	go func() {
		for responseRepository := range responseRepositoryChannel {
			result = append(result, responseRepository)
		}
		readComplete.Done()
	}()

	for _, id := range ids {
		requestIdChannel <- id
	}

	close(requestIdChannel)
	workerComplete.Wait()

	close(responseRepositoryChannel)
	readComplete.Wait()

	return result
}

go run -race main.go

fetch 1000 from 1000 repositories by 540738968

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

Цей код працюватиме навіть з каналами без буфера:

var (
	requestIdChannel          = make(chan int, 0)
	responseRepositoryChannel = make(chan repository, 0)
)

Якщо ж використовувати ресурси пам’яті сповна, то код матиме простіший вигляд:

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var (
		length      = len(ids)
		result      = make([]repository, 0, length)
		workerCount = requestLimit
	)

	if workerCount > length {
		workerCount = length
	}

	var (
		requestIdChannel          = make(chan int, length)
		responseRepositoryChannel = make(chan repository, length)
		workerComplete            = new(sync.WaitGroup)
	)

	workerComplete.Add(workerCount)
	for i := 0; i < workerCount; i++ {
		go workerFetchRepositoryStarByID(workerComplete, requestIdChannel, responseRepositoryChannel)
	}

	for _, id := range ids {
		requestIdChannel <- id
	}
	close(requestIdChannel)

	workerComplete.Wait()

	close(responseRepositoryChannel)
	for responseRepository := range responseRepositoryChannel {
		result = append(result, responseRepository)
	}

	return result
}

і якщо потім захочемо змінити:

var (
	requestIdChannel          = make(chan int, 0)
	responseRepositoryChannel = make(chan repository, 0)
)

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

Останній варіант — розділити початковий slice на пачки й для кожної розпаралелити виконання.

Ми використаємо зовнішній пакет, що поділить на діапазони:

package main

import (
	"fmt"
	"github.com/gopereza/packer"
	"runtime"
	"sync"
	"time"
)

const (
	repositoryCount = 1000
	requestLimit    = 200
)

// ... same

func fetchRepositoryStarsByIDs(ids []int) []repository {
	var (
		length = len(ids)
		result = make([]repository, length)
		wg     = new(sync.WaitGroup)
	)

	var packs = packer.Pack(length, requestLimit)

	for _, pack := range packs {
		for i := pack.From; i < pack.To; i++ {
			wg.Add(1)

			go func(i int) {
				var id = ids[i]

				result[i] = repository{
					id:        id,
					starCount: fetchRepositoryStarByID(id),
				}

				wg.Done()
			}(i)
		}

		wg.Wait()
	}

	return result
}

Схожий приклад бачив у реальному проекті.

Недолік такого рішення — одна тривала операція затримає виконання всієї пачки, тому переписував на варіант з воркерами.

Епілог

Ми в проекті вибрали варіант з воркерами, що відправляють пачками.

Репозиторій, у якому тестував варіанти.

Далі буде.

Разворачиваем AWS для разработки локально на базе LocalStack

$
0
0

Сейчас все больше компаний уходит в облака для запуска своих приложений. Мы в компании Namecheapне стали исключением и уже довольно долго используем сервисы AWS. В связи с этим перед нами встала задача упростить работу с сервисами AWS в условиях локальной разработки. Как приблизить локальное окружение к условиям прода?

В этой статье мы с вами поднимем небольшой проект, который будет взаимодействовать со стабами сервисов AWS, таких как: DynamoDB, SNS/SQS и S3.

Одним из самых распространённых решений для стабов сервисов AWS является LocalStack. Ранее этот проект разрабатывался Atlassian, но теперь брошен в дикий open-source и монетизируется за поддержку ряда дополнительных сервисов и саппорт.

TL; DR

  1. Поднимаем LocalStack при помощи docker-compose.
  2. Переключаем проект на эндпоинт сервиса LocalStack.

Холодный старт на Windows

Самый простой путь развернуть LocalStack локально — запустить его при помощи Docker Compose.

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

В содержимое docker-compose-файла запишем такой код:

version: '2.1'
services:
localstack:
image: localstack/localstack:latest
ports:
- "4567-4584:4567-4584"
- "8080:8080"
volumes:
- "//var/run/docker.sock:/var/run/docker.sock"
environment:
- SERVICES=dynamodb
- PORT_WEB_UI=8080
- DOCKER_HOST=unix:///var/run/docker.sock

Осталось только поднять docker-compose-сервис:

docker-compose -f docker-compose.yml up -d localstack

Обратите внимание на установленную переменную окружения SERVICES. С ее помощью сейчас включён сервис DynamoDB. Чтобы включить другие сервисы, настроить Debug-трейсы и кое-что ещё, настоятельно рекомендую взглянуть в мануал.

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

docker: Error response from daemon: driver failed programming external connectivity on endpoint localstack_main (a156a7ce6d590937504c17b1f37f4634e7eaec09a9f8ba20cdf37b94424db39f): Error starting userland proxy: listen tcp 0.0.0.0:8080: bind: address already in use.

На одной из испытуемых систем это выглядело как-то так:

...
ports:
- "4567-4584:4567-4584"
- "9090:8080"
...
environment:
- PORT_WEB_UI=9090
...

Можно попробовать запустить LocalStack, как по мануалу — localstack start —docker. Но есть ряд минусов. Во-первых, вам придётся установить окружение Python, для того чтобы при помощи pip установить LocalStack. А во-вторых, вам понадобится либо установить докер, либо установить Java-окружение, для того чтобы заработали некоторые стабы сервисов.

Работа с DynamoDB

Итак, у нас уже запустился и работает LocalStack. Теперь мы можем проверить работоспособность и заодно подготовить сервисы, с которыми будем работать. Для настройки этих сервисов придётся использовать AWS CLI. Надеюсь, он уже у вас установлен. Для того, чтобы подключиться к нашим сервисам, нужно будет указать в конце команды кастомный эндпоинт при помощи следующего параметра —endpoint-url=http://localhost:4578, где номер порта мы можем взять из таблицы официального мануала.

Для начала проверим, что скажет LocalStack о состоянии таблиц:

aws dynamodb list-tables --endpoint-url=http://localhost:4569
{
    "TableNames": []
}

После чего создадим таблицу:

aws dynamodb create-table --table-name Todo \
--key-schema AttributeName=Id,KeyType=HASH --attribute-definitions AttributeName=Id,AttributeType=N AttributeName=Name,AttributeType=S \
--provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5 --endpoint-url=http://localhost:4569 

И ещё раз взглянем в lLocalStack на список. Он покажет только что созданную таблицу:

aws dynamodb list-tables --endpoint-url=http://localhost:4569
{
    "TableNames": [
        "Todo"
    ]
}

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

HINT:Для тех, кому нужно сетапать инфраструкту не в ручном режиме, а с помощью терраформ, есть отличный механизм сделать это, задав маппинг ендпоинтов в модуле AWS:

provider "aws" {
    skip_credentials_validation = true
    skip_metadata_api_check = true
    s3_force_path_style = true
    access_key = "mock_access_key"
    secret_key = "mock_secret_key"
    endpoints {
        dynamodb = "http://localhost:4569"
    }
}

Чуть больше инфы по этому вопросу можно взятьздесь.

Теперь давайте попробуем подключиться к DynamoDB из нашего тестового приложения. В любимой IDE создаём консольное dotnet core приложение. И сразу же устанавливаем пакет AWSSDK.DynamoDBv2. Общие правила для большинства подключения к сервисам LocalStack:

  1. Переключаемся на использование HTTP-протокола (LocalStack из коробки работает через HTTP,хотя и поддерживает https).
  2. Устанавливаем ServiceURL на порт этого стаба.

Давайте настроим подключение:

var clientConfig = new AmazonDynamoDBConfig()
{
    UseHttp = true,
    ServiceURL = "http://localhost:4569"
};

_dynamoClient = new AmazonDynamoDBClient(clientConfig);

После этого мы можем положить в нашу таблицу первое значение:

var putItemRequest = new PutItemRequest()
{
    TableName = TableName,
    Item = 
    {
        {
            "Id", new AttributeValue() { N = "42"}
        },
        {
            "Name", new AttributeValue() {S = "Get Up Early"}
        }
    }
};
await _dynamoClient.PutItemAsync(putItemRequest);

Можем проверить, что же сохранилось в LocalStack следующей командой:

aws dynamodb get-item --table-name Todo --key '{"Id":{"N":"42"}}' --endpoint-url=http://localhost:4569
{
    "Item": {
        "Id": {
            "N": "42"
        },
        "Name": {
            "S": "Get Up Early"
        }
    }
}

Добавляем SNS & SQS

Представим, что теперь нам нужно добавить SNS и SQS. Начнём с SNS. Для начала включим сервис и создадим топик. Для этого в compose-файле добавим в переменную окружения SERVICES разделённые запятой имена сервисов, как это сделано ниже:

...
environment:
- SERVICES=dynamodb,sns,sqs,s3
...

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

docker-compose -f docker-compose.yml restart localstack

В проект добавим nuget-пакеты AWSSDK.SimpleNotificationServiceи AWSSDK.SimpleNotificationService, для того чтобы получить возможность взаимодействовать с этими сервисами.

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

var snsConfig = new AmazonSimpleNotificationServiceConfig()
{
    UseHttp = true,
    ServiceURL = "http://localhost:4575"
};

snsClient = new AmazonSimpleNotificationServiceClient(snsConfig);

var sqsConfig = new AmazonSQSConfig()
{
    UseHttp = true,
    ServiceURL = "http://localhost:4576"
};

sqsClient = new AmazonSQSClient(sqsConfig);

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

private void CreateQueue()
{
    var queueCreationResult = await sqsClient.CreateQueueAsync("MyQueue");
    var queueUrl = queueCreationResult.QueueUrl;
    var topicCreationResult = await snsClient.CreateTopicAsync(new  CreateTopicRequest("TopicName"));
    var topicArn = topicCreationResult.TopicArn;
    var subscribeRequest = new SubscribeRequest(topicArn, "sqs", queueUrl);
    var subscribeResponse = await snsClient.SubscribeAsync(subscribeRequest);
}

В тестовых целях отправим в топик оповещение и вычитаем его из очереди:

...
// Publish message to topic
var request = new PublishRequest
{
    TopicArn = topicArn,
    Message = "Test Message"
};

await snsClient.PublishAsync(request);

...
// Read message from queue
var result = await sqsClient.ReceiveMessageAsync(queueUrl);
foreach (var message in result.Messages)
{
    Console.WriteLine(message.Body);
}
...

В консоли мы видим следующее:

{"MessageId": "e4e6ef59-107a-479d-952d-2a9b9e2da15c", "Type": "Notification", "Timestamp": "2019-10-05T13:27:36.397Z", "Message": "hello", "TopicArn": "arn:aws:sns:eu-west-3:000000000000:test"}

Это говорит о том, что всё успешно работает.

Сервис S3

Давайте примемся за самый используемый сервис — S3. Так как ранее мы его уже включили, можем оставить compose-файл в покое.

Устанавливаем nuget AWSSDK.S3и создаём следующий конфиг для использования LocalStack-овского S3. Ничего нового — HTTP и кастомный порт, на котором крутится сервис:

var clientConfig = new AmazonS3Config()
{
    UseHttp = true,
    ServiceURL = "http://localhost:4572"
};
s3Client = new AmazonS3Client(clientConfig);

Давайте посмотрим, как этот сервис работает. Для этого создадим ведёрко и зальём на него файл.

await s3Client.PutBucketAsync(BucketName);
var putRequest = new PutObjectRequest()
{
    BucketName = BucketName,
    Metadata = { ["x-amz-meta-title"] = "Title" },
    FilePath = Path.GetFileName(FileName),
    ContentType = "text/plain"
};
await s3Client.PutObjectAsync(putRequest);

Можем взглянуть на его содержимое:

var result = await s3Client.ListObjectsAsync(BucketName);
foreach (var s3Object in result.S3Objects)
{
    Console.WriteLine(s3Object.Key);
}

Попробуем скачать:

using (GetObjectResponse response = await s3Client.GetObjectAsync(BucketName, FileName))
using (Stream responseStream = response.ResponseStream)
using (StreamReader reader = new StreamReader(responseStream))
{
    Console.WriteLine("Object metadata, Title: {0}", response.Metadata["x-amz-meta-title"]);
    Console.WriteLine("Content type: {0}", response.Headers["Content-Type"]);
    Console.WriteLine(reader.ReadToEnd());
}

Осталось только подчистить за собой состояние сервиса:

await s3Client.DeleteObjectAsync(BucketName, FileName);
await s3Client.DeleteBucketAsync(BucketName);

Выводы

Это всё! Вот так мы подключили приложение, настроили и поработали со стабами трёх сервисов AWS — DynamoDB, SNS/SQS и S3. Теперь, зная, как пользоваться этим инструментом, мы можем вести разработку приложения локально, а не реальный демо-аккаунт AWS. Это даёт нам возможность с самого начала разработки задать высокий уровень development experience. Всем, кому интересно чуть больше поиграться с LocalStack и попробовать взаимодействие с ним в тестовом проекте, прошу в репозиторий.

Product Marketing дайджест #2: создание продуктов нового поколения, контент-маркетинг в 2020

$
0
0

Всем привет! Понемногу включаемся в рабочий режим после праздников. Сегодня в выпуске: серия роликов Growth Master от Segment, как использовать social proofs для своего бизнеса, контент-фреймворки для стартапа и многое другое.

Почитать

60+ Important 2019/2020 Mobile Marketing Statistics. Мы можем с уверенностью сказать, что живем в мобильном мире. Это не то, что приближается, это происходит прямо сейчас. Udonis подготовила отчет со статистикой маркетинга мобильного рынка за 2019 год.

SEO for Startups: 7 High-Converting Content Frameworks. Сложно создавать контент, который будет не только повышать awareness вашего продукта, но и приносить продажи. В статье приведены фреймворки, которые стартапы могут использовать для привлечения пользователей из поисковых систем с высокой вероятностью конверсии.

The three strands of brand authenticity | Inside Intercom. Одним из главных определяющих факторов успеха компании является ясность ее послания и то, как эта ясность проявляется во всех взаимодействиях между продуктом и брендом. Intercom рассказывает, как они «делают интернет-бизнес персональным».

Power Up Your Website: 15 Must-Haves for Social Proof. Существует бесконечное множество техник, которые влияют на решения пользователя о покупке. Одним из самых важных является social proofs. В статье детально описано, что это такое и как это использовать для своего бизнеса.

Behavior-Based Attribution Using Google BigQuery ML. В статье от CXL рассказывается, как раскрыть весь потенциал сырых данных и начать использовать Google BigQuery ML, чтобы строить атрибуцию с помощью всего лишь небольшого количества SQL — без знания Python или R.

SaaS Landing Pages You Should Run at All Times. Unbounce рассказал о 5 лендингах, которые постоянно должны быть в арсенале SaaS-маркетолога.

Content Marketing in 2020: The Definitive Guide. С каждым годом все больше компаний инвестируют ресурсы в контент-маркетинг. В гайде от backlinko вы найдете ответы на такие вопросы: как создавать и продвигать свой контент, какие форматы работают сейчас.

Послушать

Pursuing a Mission While Bootstrapping to Millions with John O’Nolan of Ghost — The Indie Hackers Podcast. Фаундер Ghost делится мыслями о настоящем и будущем издательского дела, создании контента и почему он решил запустить non-profit проект.

Жизнь в Сингапуре, контент-маркетинг и отказ от аналитики с Tim Soulo, CMO в ahrefs. Тим рассказывает, как устроен маркетинг в ahrefs, почему они не используют Google Analytics и Facebook Pixel, а также как делать контент-маркетинг в 2020.

Посмотреть

В видео от Product School Нейт (Product Manager в Amplitude) делится советами и инструментами, которые помогают создавать продукты нового поколения.

Три совета по управлению заинтересованными сторонами от Чарльза Вонга, Senior Product Manager в WeWork.

Growth Masters. Segment запустил серию интерактивных видеороликов для продактов и маркетологов Growth Masters, в которых много отличного (и бесплатного!) контента. Очень крутые лекторы: Эндрю Чен, Густав Альстромер и Лекс Роман и многие другие. Охватывает такие темы, как привлечение, онбординг и исследования пользователей.


Спасибо, что дочитали до конца. Увидимся в следующем выпуске!

P. S. Подписывайтесь на мой канал в Telegram, чтобы быть в курсе всего интересного из мира маркетинга продуктов и не пропустить следующий выпуск дайджеста.


← Предыдущий выпуск: Product Marketing дайджест #1

C++ дайджест #23: оптимізація компіляції та підсумки року

$
0
0

Привіт, мої любі сішники! Вітаю вас з Новим роком та Різдвом! Нехай у цьому році код стає якіснішим, компіляція швидшою, а проекти цікавішими! ;)

Новорічний випуск пропоную присвятити підсумкам року та оптимізації компіляції. То ж почнімо? :)

Підсумки 2019

C++ at the end of 2019 — детальний підсумок в подіях та фактах.

На Meeting C++ запущено опитування, за яким маємо такі цікаві результати (результати актуальні на 10 січня та можуть змінюватися в зв’язку з тим, що опитування ще триває).

Найчастіше зі стандартів використовуються:


Бібліотеки:


Середовище:

Оптимізація часу компіляції

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

Герб Саттер для вирішення цієї проблеми пропонує перевірити хедерита використовувати Pimpl, як і хлопці в цьому блозі:

Онлайн книга С++ best practices пропонує більш розширений список рекомендацій.

З цієї теми корисно буде почитати:

Відео з CppCon:

Modern C++

C++20: Concepts — What we don’t get

C++20: Concepts, the Placeholder Syntax

C++ coroutines: Getting started with awaitable objects

A beginner’s guide to C++ Ranges and Views

Корисні посилання

Substitution Failure is Error and Not An Error

Named Template Arguments

What Is MISRA and how to Cook It

Modern C++ type CoDec Challenge

Dry-comparisons: A C++ Library to Shorten Redundant If Statements

Accidentally Overwriting Another Local Variable in C and C++

A Compiler Writing Journey

The Eight Rules of Multithreaded Qt

Open sourcing Google Cardboard

Waiting for std::embed: Very Large Arrays in Clang

C++ UI Libraries

Інструменти

Top 10 Bugs Found in C++ Projects in 2019 PVS studio

CMake 3.16 added support for precompiled headers & unity builds

The Qt Marketplace has landed

A Gentle Intro to Developing C++ Apps for AWS and S3

CLion: Our Plan for Next Year and the 2020.1 Roadmap

Build C++ Applications in a Linux Docker Container with Visual Studio

Оновлення

Цього місяця маємо такі оновлення:

Хвилиночка флуду




← Попередній випуск: C++ дайджест #22

Зарплати українських розробників — грудень 2019

$
0
0

З 2 грудня до 5 січня ми проводили чергове анонімне зарплатне опитування, в якому взяли участь 10 187 ІТ-спеціалістів. Як і влітку, результати публікуватимемо у трьох частинах: зарплати розробників, зарплати тестувальників та зарплати інших технічних і нетехнічних спеціалістів.

У цій статті розглядаємо зарплати розробників, їх серед опитаних — 4921 спеціаліст. До розробників відносимо Software Engineer, TechLead і System Architect. Також цього разу ми дещо оновили анкету і для програмістів додали можливість обрати додаткову мову програмування й фреймворк/бібліотеку, що використовуються на поточній посаді.

Усі зарплати вказані в доларах США (за курсом міжбанку), чистими (після сплати податків). Для оцінки зарплат у вибірках використовується медіана. Статті з результатами минулих опитувань тут. Дані на GitHub та у віджет заллємо десь за тиждень.

Портрет учасників опитування

Середні зарплати

У всіх категорій, окрім Software Engineer, за останні півроку середня зарплата по Україні зросла: +$200 у Software Architect, +$150 у TechLead, +$100 у Senior Software Engineer і +$50 у Junior SE. У Software Engineer зростання відбулося у Києві, Харкові, Дніпрі й Запоріжжі, в інших містах середня зарплата SE або не змінилася, або навіть зменшилася (в Одесі — -$220, у Вінниці — -$100).

Динаміка

Середні зарплати Senior-ів у Києві досягли позначки $4000, і це на $500 і $250 вище, ніж у Харкові і Львові відповідно. Щодо джуніорів, то найменше (серед топ-5 міст) отримують початківці у Харкові ($600), а найбільше — у Києві ($840).

За посадами

Доволі висока середня зарплата розробників в Івано-Франківську — $2000. В той час як в Одесі середня зарплата — $1550.

Цікаво, що середня зарплата Kotlin-розробників у Києві і Львові на $800 вища, ніж у Харкові. Вища за харківську й середня зарплата львівських JavaScript-розробників — на $185.

За містами

Середня зарплата Senior Scala за півроку зменшилася на $200, але все одно залишається найвищою серед інших мов програмування. Серед Software Engineer найнижча середня зарплата у 1C-розробників ($1400), а найвища у Go ($2800).

За мовами програмування

Середня зарплата Senior-розробників у продуктовій компанії на $400 вища, ніж в аутсорсинговій. Більше у продукті отримують і джуніори — $800 проти $700 в аутсорсі та $600 у стартапі.

За типом компаній

Найвищі середні зарплати серед випускників ДонНТУ, КНУ ім. Шевченка та НТУУ «КПІ» — у всіх по $3000. Серед студентів, що вже працюють, найвищі зарплати у тих, хто навчається у ДНУ ім. Гончара, НТУ «ХПІ», Львівській політехніці та КНУ ім. Шевченка — понад $1000. Найнижча середня зарплата у студентів ЛНУ ім. Франка — $600.

За вишами

Середні зарплати: динаміка, фреймворки й порівняння

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

Java

Почнемо з Java, за останні півроку лише позитивна динаміка: середня зарплата Junior SE зросла на $68, SE — на $100, Senior SE — на $130. А за останні п’ять років середні зарплати збільшилися на $68, $325 і $600 відповідно.

Динаміка середніх зарплат Java

Щодо фреймворків і бібліотек, то найпопулярнішими серед Java-розробників є Spring і Hibernate (601 і 346 анкет). Всі інші варіанти зібрали суттєво менше відповідей. А ось найвищі середні зарплати у тих, хто використовує в роботі Play, Apache Spark, Node.js.

Серед додаткових мов програмування найбільш популярними у Java-розробників є JavaScript, SQL і Kotlin. А ось найвищі середні зарплати у тих, хто, окрім Java, ще використовує Go і Python — $3400 і $3100 відповідно. Цікаво, що майже кожен третій Java-розробник не використовує додаткову мову програмування на поточній роботі.

Середні зарплати Java-розробників з розбивкою за фреймворками та додатковою мовою програмування

JavaScript

Переходимо до JavaScript, за останні півроку середня зарплата Junior SE зросла на $50, а SE — на $100. Середня зарплата сеньорів з червня не змінилася, але за останні п’ять років вона збільшилася на $775. А от у джуніорів навпаки з 2014 року негативна динаміка — середня зарплата зменшилася з $750 до $650.

Динаміка середніх зарплат JavaScript

Серед найбільш популярних фреймворків і бібліотек у JavaScript-розробників: React.js (792 анкети), Node.js (559), Angular/Angular.js (409), Vue.js (212), Express (188), jQuery (168), React Native (158). Найвищі середні зарплати серед цих інструментів у Node.js ($2250), Angular/Angular.js ($2100) і Express ($2000).

70% JavaScript-розробників використовують на поточній роботі лише одну мову програмування. Серед тих, хто використовує додаткову мову, найбільш популярною є PHP (119 анкет). Але, схоже, що на рівень зарплати це не впливає: середня зарплата JS-розробників, що використовують PHP, на $200 нижча, ніж тих, хто використовує лише JavaScript.

Середні зарплати JavaScript-розробників з розбивкою за фреймворками та додатковою мовою програмування

C#/.NET

Серед C#/.NET середня зарплата за півроку зросла лише у джуніорів — на $100. У SE і Senior SE середня зарплата не змінюється вже рік.

Динаміка середніх зарплат C#/.NET

.NET (544 анкети), .NET Core (472) і ASP.NET (437) — найбільш популярні платформи серед .NET-розробників. Також доволі популярний фреймворк Angular/Angular.js — 195 анкет. Але найвищі середні зарплати у тих, хто, окрім стандартних платформ, використовує у роботи React.js ($3000) і Xamarin ($2700).

Майже половина .NET-розробників використовує JavaScript як додаткову мову програмування. Але найвищі зарплати серед тих, хто додатково працює з SQL — $2500 проти $2000 серед тих, хто використовує лише C#.

Середні зарплати C#/.NET-розробників з розбивкою за фреймворками та додатковою мовою програмування

PHP

За останні півроку зарплати PHP розробників практично не змінилися — лише трішки зросла середня зарплата джуніорів (на $50).

Динаміка середніх зарплат PHP

Laravel (262 анкети), jQuery (214), Vue.js (122) — найпопулярніші фреймворки і бібліотеки серед PHP-розробників. 70% респондентів використовують JavaScript як додаткову мову програмування.

Середні зарплати PHP-розробників з розбивкою за фреймворками та додатковою мовою програмування

Python

Зарплата Senior Python за півроку не змінилася, проте вона суттєво зросла у першому півріччі (на $500). Цікаво, що за останні п’ять років середня зарплата Senior SE виросла на $1100, а ось SE і Junior SE лише на $200 і $100 відповідно.

Динаміка середніх зарплат Python

Серед найбільш популярних фреймворків у Python-розробників — це Django (169 анкет) і Flask (127). Щодо додаткових мов програмування, то частіше за інші розробники на Python використовують в роботі JavaScript, але найвища середня зарплата у тих, хто має у своєму арсеналі Go — $2700.

Середні зарплати Python-розробників з розбивкою за фреймворками та додатковою мовою програмування

C++

На $250 зросла середня зарплата Senior С++ розробників за останні півроку. Також на $100 збільшилася зарплата Junior C++ і досягла позначки $900. Наразі вона найвища серед зарплат джуніорів за основними мовами програмування.

Динаміка середніх зарплат C++

Найпопулярніша додаткова мова програмування — Python (40 анкет). Стільки ж респондентів сказали, що використовують лише основну мову — C++. Найвищі зарплати у тих, хто додатково працює ще і з Java — $3625.

Середні зарплати C++ розробників з розбивкою за фреймворками та додатковою мовою програмування

Ruby/Rails

Середня зарплата Junior Ruby/Rails-розробників зросла чи не найбільше серед основних мов програмування — на $225 за півроку. Зарплати Software Engineer і Senior Software Engineer також виросли, хоч і скромніше, ніж у джунів, — на $75 і $100 відповідно.

Динаміка середніх зарплат Ruby/Rails

Swift

Усі категорії Swift-розробників демонструють негативну динаміку за останні півроку: якщо середня зарплата Software Engineer зменшилася на $50, то середня зарплата джуніорів і сеньорів на $175 і $100 відповідно.

Динаміка середніх зарплат Swift

Середня зарплата Swift-розробників, що додатково використовують Objective-C, майже в два рази вища, ніж у тих, хто використовує лише Swift.

Середні зарплати Swift-розробників з розбивкою за фреймворками та додатковою мовою програмування


Дані про кількість вакансій і відгуків дивіться в розділі «Тренди».


Візуалізація даних: Ігор Яновський


Секретные техники проработки требований. Часть 3

$
0
0

В предыдущих статьях (1, 2) мы с вами рассмотрели большую часть техник, которые я использую на практике, чтобы проверить требования на полноту. В данной статье я хотел бы рассмотреть оставшиеся три техники:

  • Администрирование.
  • Отчетность.
  • Нефункциональные требования.

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

Администрирование

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

Прошло полгода, и когда «сдавали» систему, представители заказчика спросили: «А как нам управлять справочными данными?» Дело в том, что один из основных справочников системы имел более 10 000 записей (вот вам и подводный камешек). А обновление данных должно было происходить не реже чем один раз в час. Также необходимо было реализовать синхронизацию данных пользователей системы из active directory.

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

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

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

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

Управление справочниками системы

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

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

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

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

Управление учетными записями, ролями и полномочиями

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

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

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

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

Архивирование и восстановление объектов

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

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

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

При проработке требований к хранению удаленных объектов следует учитывать:

  • Как и кто может восстанавливать данные?
  • Какой срок хранения удаленных документов?
  • Есть ли ограничения по объему удаляемого документа?

Журналирование действий пользователей

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

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

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

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

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

Отчетность

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

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

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

Итак, что я рекомендую учитывать при проработке требований к отчетности:

Варианты использования — или, другими словами, как отчетом будут пользоваться

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

При проработке требований рекомендую искать ответы на следующие вопросы:

  • Необходимо ли обрабатывать данные после отображения результата запроса?
  • Есть ли необходимость хранить данные после получения (архив отчетов за период)? Если да, ВНИМАНИЕ: нужно более детально проработать требования к отчетности. Возможно, понадобится организовывать хранилище данных, а это совсем нетривиальная задача.

Источники данных

Для себя я выделяю три источника данных:

  • Внутренняя — база данных системы.
  • Внешняя — базы данных других систем.
  • Гибридная — часть данных тянется из внутренней базы данных, а часть — из внешних.

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

  • доступность данных на момент формирования отчета;
  • производительность построения отчета.

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

Визуализация

Если вариант использования — «Для печати», рекомендую проработать так называемый визуальный макет, в котором есть:

  • верхний колонтитул;
  • заголовок (название отчета);
  • тело отчета — основная часть;
  • нижний колонтитул.

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

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

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

Самостоятельно реализовать сервис для визуализации данных будет трудозатратно. Уточните, какой ориентировочный срок и бюджет для реализации визуализации данных. Помните, что на рынке есть много хороших решений: PowerBI, Google Data Studio, Tableau и другие. Проанализируйте их.

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

Диаграмма — представление данных при помощи графических компонентов (линии, точки), связанных со справочниками, имеет одну или несколько числовых шкал.

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

Карта — представление показателей, связанных с географическими данными (страна, регион, город и т.д.)

А возможно, будет достаточно реализовать отображение графиков в Excel.

Источник

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

  • возможность настраивать представление данных;
  • навигацию между разделами отчета.

Дополнительные возможности

Отчеты могут иметь ряд дополнительных возможностей:

  • Публикация отчетов:для некоторых отчетов необходимо иметь возможность публиковать результаты на веб-ресурсах в виде тех же диаграмм, карт и т.д. В данном случае следует учитывать периодичность обновления данных. На практике бывали случаи, когда требования к публикации на веб-ресурсах не прорабатывались, и на первых этапах развития системы просто публиковали изображение, которое предварительно подготавливалось сотрудником, поэтому не забудьте проработать требования не только к публикации, но и к визуализации данных.
  • Формирование и отправка отчетов по расписанию:при проработке требований к формированию и отправке отчетов по расписанию следует учитывать время формирования (как правило, отчеты формируются в нерабочее время, но и в правилах бывают исключения) и способ отправки (электронная почта или сохранение на сетевой ресурс). Следует продумать, с какого электронного адреса будет отправляться отчет, и список получателей. При проработке получателей рекомендую отправлять на группу контактов, группами легче в будущем управлять и сопровождать.
  • Экспорт данных:требования к возможностям экспортировать данные в Excel, Word, PDF или другие форматы.

Нефункциональные требования

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

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

  1. Runtime — это требования, которые описывают время работы системы.
  2. Design time — это требования, определяющие аспекты проектирования системы.

К группе Runtime относят:

  1. Доступность.
  2. Надежность.
  3. Время хранения данных.
  4. Масштабируемость.
  5. Удобство использования.
  6. Безопасность.
  7. Производительность.
  8. Ограничения.

1. Доступность — требования ко времени непрерывной работы системы

Пример требований к доступности: система должна поддерживать режим 24*7 — круглосуточный режим работы.

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

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

Доступность, %Время простоя в годВремя простоя в месяцВремя простоя в неделю
90 (одна девятка)36,5 дней72 часа16,8 часов
9518,25 дней36 часов8,4 часов
987,30 дней14,4 часов3,36 часов
99 (две девятки)3,65 дней7,20 часов1,68 часов
99,51,83 дней3,60 часов50,4 минут
99,817,52 часов86,23 минут20,16 минут
99,9 (три девятки)8,76 часов43,2 минут10,1 минут
99,954,38 часов21,56 минут5,04 минут
99,99 (четыре девятки)52,56 минут4,32 минут1,01 минут
99,999 (пять девяток)5,26 минут25,9 секунд6,05 секунд
99,9999 (шесть девяток)31,5 секунд2,59 секунд0,605 секунд

Сразу скажу, все заказчики хотят доступность в шесть девяток, но когда начинаем прорабатывать аппаратную архитектуру, соглашаются на 95-99 :-D

2. Надежность

Требования к надежности описывают поведение системы в нештатных ситуациях. Требования к надежности должны предусматривать:

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

Ниже приведу несколько примеров:

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

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

3. Требования к времени хранения данных

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

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

При проработке архивирования данных не забывайте о возможных связях объектов вашей системы.

4. Масштабируемость

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

Как правило, выделяют два направления масштабирования:

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

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

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

5. Требования к удобству использования

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

Система должна иметь удобный, интуитивно понятный и дружественный интерфейс.

Когда я вижу подобное в требованиях, сразу задаю вопрос: какие критерии проверки удобства и дружественности интерфейса?

Недостаточно написать — удобный, интуитивно понятный и дружественный. Следует раскрыть эти сущности.

Для себя выделяю семь пунктов юзабилити для проверки требований на полноту:

  1. Шрифты:осмысленные размеры шрифтов и их поведение при адаптивном дизайне.
  2. Адаптивность:проработайте размещение и поведение элементов системы при адаптивности. Максимальное и минимальное разрешение. Разрешение, при котором изменяется размещение элементов.
  3. Ошибки:информативная обработка сообщений об ошибках. Недостаточно показать код ошибки — следует сообщить, что пользователю делать с этой ошибкой. А также потрудитесь отдельно проработать требования к страницам с информацией об ошибке.
  4. Навигация:отдельно раскрывал эту тему во второйчасти статьи.
  5. Поиск:для удобства пользователя поиск размещают практически на всех интерфейсах пользователя (я не говорю сейчас о диалоговых или информационных интерфейсах). Поиск информации может быть глобальным — в рамках всей системы, или локальным — в рамках определенного модуля, а также контекстным.
  6. Кроссбраузерность:если у вас система работает через браузеры, опишите браузеры и их версии, на которых должна функционировать система. Тут важный аспект: чем больше браузеров, тем больше работы у разработчиков и верстальщиков, а также увеличивается время на тестирование.
  7. Обработка отдельных элементов:к примеру, ссылки, которые посещал пользователь, должны отображаться не синим, а фиолетовым. Также необходимо указать коды цветовой гаммы: цвет активной ссылки — #0000FF, цвет посещенной ссылки — #800080

6. Требования к безопасности

Требования к безопасности бывают трех категорий:

  • связанные с разграничением доступа;
  • связанные с работой с приватными данными;
  • направленные на снижение рисков от внешних атак.

Для понимания ниже приведу несколько примеров каждой категории.

Примеры требований с разграничением доступа:

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

Примеры требований, связанных с работой с приватными данными:

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

Примеры требований, направленных на снижение рисков от внешних атак:

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

7. Требования к производительности

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

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

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

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

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

8. Ограничения

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

На одном из проектов мы с удивлением узнали, что у клиента есть ПК, на которых установлена ОС Windows XP c браузером IE 8, и это очень ограничивало нас в разработке, а именно — в выборе технологии реализации.

К группе Design time относят:

  • Требования к расширяемости.
  • Требования к переносимости.
  • Требования к взаимодействию.
  • Требования к поддержке.
  • Требования к возможности тестирования.
  • Требования к локализации.

Требования к расширяемости

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

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

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

Требования к переносимости

В требованиях к переносимости описывают требования работы системы на разных платформах.

Переносимость системы включает:

  • Перенос системы на другую среду (компьютер, ферму серверов) аналогичной архитектуры.
  • Установка или переустановка из дистрибутивных файлов на другую среду (компьютер, ферму серверов) аналогичной архитектуры.
  • Сборка исполняемых программ для разных платформ из исходного кода.

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

Требования к взаимодействию

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

На моей практике для построения организационной структуры предприятий мы использовали разнообразные HR-системы или данные из Active Directory, а иногда и данные из нескольких систем. Для этого должен быть некий уникальный идентификатор, который используется с целью построения интеграционных связей между системами.

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

Для более сложных интеграций используют протоколы обмена данными между системами или, как пример, реализовывают API (application programming interface).

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

Название поляОписание поляТип данныхОбязательность дополненияКомментарий
1UserIdУникальный идентификаторIntegerДа— 
2SurnameФамилияStringДа— 
3NameИмяStringДа— 
4PatronymicОтчествоStringДа— 
5PhoneТелефонStringНет— 

Для интеграции систем аналитики описывают мапинг полей:

Описание поляНазвание поля
Система 1
Тип данных
Система 1
Название поля
Система 2
Тип данных
Система 2
Комментарий
1Уникальный идентификаторUserIdInteger (12)TabIdInteger (12)— 
2ФамилияSurnameString (256)SnameString (256)— 
3ИмяNameString (256)NameString (256)— 
4ОтчествоPatronymicString (256)MNameString (256)— 
5ТелефонPhoneString (256)MobPhoneString (256)— 

При мапинге полей следует обращать внимание на совпадение типа полей и их длину (в таблице указал в скобках максимальное количество символов).

Требования к поддержке

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

Примеры функций:

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

Требования к возможности тестирования

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

Пример шаблона тест-кейсов:

ДействиеРезультат
1Зарегистрироваться в администраторской частиНа экране отобразится иерархический список разделов и действий
2Перейти в раздел управления пользователямиВ правой верхней части экрана появится список действий, в правой нижней части — список пользователей
3Выбрать функцию «Добавить пользователя»На экране появится форма для добавления нового пользователя:
  • имя пользователя;
  • личная информация;
  • роль (выбор из списка);
  • кнопка «Добавить пользователя»

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

Требования к локализации

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

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

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

Уверен, что моя статья, как минимум, натолкнет вас на размышления.

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

Гармонии вам и процветания! До новых встреч на страницах DOU!

Веб-розробка: вчора, сьогодні, завтра

$
0
0

Привіт, мене звуть В’ячеслав Колдовський, я Programming Mentor. У веб-розробці я з 1990-х,тепер працюю в SoftServe над навчальними проектами. Чверть століття я спостерігав за еволюцією вебу, бачив появу та смерть технологій, робив ставки в конкурентних війнах, мене завжди цікавило, куди воно все рухається, — саме про це хочу з вами поговорити, і розмова не буде короткою.

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

Перший веб-сайт побачив світ 6 серпня 1991 року. Це був набір примітивних веб-сторінок, які, власне, і презентували всесвітню павутину — World Wide Web. Цікаво, що він і досі доступнийза тією самою адресою, що й майже три десятиліття тому.

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

HTML

Як сам батько вебу — фізик-контрактор CERN Тім Бернерс-Лі — його уявляв, можна побачити на тому самому першому сайті: «The WorldWideWeb (W3) is a wide-area hypermedia information retrieval initiative aiming to give universal access to a large universe of documents». У вільному перекладі звучить так: це така собі бібліотека документів, пов’язаних між собою гіперпосиланнями. Тобто мовиться про всього-на-всього документи, які подані у форматі гіпертексту та поєднані між собою гіперпосиланнями. Ключові терміни тут: «документи», «гіпертекст» та «гіперпосилання».

Цікаво, що Тім Бернерс-Лі не був автором ні ідеї, ні самого терміна «гіпертекст». Термін винайшов ще 1963 року Тед Нельсон, який працював над проектом Xanadu — спробою переосмислити поняття документа й роботою з інформацією взагалі. Xanadu — це проект усього життя Теда Нельсона, а його ідеї випередили час. Але як нерідко трапляється в реальному світі, успішним стає не оригінальний автор науково обґрунтованої рафінованої ідеї, що часто відірвана від реальності, а той, хто побачив, як поєднати ідею з реальністю, навіть пожертвувавши якимись її важливими принципами. Тут можна згадати класичний випадок, коли автор ООП Алан Кей жорстко розкритикував C++ як невдалу імплементацію його задумів: «Коли я винайшов ООП, то не мав на увазі C++». Те саме можна сказати й про винахід Теда Нельсона — йому не надто сподобалося, як його ідеї були зреалізовані у WWW. Ось цікаве відеоз 2008 року, де автор демонструє робочий прототип і пояснює ключові концепції свого проекту. Там на власні очі можна переконатися: воно дуже відрізняється від того, що зреалізував Тім Бернерс-Лі.

Крім концепції гіпертексту та гіперпосилань, варта уваги й імплементація веб-сторінок за допомогою HTML. Усі веб-розробники знають про сучасну п’яту версію HTML, але мало кому відомо, що першою формальною версією цієї мови є HTML 2.0, яка вийшла у форматі RFC аж у листопаді 1995 року. До того моменту як такого стандарту мови взагалі не було. Тім Бернерс-Лі запозичив ідею мови в SGML, але водночас досить вільно інтерпретував її, а тому веб-сторінки не були коректними SGML-документами, хоча й використовували синтаксичні конструкції мови, такі як теги та атрибути. Утім, версії HTML із другої по четверту будувалися як SGML-документи, однак уже в HTML5 від такої ідеї відмовилися. Для охочих залишається можливість зреалізувати веб-сторінки у форматі XHTML, але сенсу в тому небагато, бо виникають деякі побічні ефекти, наприклад селектори CSS стають чутливими до реєстру тощо. Історія показала, що ідея підтягнути HTML відповідно до SGML із самого початку була нелогічною, — схоже, треба вміти вчасно відрубати кінці минулих ідей і не тягти із собою в майбутнє ворох минулого — веб у цьому сенсі гарний антиприклад.

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

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

CSS

Думаю, досить про HTML, поговорімо про CSS. Скільки болю доводилося бачити в очах цих молодих людей, що з ентузіазмом починали вивчати веб-розробку, з легкістю опановували основи HTML, а потім обривали свій політ, зіткнувшись із суворою реальністю роботи з таким чудовим винаходом, як каскадні таблиці стилів.

Вважається, що автором CSS є норвежець Гокон Лі (Håkon Wium Lie), який запропонував ідею Тімові Бернерс-Лі в жовтні 1994 року, а перша версія стандарту вийшла два роки після того. До CSS як такого поділу на представлення і контент в HTML не існувало, і ідею розділити обов’язки можна було б вважати геніальною, якби вона не була одним з фундаментальних принципів розробки програмних проектів. Але, як ми знаємо, зло ховається в деталях, і найбільше це стосується CSS. Іронічно, що сайт винахідника CSSне дуже добре виглядає ні на занадто широких, ні на вузьких екранах, і навіть валідатор CSS має до нього претензії.

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

Написання коду на чистому CSS приносить мало задоволення, особливо тому, що в ньому практично відсутні були механізми реалізації одного з найважливіших принципів розробки — DRY (Do Not Repeat Yourself). Донедавна змінних не існувало, для вкладених елементів DOM доводиться повторювати ланцюжки селекторів, а можливості перевикористовувати код, модифікуючи його поведінку залежно від певних умов, немає й тепер.

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

Узагалі CSS — такий потужний і гнучкий інструмент, що його часто застосовують не за призначенням, скажімо, виправляючи хиби HTML. Наприклад, у HTML є тег, який дозволяє зробити горизонтальну лінію, логічно було б мати тег, який робить вертикальну. Однак такого немає, і щоб намалювати вертикальну, доводиться креативити, багато хто робить це по-різному і використовує CSS. Водночас особливо цинічний випадок такого застосування — це трансформувати елемент горизонтальної лінії в лінію вертикальну. «Цинічний» — бо якщо сприймати код HTML семантично, то тег hr, що має створювати горизонтальну лінію, повинен створювати саме горизонтальну лінію. (Якщо говорити про семантично коректний підхід до того, як розв’язати це завдання, то тут ліпше створити власний елемент в HTML, стандарт це дозволяє, ось приклад).

JavaScript

Переходячи до, ймовірно, найцікавішої складової фронтенду, варто зробити відступ і запитати: а що робить мова програмування на фронтенді взагалі? Тут варто зазначити, що в 1990-хлюдину, яка займалася веб-сайтом, дуже часто називали веб-майстер, і далеко не завжди це була людина з навичками програмування. Якось на цю тему пожартував Кріс Коєр, засновник css-tricks.com: «Два фронтенд-розробники сидять поруч у барі. Їм ні про що говорити». І це не той випадок, коли хтось пише на React, а інший на Angular. Це радше про те, що один типовий програміст — з алгоритмічним мисленням, якому зручніше згенерувати весь контент динамічно та імперативно, досить лише отримати контейнер, а другий, навпаки, людина, для якої ближчою є семантика елементів, структура контенту, стилі, анімації тощо, тобто декларативний підхід. Якщо говорити про філософію, закладену в HTML, то саме другий підхід є коректнішим, хоч би як дивно це здавалося для декого з розробників сьогодні.

Джерело

Власне, сам Тім Бернерс-Лі жодної мови програмування всередині браузера не передбачав, тому не дивно, що історія її виникнення скидається на детектив. Компанія Netscape, заснована у квітні 1994-го,випустила першу публічну версію браузера Netscape Navigator з номером 0.9 у листопаді того самого року. Браузер стрімко почав набирати популярність, і вже за чотири місяці займав три чверті всього ринку.

Частка ринку браузера Netscape Navigator, 1994–2007

Засновник компанії Марк Андрессен вирішив, що HTML не вистачає саме легковагової скриптової мови програмування, код якої можна було б писати прямо в тексті веб-сторінок. Тож у квітні 1995 року він найняв Брендона Айка, який був тоді відомим фахівцем з мов програмування, для того щоб вбудувати мову програмування Scheme у браузер Netscape Navigator. Однак у мови Scheme досить специфічний синтаксис, а Sun тоді мала сильні ринкові позиції та активно просувала Java, тому однією з вимог, які висунув Брендон Айк до нової мови, була синтаксична подібність з Java. До вимог також належало, щоб мова була досить проста та не містила класів, тож для Брендона вона стала своєрідним челенджем — він вирішив зреалізувати в ній ООП, але без класів.

У Netscape прийнято було працювати дуже швидко, тому Брендон Айк розробив прототип мови за 10 робочих днів у травні 1995 року. Це справді дуже мало для того, щоб створити власну мову програмування з нуля, але, схоже, цілком досить, якщо базуватися на вже готових рішеннях. Саме тому нова мова запозичила синтаксис із Java, основну функціональність із Scheme, а реалізацію ООП із Self.

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

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

Діалог у твітері з Брендоном Айком стосовно блочної області видимості

Годі було 1995 року уявити, що одного дня JavaScript стане найпопулярнішою мовою програмування у світі. Власне, тоді, у 1990-х,старт JS серед розробників навряд чи можна було вважати вдалим, бо ця мова сприймалася як щось недосить серйозне, чим слід користуватися, коли треба замінити зображення, поверх якого рухається курсор миші, чи якесь інше схоже завдання.

Варто згадати про тогочасний тренд — уникати написання коду на фронтенді загалом і використовувати інструменти, що дають змогу конструювати сторінки візуально, а код генерувати автоматично. Серед таких інструментів — Vermeer FrontPage, що вийшов 1995 року (пізніше Microsoft FrontPage) та Macromedia Dreamweaver (пізніше Adobe Dreamweaver), який вийшов 1997-го.Можливість згенерувати код веб-сторінки з візуального її представлення отримав Adobe Photoshop. Тобто дуже часто фронтенд-частина сайту сприймалася як частина проекту, з якою працюють дизайнери — не програмісти, бо для останніх є бекенд.

До речі, програмування на бекенд прийшло значно раніше, ніж на фронтенд, там його місце здавалося логічнішим. Першою такою технологією, що давала змогу динамічно генерувати HTML, була технологія CGI (Common Gateway Interface), створена 1993-го,всього за два роки після запуску першого сайту. Зреалізована вона була дуже примітивно: HTTP-запит від клієнта направлявся на скрипт на сервері, який отримував параметри запиту та генерував відповідь, направивши її на стандартний вивід, що, власне, і отримував браузер у відповідь. CGI дозволяла писати код будь-якою мовою, досить було запустити її на сервері — хоч Perl, хоч C, однак загалом це робилося доволі трудомістко.

Справжнім проривом у веб-розробці стала поява PHP 1995 року — ця мова спеціально була створена для вебу й давала змогу органічно поєднати HTML та синтаксично близьку до C мову програмування. Ідея виявилася напрочуд вдалою і послугувала прообразом для Active Server Pages від Microsoft, що вийшла 1996-го,та багатьох інших технологій, які зайняли свою нішу ринку, проте не змогли наблизитися до популярності PHP навіть чверть століття після того.

Певною мірою своїм успіхом PHP завдячує тому, що браузер тоді не сприймався як серйозна платформа для програмування. Можливості JavaScript у роботі зі сторінкою були дуже обмежені, до того ж у другій половині 1990-хрозгорілися браузерні війни: Microsoft випустила свій браузер, у якому імплементувала власну інтерпретацію JavaScript під назвою JScript, і особливо проблемно було створювати кросбраузерний код.

Ось, наприклад, фрагмент коду з реального сайту 1998 року. Можна лише уявити, яке «задоволення» приносило писати щось таке:

Саме такий вигляд мав кросбраузерний код 1998 року

RIA

Як додаткове підтвердження того, що пара HTML/JavaScript не сприймалася як платформа для розробки, слід назвати появу та розквіт різноманітних плагінів, які мали бути вбудованими у веб-сторінки — чи взагалі заміняти їх — і надавати розробникам «повноцінніший» досвід програмування. Зокрема, 1996 року Sun у межах платформи Java випустила Java Applets, а Microsoft представила ActiveX, водночас компанія Macromedia придбала FutureWave Software і випустила свій плагін для браузера — Macromedia Flash, який спочатку позиціювався як медіапрогравач, але згодом став повноцінною програмною платформою.

Усі ці плагіни були сторонніми для вебу, потребували часу на завантаження та інсталяцію й не приносили особливого задоволення користувачам браузерів. Водночас можливості для програмування в браузерах саме за допомогою JavaScript розвивалися досить повільно, хоча й були перші зрушення. Зокрема, коли в Netscape відчули серйозну загрозу з боку Microsoft, то вирішили віддати JavaScript на стандартизацію в організацію Ecma International. Організація досить оперативно взялася стандартизувати та розвивати мову й упродовж 1997–1999років випустила три версії EcmaScript. Також 1997 року світ побачив Microsoft Internet Explorer 4.0 — нищівний для Netscape продукт, завдяки якому MS перемогла в браузерних війнах. Серед його особливостей була задекларована підтримка Dynamic HTML — набір технологій, до яких входили JavaScript та DOM, що нарешті давали змогу повноцінно маніпулювати вмістом HTML-сторінки на клієнтському боці й навіть динамічно застосовувати стилі.

Браузерні війни 1996–2009

Утім, розробники браузерів та плагінів об’єднали зусилля й запропонували 2002 року концепцію RIA — Rich Internet Applications, у яких ідея користуватися браузерами з плагінами подавалася як необхідність для того, щоб отримувати якісний медіаконтент та досвід роботи із сайтом загалом. Такий підхід значною мірою нівелював ідею вебу як єдиної платформи обміну інформації, бо Flash, Silverlight тощо — це, по суті, окремі незалежні платформи, контрольовані комерційними організаціями, які самостійно визначають правила гри.

Web 2.0 / Web.3.0

Уже наприкінці 1990-хстало зрозуміло, що Інтернет загалом та веб зокрема захопили світ, потіснивши всі інші мережі й способи представлення інтерактивної інформації. У січні 1999 року вийшла статтяавторства Дарсі Дінуччі, у якій уперше прозвучало про концепцію Web 2.0, авторка назвала наявний на той час веб лише ембріоном того, що має прийти в майбутньому. Основною рисою Web 2.0 була робота на пристроях з різними обчислювальними можливостями, розмірами екранів, способами введення інформації та в умовах кардинально різної швидкості зв’язку. Упродовж кількох років концепцію Web 2.0 доповнило поняття «контент», генероване користувачами, хоча тоді мало хто уявляв, яким воно стане в недалекому майбутньому з тотальним засиллям соціальних мереж. Тоді це здавалося радше як набір незалежних сайтів-блогів, на сторінках яких відвідувачі могли б залишати коментарі.

Як бачимо, концепція Web 2.0 виявилася пророчою, бо тепер веб дуже подібний до того образу, який створили два десятиліття тому.

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

Мета семантичного вебу — дати можливість машинам розуміти дані, які описує HTML. Досягнути її можна, використовуючи такі технології, як RDF (Resource Description Framework) та OWL (Web Ontology Language).

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

Наприклад, звичайний елемент div, що містить інформацію про людину, доповнений RDF-атрибутами, може мати такий вигляд:

Семантична розмітка

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

AJAX

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

Однак 1999 року разом із браузером MS IE версії 5.0 Microsoft випустила оновлену версію ActiveX бібліотеки MSXML, однією з особливостей якої була підтримка можливості без перезавантаження сторінки та асинхронно, не блокуючи потоку виконання JavaScript-коду, надіслати запит на сервер, отримати результат і за допомогою DHTML вбудувати його в сторінку.

Цікаво, що кілька років таку можливість не помічали: хоча її і використовували на певних сайтах, але загалом про масове поширення не йшлося доти, поки Google не запустила у 2004-мусервіс Google Suggest, що показав можливості технології всьому світу. У лютому 2005 року Джеймс Ґаррет опублікував статтю «AJAX: новий підхід до побудови веб-аплікацій», у якій було запропоновано сам термін та детально описано технологію, що й зумовило активне її застосування.

AJAX фактично був останнім фрагментом у тому пазлі технологій, які перетворювали рідні компоненти вебу — HTML, CSS та JavaScript — на повноцінну платформу програмування.

jQuery

З появою AJAX інтерес до програмування за допомогою JavaScript у браузері суттєво зріс, однак писати кросбраузерний код не стало простіше навіть за умов монополії браузера від Microsoft, оскільки додалися проблеми сумісності різних версій IE.

2006 року світ побачила перша версія бібліотеки jQuery, яку розробив Джон Резіґ, що надихнувся ідеєю вибору елементів HTML за допомогою селекторів CSS в іншої бібліотеки cssQuery, але вдало поєднав її зі зручними методами маніпуляції DOM та вбудував можливість робити AJAX-запити.

Для багатьох розробників, які випробовували свої сили в браузерному програмуванні, jQuery стала саме тою рятівною соломинкою, що дозволяла вибратися з трясини кросбраузерного програмування та сфокусуватися на самому завданні, а не способах його розв’язання. Інтерес до «рідного» програмування в браузері, а не до сторонніх плагінів почав суттєво зростати.

HTML5 / EcmaScript 2015

У січні 2008 року вперше побачила світ чернетка нової, п’ятої версії HTML. Крім власне модифікації самої мови розмітки, вона містила також опис значної кількості API, що перетворювали браузер на повноцінну платформу програмування. Якщо говорити власне про мову розмітки, то серед важливих змін варто назвати появу семантичних тегів і відмову від деяких тегів, що відповідали за представлення. Вихід HTML5 як стандарту затягнувся на цілих шість років. Утім, як розробники самих браузерів, так і веб-розробники сприйняли його дуже позитивно, адже нарешті він перетворював браузер на повноцінну програмну платформу, нівелюючи потребу в такому сторонньому для вебу створінні, як плагіни для RIA.

Паралельно з роботою над HTML5 велася робота й над черговою версією JavaScript. 2009 року виходить EcmaScript 5, рівно через 10 років після попередньої версії. На диво, змін за десятиліття було запропоновано відносно небагато, незважаючи на те що вже почали відчуватися ті хиби мови, які були закладені під час її створення. Лише через шість років світ побачив по-справжньому оновлений стандарт мови під назвою EcmaScript 2015, і разом з ним мова нарешті позбулася деяких дитячих хвороб, які її переслідували (наприклад, уже згадана раніше блочна область видимості), а також отримала оновлений синтаксис, зберігаючи водночас зворотну сумісність з ES5.

Саме парочку HTML5 / ES2015 варто вважати переходом веб-платформи в період зрілості, потреба в jQuery суттєво зменшилася, програмувати на чистому JS стало значно комфортніше.

Шлях стандартизації HTML5 був непростим, тривалий час існувало два окремі стандарти: від W3C та WHATWG, і лише 2019 року двом організаціям вдалося домовитися про єдиний стандарт — тепер це просто HTML Living Standardбез номерів версій, над яким оригінально працювала WHATWG. У стандартизації EcmaScript також відбулися важливі зміни: нова версія стандарту мови тепер виходить щороку, мова розвивається динамічніше й водночас зміни не навантажують розробників великими порціями.

SPA

Уже наприкінці першої декади 2000-хстало помітно, що обсяг коду на фронтенді дуже зріс, важливою стає модульність і підтримуваність рішень, jQuery в цьому аспекті мало що могла запропонувати, тому на сцену почали виходити фреймворки Single Page Application, які самою можливістю свого існування мають завдячувати AJAX.

Knockout, Backbone, ExtJS, AngularJS — далеко не повний перелік SPA-фреймворків, які почали тоді з’являтися й здебільшого використовували патерн MVC або його похідні. Сам патерн винайшли ще наприкінці 1970-х,але у веб-розробці його використання стало особливо поширеним. Вважається, що вперше MVC у вебі застосували 1996 року в маловідомому на сьогодні серверному фреймворку WebObjects, потім він швидко поширився на інші серверні фреймворки й загалом дуже комфортно почувався у вебі, накладаючись на традиційну модель комунікацій, яка передбачала перезавантаження сторінки під час кожного запиту клієнта.

Однак з появою AJAX гармонія MVC почала руйнуватися, бо, крім традиційних запитів на контролер, які мають оновити представлення, з’явилися запити, які не зовсім вкладаються в патерн. І саме за допомогою SPA цю гармонію вдалося відновити. Також у пригоді став створений на початку двотисячних Дуґласом Крокфордом формат передачі даних JSON — значно зручніший за XML. За десять років SPA розквітли й закріпилися на фронтенді, практично монополізувавши його як підхід до створення веб-рішень. Багато веб-розробників навіть не бачили альтернатив і не задумувалися про них, та й узагалі навряд чи запитували себе, чи потрібно щось інше, ніж SPA.

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

Спочатку така відповідь може збентежити, але якщо задуматися, то складно не погодитися з тим, що Single Page — це не дуже добре, оскільки в самій природі вебу закладено мати багато сторінок, щоб з’єднати їх гіперпосиланнями. І ці сторінки не мають бути просто імітацією в браузері, вони мають бути доступні будь-якому клієнту, який робить HTTP-запит до сервера за конкретною адресою, а не лише тому, який отримає мініміфікований код на JavaScript, виконає його та імперативно збудує сторінку — у такому разі ми втрачаємо декларативну сутність вебу, підміняючи його аплікаціями. Власне, тут і стає зрозумілим, що Application теж зайва — хіба ми не визначилися з тим, що HTML значно ближче до книжки чи журналу, ніж до графічного інтерфейсу комп’ютерних аплікацій?

Слід визнати, хоч би як це було прикро сучасним розробникам, які не уявляють фронтенд без SPA, що ця концепція насправді чужа для вебу, бо намагається підмінити ідеї, закладені у веб, підходами, що прийшли з розробки аплікацій з графічним інтерфейсом користувача. Хтось, можливо, вважатиме, що це не принципово, і якщо воно працює, то яка різниця, як саме воно зроблено. Але практика показує, що це не так. Усе-таки SPA виконуються в браузері, і щонайменше залишається потреба мати можливість робити посилання на окремі сторінки. Для цього почали реалізовувати deep linking, перенаправляючи будь-які запити на бекенд на одну сторінку, що є точкою входу в аплікацію, і виводячи потрібну сторінку на фронтенді. Але потім стало зрозуміло, що не можна цілком відмовитись від декларативного HTML на фронтенді й повністю підмінити його динамічною аплікацією, ліпше мати HTML-контент на сервері, як наслідок — виникло поняття Server-Side Rendering. Однак, реалізуючи SSR, виникає завдання передати стан із сервера до клієнта, це теж потребує певних зусиль на реалізацію. Також не дуже тривіальною виявляється підтримка доступності (accessibility) для SPA-аплікацій, декларативний HTML для цього ліпше пристосований. І так далі — скидається на безперервний процес, у якому розв’язання одних проблем призводить до появи інших.

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

А що в нас із фреймворками?

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

Приблизно у 2014-му AngularJS був лідером серед SPA-фреймворків, але відтоді багато що змінилося. Уже кілька років поспіль в абсолютних лідерах React, який формально є більше бібліотекою, ніж фреймворком. Проте популярність — це річ оманлива: по-перше, вона перемінна, постійно тримати корону вдається хіба що jQuery, по-друге, не завжди найпопулярніша технологія є найоплачуванішою — тут варто згадати про PHP.

Багато хто вже «поховав» Angular, але тут не все так просто: у Google переписали AngularJS з нуля, навіть ім’я змінили, повністю поламавши зворотну сумісність, проте навряд чи хтось скаже, що цим вони зробили гірше. Як наслідок — вийшов такий собі мегаконструктор SPA, який не дуже підходить для нескладних проектів, але вдало знайшов свою нішу в корпоративних. Він і далі активно розвивається, Google забезпечує серйозну підтримку — загалом майбутнє видається значно оптимістичнішим, ніж може здатися на перший погляд.

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

Але справжнє відкриття 2019 року, яке ще має себе показати у 2020-му, —це «фреймворк, що щезає» — Svelte. Поки React та Vue називають Virtual DOM своїми перевагами, Svelte, навпаки, серед переваг називає його відсутність. Але ключова його особливість полягає в тому, що після збірки аплікації в ній не залишається фреймворку як такого — аплікація компілюється в чистий JS, за допомогою якого і відбуваються маніпуляції з елементами сторінки. Це досить суттєво відрізняє Svelte від інших, хоча такий підхід використали розробники Angular в останніх версіях із новим двигуном рендерингу Ivy.

Наприкінці 2019 року серед фронтенд-розробників всього світу проводилося традиційне опитування «State of JS», у якому за рівнем цікавості Svelte посів перше місце.

Рейтинг фреймворків за рівнем цікавості 2019 року

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

Що з бекендом?

Ще з 1990-хна бекенді заправляє балом стек LAMP і похідні, створені за його образом та подобою. І питання навіть не в конкретному наборі технологій, які його формують, а в загальних принципах роботи — запити з фронтенду обслуговуються динамічно, у процесі залучена база даних та сервер аплікацій, що відносно повільно працюють та складно масштабуються по горизонталі. У такому підході принципово нічого не змінилося навіть з приходом SPA, які дозволили відмовитися від передачі згенерованих сторінок із сервера, переганяючи лише дані за допомогою RESTful API.

Водночас варто зазначити, що розробникам на бекенді доводиться розв’язувати типові завдання навіть у різних проектах — зреалізовувати аутентифікацію та авторизацію, створювати типові CRUD-операції для сутностей предметної ділянки, передавати DTO між різними рівнями аплікації, покривати все це тестами тощо. Щоб не повторюватися щоразу й перевикористовувати зроблені раніше рішення, ще з кінця 1990-хстали набирати популярність CMS (Content Management Systems), а з поширенням RESTful API — так звані Headless CMS, що взагалі не мають фронтенду.

Попри те, що CMS вдається розв’язати певну частину проблем з перевикористанням коду, проблеми з розгортанням та підтримкою серверів залишаються. Подальша еволюція таких рішень — це міграція в хмари і використання сервісів, які повністю керуються хмарними провайдерами. У цьому сенсі дуже привабливими видаються рішення, такі як Google Firebase та подібні. Поєднання можливостей аутентифікації, авторизації, API для роботи зі структурованими даними з можливостями хостингу з підтримкою CDN — серйозний аргумент проти того, щоб займатися всіма цими питаннями самостійно. Поділ монолітів на мікросервіси та використання платформ, які беруть на себе масштабування під навантаженням, — такі архітектурні рішення спонукають використовувати хмарні сервіси й не займатися питаннями керування та підтримки інфраструктури.

Одна з цікавих інновацій на бекенді, що швидко набуває популярності й здатна вплинути на прийняті підходи до розробки рішень, — це GraphQL, розроблена у Facebook технологія, що дозволяє на фронтенді сформувати запит до структури даних, які має повернути бекенд. Такий підхід позбавляє бекенд-розробників потреби створювати нескінченні CRUD-операції та загалом є гарною альтернативою до RESTful API.

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

JAMstack

Наприкінці 2017 року вийшла цікава стаття, у якій досить детально було описано стек технологій під загальною назвою JAMstack (JavaScript + API + Markup). Сам термін винайшла та активно просуває компанія Netlify, яка дуже вдало почала просувати ідею альтернативного до SPA підходу, що насправді зовсім не новий, але значно ближчий до оригінальних ідей вебу, ніж SPA.

JAMstack пропагує ідею так званих статичних сайтів, хоча термін «статичний» тут зовсім недоречний, бо насправді статичними ці сайти не є, просто, на відміну від SPA, їхній звичайний стан — це заздалегідь відрендерений статичний HTML-контент, розміщений на CDN, і динамічні вставки лише там, де треба. Бекенд розглядається у вигляді набору API, до яких можна звертатися за допомогою JavaScript, і це далеко не завжди кастомний бекенд, це можуть бути вже готові сервіси, які реалізують аутентифікацію, сервіси збереження даних і таке інше. Текстовий контент не обов’язково тримати у вигляді HTML, для цього доцільно застосувати якусь із мов розмітки, наприклад Markdown. А сам сайт оновлюється за допомогою процесів CI/CD, які стартують за тригером, наприклад після оновлення коду в системі контролю версій.

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

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

GatsbyJS — один з найвдаліших фреймворків для JAMstack, на DOU навіть є цикл публікаційпро нього, він поєднує в собі підтримку React, GraphQL, Markdown і досить гнучкий, щоб адаптуватися до різних сценаріїв використання.

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

JAMstack формують добре відомі складники

WebAssembly

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

Оскільки серед основних аргументів на користь WebAssembly називають швидкість, то ми, ймовірно, спостерігатимемо процес, коли десь там «під капотом» у реєстрі npm оновлюватимуться бібліотеки, які будуть оптимізовуватися за швидкістю з використанням альтернативних до JavaScript мов, однак їхні інтерфейси так само залишатимуться на JavaScript.

Звісно, WebAssembly поступово почне «відкушувати» частину розробників у JavaScript, цьому сприятимуть такі проекти, як, наприклад, Microsoft Blazor, призначені здійснити давню мрію бекенд-розробників: позбавити себе задоволення вивчати JS. Проте ці процеси навряд чи відбуватимуться швидко, і якщо говорити про перспективу кількох найближчих років, то монополії JavaScript на фронтенді це навряд чи суттєво загрожуватиме.

Імовірно, єдина мова, яка в найближчій перспективі хоч якось помітно здатна потіснити JavaScript у вебі, — це TypeScript, але її навряд чи можна назвати альтернативою до JS, це радше такий собі «JavaScript наступного рівня». Він опційний для використання і стає потрібен тоді, коли проект значно розростається. Тож важливо мати не лише статичну типізацію, а й інтерфейси, декоратори та інші складові, які є в TS.

Висновок

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

У цій боротьбі завжди з’являється хтось, хто відчуває в собі сили та бажання підім’яти під себе веб, встановивши монополію на браузер чи певні технології, які мають використовувати розробники. Спочатку це була Netscape, потім її витіснила Microsoft, згодом у вебі почала панувати Google, яку, своєю чергою, витісняє Facebook. Але втримувати корону ще складніше, ніж її одержати, бо сила вебу — у відкритості стандартів, і щоразу, коли його намагаються монополізувати чи інфікувати сторонніми складниками, — як, наприклад, було з RIA, — він знаходить сили оновитися й позбутися їх. Але веб не робить це самостійно — це роблять розробники, що своїми руками сьогодні надають йому тих форм, які він матиме завтра. І щоб розробляти під веб, треба розуміти його, треба відчувати його філософію, ідеї, які заклали в нього його творці. Саме тому я закликаю розробників відповідальніше ставитися до тих рішень, які ми ухвалюємо, і підходів, які ми застосовуємо, старатися менше використовувати сторонніх для вебу речей, а більше того, що нам він дає як платформа, бо, як казав геніальний Алан Кей, «немає найліпшого способу передбачити майбутнє, ніж створити його».

Контакти автора: LinkedIn, телеграм-канал, веб-сайт.

Данные важнее, чем модели. Как выглядят эффективные процессы в Data Science

$
0
0

Всем привет! Меня зовут Вадим, я Machine Learning Researcher в Wix. Работаю в продуктовых компаниях в сфере Data Science уже более шести лет. Занимался построением Machine Learning моделей и закрывал весь цикл Data Science проектов. Мне доводилось строить проекты для разнообразных бизнес-задач, а также в разных доменах ML & Deep Learning.

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

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

Этапы Data Science проекта

В Data Science, как в других IT-направлениях, уже давно есть эффективные процессы структурирования проектов. Удивительно, но далеко не все дата саентисты догадываются об их существовании. Первый фреймворк был придуман в 1996 году и называется CRISP-DM (Cross industry process in data mining). Модной фразы Data Science тогда еще не было, и говорили просто Data Mining. Интересно, что за 24 года своего существования система все ещё актуальна. Появились новые процессы, более подходящие под текущие реалии, но они так или иначе базируются на CRISP-DM. Примером для больших команд может быть процесс Microsoft, а на Медиумеесть хорошая инструкция для стартапов.

Чтобы лучше понять, как же устроена работа дата саентиста, давайте за основу возьмем CRISP-DM и пройдемся по основным этапам этой методологии (я немного изменил оригинальную схему для лучшего воcприятия):

  1. Определение бизнес-необходимости проекта и установление KPI.Обдумать KPI — задача нетривиальная, поэтому над ней зачастую не заморачиваются. Но это может привести к очень неприятным последствиям, вплоть до закрытия проекта.
  2. Работа с данными, которые необходимо где-то взять, убедиться в их качестве и подготовить для тренировки. На этом этапе нужно «засучить рукава», забыть о моральном вознаграждении и очень скрупулезно поработать. Интересный факт, что для достижения хороших результатов на этот этап тратится около 80% общего времени.Проверено на личном опыте :)
  3. Построение модели, — наверное, самый приятный этап. Мне кажется, именно из-за него программисты часто хотят перейти в Data Science. Но опытные специалисты знают, что это опасное место, на котором можно зациклиться и потратить много времени зря.
  4. Оценка качества модели — самый критичный этап. Во время построения модели мы делаем множество итераций и экспериментов, слабые места есть всегда. От того, как мы их проработаем, зависит скорость развития проекта и его финальное качество.
  5. Вывод в продакшн — во многом инженерная часть, но тесно связанная с алгоритмами Machine Learning.

Правильная коммуникация в команде особенно важна для успеха Data Science проекта. Обычно Data Scientist ведет общение на двух фронтах — с продакт-менеджером и инженером. В маленьких компаниях из-за недостатка людей дата саентисту приходится дополнительно закрывать либо продуктовую, либо инженерную часть. В некоторых компаниях пытаются искать «идеального» специалиста во всех трех сферах, но «быть профессионалом везде = быть профессионалом нигде».

Давайте подробнее рассмотрим каждый из этапов жизни Data Science проекта.

Business understanding

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

Проект с Data Science требует значительных затрат: как денежных, так временных. Это затраты на получение и обработку данных, проверку гипотез, построение модели, оценку качества, а также решения вопросов интеграции и мониторинга. В самом начале будет гораздо легче и быстрее обойтись без этого. Можно проанализировать рынок, придумать несколько базовых правил и на их основе запустить проект. И только когда этих правил станет слишком много и ими будет тяжело управлять, стоит задуматься об ML-алгоритме.

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

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

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

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

Получение данных

Для того чтобы натренировать модель определять взаимосвязи, необходимо иметь размеченные данные. Это набор примеров с характеристиками и «правильный ответ» по каждому из примеров. Например, у вас есть информация по 10к пользователям и о том, что они делали на сайте, а также «ответ»: купили ли они премиум в течение месяца. Другой пример: текст комментария в фейсбуке и оценка его агрессивности от 1 до 10.

Отмечу, что не для всех задач нужны размеченные данные. Исключение — задачи unsupervised learning (например кластеризация).

Ключевой фактор результативности модели — качество данных! Если что-то не так с данными, модель выявит неправильные взаимосвязи, и результаты не будут отображать реальность, а полезность будет нулевая. В Data Science кругах ходит популярная фраза: «Garbage in = garbage out». Никакая модель не сможет дать правильное предсказание, если данные на вход были неправильными. Именно поэтому хороший дата саентист проводит гораздо больше времени, разбираясь в данных, нежели тестируя разные модели.

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

Ниже рассмотрим основные источники получения размеченных данных.

Базы данных (логов) продукта

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

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

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

Скрэйпить из интернета

Думаю, тут сложность очевидна: вытащить данные из разных источников и унифицировать их. Вдобавок к инженерной сложности соскрейпить данные возникает другая проблема. Часть данных может не иметь никакого отношения к моделированию, и определить и исключить эти данные — достаточно кропотливая работа. Допустим, для задачи необходимо вытащить заголовки текстов с разных сайтов. Как это сделать? Вытаскивать заголовки по тегам <h1>, <h2> недостаточно, потому что пользователь может обойтись без них и просто сделать для обычного текста шрифт побольше. Вытаскивать все тексты со шрифтом больше 32pt тоже нелогично, ведь на сайте может быть весь текст с таким шрифтом. То есть чтобы получить качественные данные, нужно выбирать текст, учитывая особенности каждой отдельной страницы.

Ручная разметка

Процесс получения таких данных самый долгий и дорогой. Эти данные нужны для задач, с которыми легко справляется человек, но они сложны для алгоритма. К таким сценариям относятся reCAPTCHA, поиск опухолей на МРТ, обведение силуэта автомобиля, оценка эмоции по голосу. Почему такие задачи сложны для алгоритма? Они решаются на так называемых «неструктурированных данных». Например, две картинки с котиками разного цвета и в разном масштабе будут иметь абсолютно разные значения пикселей, хотя они и остаются котиками. Для человека это одна и та же сущность, а алгоритму необходимо будет выяснить, что эти два разных набора пикселей — один и тот же объект.

При этом автоматически получить размеченные данные для тренировки невозможно. Поэтому для таких задач человек вручную размечает N примеров, а потом эти данные используются для тренировки алгоритма. Задача ручной разметки данных с 2014 года превратилась в отдельную огромную индустрию и продолжает расти. Есть множество компаний, которые занимаются разметкой ваших данных. Например, вы платите компаниям, чтобы они разметили автомобили на ваших видеороликах. По оценкаманалитических компаний, в 2018 году рынок аутсорса Data Labelling достиг $318 миллионов, и предсказывают рост до $1,5 миллиарда к 2025. А некоторые эксперты ожидают вдвое больший рост.

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

Моделирование

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

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

Выбор алгоритма влияет на то, как и какие данные необходимо собирать. Допустим, есть задача отсортировать «объекты» по качеству. Вот два разных способа, как разметить данные, от которых будет кардинально зависеть выбор модели:

  • каждому объекту давать оценку от 1 до 10 и потом усреднить результаты;
  • показывать объекты попарно и спрашивать, какой лучше.

В целом, для дата саентиста задача моделирования сводится к следующему:

  • исправить неточности в данных;
  • добавить новые признаки, чтобы облегчить задачу алгоритму (например, к длине и ширине объекта, добавить «площадь»);
  • выбрать подходящий алгоритм и параметры тренировки;
  • натренировать модель;
  • разобраться, в каких ситуациях модель допускает ошибки;
  • повторять до готовности.

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

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

Почему важно начать с самой простой модели? Чем проще модель, тем обычно она лучше объясняет, где были допущены ошибки, и благодаря этому гораздо легче определять, на чем фокусироваться дальше. Такому принципу следуют все крупные компании уровня Google, Amazon и Facebook. У Гугла есть на эту тему очень хорошие гайдлайны.

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

При достижении каких-либо интересных результатов либо наоборот, когда прогресса нет, стоит обсудить статус модели с продакт-менеджером.

Оценка результативности и принятие решения

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

По своему опыту обратил внимание, что коммуникация результатов очень подвержена такому когнитивному искажению, как Halo effect. (Из Википедии: результат воздействия общего впечатления о чём-либо на восприятие частных особенностей. Примером может служить впечатление, что у людей с привлекательной внешностью большие умственные способности.)Он работает как в позитивную, так и в негативную сторону. В связи с этим обсуждение текущих результатов модели создает определенную эмоциональную окраску для будущих оценок. Это влияет на принятие конечного решения. И даже если все ваши решения data driven, из-за неправильного донесения особенностей выход модели в продакшн может изрядно замедлиться (например, в середине проекта решают ужесточить ранее установленный KPI).

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

Бывает, что качества модели недостаточно, чтобы выводить ее в продакшн. При этом нет четкого понимания, какие действия наверняка улучшат качество. Такая ситуация вероятна, так как Data Science проекты не имеют четко определенного пути к цели. Задача сводится к пониманию проблемы, составлению гипотез и разнообразным экспериментам. Причины неуспеха могут быть связаны как со сложностью задачи, так и с качеством и количеством данных. Умение признать нерешаемость задачи и найти достойный pivot — очень ценный навык. Хороший пример pivot`a от сложной к более простой задаче: не делать полноценную систему рекомендаций, а внутри каждой категории рекомендовать самый популярный продукт.

Выведение в продакшн

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

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

Оптимизация кода.Во время рисерча дата саентист обычно пишет «грязный» и неэффективный код. И это абсолютно нормальная ситуация, потому что построение модели — это экспериментальный и итеративный процесс. Дата саентист тестирует много идей, многие из них не срабатывают, поэтому большое количество кода меняется и удаляется. Каждый раз писать качественный код — большая трата времени. И только к моменту, когда модель дошла до статуса готовности выхода в продакшн, есть смысл оптимизировать код. Ускорение вполне может достигать 10-100 раз.И это хорошее место для вовлечения инженера.

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

Автоматизация.Обновление моделей — часто болезненный этап для проекта. Сценариев для обновления обычно два — устаревание модели и выход новой версии:

  • Устаревание модели. Для некоторых проектов это естественная ситуация, так как меняется продукт, поведение пользователей, данные. Если модель привязана к «текущему состоянию проекта» — то для того, чтобы она еще долго оставалась полезной, ее нужно обязательно обновлять. Перетренировку модели на актуальных данных, сравнение качества и выливание в продакшн можно и желательно автоматизировать. Это можно делать и вручную, но тратить на это время — не очень эффективная стратегия.
  • Выход новой версии.Когда дата саентист приходит с новой версией модели, обычно, кроме самой модели, меняется и процесс обработки данных. А это ведет к необходимости дополнительной оптимизации, а также проверки эффективности по качеству и скорости. У нас на проекте был интересный use case с нейронной сетью, где на одном из этапов мы уменьшаем разрешение картинки. Для продакшна мы заменили библиотеку для преподготовки изображения с PIL на OpenCV. И вот одна и та же функция с одним и тем же названием bicubic_interpolation давала разницу примерно в ~7%. Несложно догадаться, что это значительно повлияло на качество :) Так что тесты и мониторинг — это правильный уровень maturity Data Science проекта. (По ссылкехороший набор критериев для оценки уровня развитости вашего Data Science проекта.)

Идеальный вариант обновления модели — через А/Б тест, когда одновременно крутится две версии, чтобы удостовериться, что все корректно работает. Такой вариант не всегда возможен, поэтому чаще идут более простым путем. Собирают небольшой набор тестовых данных, которые ни одна из моделей не видела и которые не использовались для оптимизации. Эти данные служат только для финальной проверки: действительно ли новая модель работает лучше.

Итоги

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

Ключевые идеи:

  • Важно понимать целесообразность использования Machine Learning для решения задачи.
  • Установление правильных бизнес-требований — ключ к успешному проекту.
  • Главная сложность и залог успеха — в получении качественных данных.
  • Данные гораздо важнее, чем модель!
  • Процесс моделирования состоит из проверки гипотез, и вполне вероятно, что ни одна из них не сработает.
  • Деплоймент модели в продакшн — отдельный и значимый этап, который требует дополнительной автоматизации и другого подхода к данным.

Спасибо за ваше время!

Интересные ссылки

Оффер получен: как подготовиться к переезду в Берлин

$
0
0

Меня зовут Станислав Малкин, я технический специалист. В разработке уже более 10 лет, а в данный момент DevOps в небольшом стартапе (45+ сотрудников) в сфере eHealth в Берлине.

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

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

Попробуем, тем не менее, составить максимально полное руководство для иммигранта (-ки) в Берлин.

Итак, оффер получен. Что дальше?

Я с двоюродной сестрой, Берлин

До подписания

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

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

Стоит посмотреть свои дипломы и понять, в какой области возможна занятость, нужно ли будет проводить процедуру признания дипломов (немцы не признают по умолчанию наши дипломы, кроме IT-специалистов) и/или учить немецкий язык до уровня С1/С2.

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

Один из вариантов социализации — пойти на курсы или поступить в университет, особенно если диплом не признается или по профессии работать нет желания и/или возможности. С местным дипломом работу найти будет проще, а заодно и язык изучите. Высшее образование в Германии бесплатное (при условии поступления).

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

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

Надо разобраться, по какой визе вы будете проживать в Германии после переезда (на въезд дают шестимесячную шенгенскую визу D с указанием направления на дальнейшую визу — рабочую или Blue Card) и подготовиться.

Если вы хотите получить Blue Card (требования довольно простые: профильное образование и зарплата выше 55,200 евро брутто, так же смотрите FAQпо поводу Blue Card) — стоит проверить, что ваш диплом есть в списке Anabin (должен быть статус H+ или H+/- [в этом случае надо проверять конкретный факультет и специальность — если они есть в списке]) и что по офферу вы будете получать не меньше этой суммы в год. Если диплома нет в списке — отчаиваться не стоит, за 200 евро специальное учреждение проверяет ваш дипломи он может быть добавлен в базу, если будет соответствовать немецкому.

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

Узнайте, в чем будет состоять помощь компании при переезде: очень часто бывает так, что помогают с жильем на первое время, сопровождают с документами и помогают определить дату посещения министерства по делам иностранцев (Ausländerbehörde aka АБХ) на месте (вы обязаны поменять въездную визу на резидентство в течение 3–6месяцев по приезде, но тут есть нюанс, о котором чуть дальше). Это может как сильно облегчить процесс переезда, так и усложнить (есть случаи, когда не помогают ни с чем, кроме контракта).

Для многих оказывается неожиданным факт, что за уровень зарплаты можно поторговаться, уже получив контракт на подписание. Вы можете получить на 5–10%больше, даже просто спросив об этом. За спрос ведь не бьют, верно? По моим ощущениям и опыту моих знакомых и друзей, переезжавших в последнее время, уровень зарплаты в 60 тысяч евро в год и более будет вполне комфортным для старта. Рассчитать, сколько у вас будет оставаться после налогов, можно на этом калькуляторе. Стоит внимательно изучить контракт и обсудить с работодателем все непонятные или спорные моменты.

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

Также нелишним будет заранее пожить 2–3недели в Берлине, ведя тот же образ жизни, что и у себя в стране, чтобы понять, насколько комфортно вам будет в немецкой столице. Это поможет не удивляться потом моментам, которые обычно видны даже в течение недели-двух, таких менталитет населения (например, поощрение ЛГБТ-движения), отношения с местными, тот факт, что люди не парятся над подбором одежды и веяниями моды, уровень бытового обслуживания: парикмахерские услуги, медицина, транспорт, развлечения и т. д. (добавьте свое).

Берлин в декабре. @herrhehn

Контракт подписан

Попросите прислать подписанный контракт почтой DHL (так надежнее и быстрее).

Теперь можно назначать дату подачи визы и, если нужно, свадьбы (если будете уезжать вместе и еще не оформились, можно все сделать очень быстро в «Готово»). А также начинать собирать вещи (и раздавать те, которые не будете забирать с собой).

Кстати, вещи можно передать перевозчиками из Львова, отправив им вещи «Новой Почтой». Мы перевозили с помощью Юрия (брал 1 евро за 1 килограмм вещей). Доставил оперативно и без проблем.

Также можно вступить в группу «Украинцы в Берлине» (довольно живая группа, в которой можно найти анонсы мероприятий, ответы на вопросы или задать свои).

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

Виза получена

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

Ваш термин, к слову, является гарантией вашего легального пребывания в стране даже по окончании визы, но выехать из Шенгена вы не сможете (да и внутри него с невалидной визой я бы не рекомендовал передвигаться). Получение статуса резидента (по Blue Card) может занять до 8 недель с момента подачи заявки, поэтому, чем раньше подаемся, тем лучше для нас. Есть вариант прийти рано утром и получить термин в тот же день, но, во-первых, приходить надо в 4–5 утра,а во-вторых, место может находиться далеко от вашего места жительства, поэтому лучше записаться заранее.

Особый пункт — поиск жилья в Берлине. Если компания с этим не помогает, оно может быть существенной заморочкой. Я настоятельно не рекомендую снимать квартиру удаленно, но многие хотят приехать, чтобы уже было где жить (в таком случае можно воспользоваться сервисами Airbnb/Wunderflats).

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

Обязательно уточняйте, возможна ли прописка (в Airbnb/Wunderflats это обычно не проблема).

Ботанический сад в Берлине, Рождество. @herrhehn

По приезде

Регистрация

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

Жилье

Я рекомендую по приезде пожить в отеле 1–2 недели,посмотреть на город, его районы и понять, где вам будет удобнее (все районы разные). Снимать жилье сразу на долгий срок не рекомендую потому, что немцы любят контракты и приехавшему будет очень сложно найти что-то адекватное. К тому же почти всегда требуется документ, называемый Schufa (подтверждение кредитоспособности), который приезжий может получить, но он будет пустой, так как истории жизни в Германии у него не было. Поэтому шансы приезжего на успех будут существенно малы ввиду огромного спроса на аренду жилья и отсутствия у него отличительных преимуществ.

Лучше снять меблированную квартиру на 3–6месяцев (их выбор больше, и документов обычно нужно меньше) и за это время спокойно поискать долгосрочный вариант. Так как долгосрочные квартиры, как правило, идут без мебели, вам нужно будет заниматься всем: от покупки и транспортировки мебели до подключения интернета (3–4 недели)и заключения контракта на электричество. Согласитесь, ненужная нагрузка на первый месяц, когда нужно разбираться с множеством других нюансов. Заодно и с районами ознакомитесь.

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

Мобильная связь

Хорошим вариантом для старта может стать Aldi Talk. Сим-карту можно купить в любом магазине Aldi в первый же день приезда. В базовом тарифе за 8 евро идут 300 минут на звонки внутри сети и 3 гигабайта интернета, которые можно использовать по всему ЕС, как дома. Регистрация не требуется.

Страховка

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

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

Банковский счет

До недавнего времени открыть счет было очень просто: через N26 (аналог нашего «Монобанка»), не нужна была даже прописка, а только адрес для доставки письма с картой и загранпаспорт (идентификация через конференц-созвон).

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

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

Попробуйте Comdirect, Commerzbankили Deutsche Bank (обычно новоприехавшие успешно открывают счет в одном из этих банков).

Барахолки и покупка фурнитуры

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

Изучение языка

При получении Blue Card в АБХ можно запросить для своей пары бесплатное направление на интеграционные курсы, где в том числе идет преподавание немецкого языка.

Успешного переезда!

Від волонтерства на Майдані до держслужби в Одесі. Як програмістка Люба Шипович намагається змінювати Україну

$
0
0

Люба Шипович — успішний ІТ-фахівець, колишня СТО нью-йоркської компанії. У 2015 році продала її та приєдналася до реформаторської команди Міхеїла Саакашвілі в ОДА. Наразі Люба є позаштатним радником прем’єр-міністра.

Про те, чому успішна девелопер вирішила відмовитись від кар’єри задля допомоги Батьківщині, Люба Шипович розповідає спеціально для DOU.

З України я не шукала вакансій: взяла останню зарплатню і переїхала до США

За фахом я магістр комп’ютерних наук: закінчила Києво-Могилянську академію у 2007 році. Це був період після Помаранчевої революції, коли всі наші надії та сподівання йшли на спад. Загалом, в ті часи Могилянку називали «ВНЗ імігрантів»: йдеш в Могилянку — значить, наближаєшся до Борисполя. Я активно придивлялась до Нової Зеландії та Канади: завдяки спеціальним програмам ці варіанти були найпростішими для ІТ-фахівця. Та ще раніше почала подаватися на грін-карту в США: може, пощастить. І просто в день захисту диплому я отримала той самий жовтий конверт: подзвонили батьки з питанням, чи поїду я до Америки. Це було трохи несподівано для мене: я подавалась вдев’яте, тож особливо не розраховувала, що виграю її. Тоді я швидко завершила всі справи і поїхала до Штатів, особливо нічого не плануючи.

Я з третього курсу працювала в канадській компанії: країни схожі, та і правила ІТ-сектору в різних країнах подібні — мене очікувало щось звичне. Тому з України я не шукала вакансій, просто взяла останню зарплатню і приїхала до США. Втім, я мала місяць, аби знайти роботу: запаси грошей не вічні. Як математик, я одразу подивилась статистику винаймання — відгук за резюме десь 7%. Все просто: треба розсилати по 100 резюме на день, аби отримувати десь 6-7 дзвінків.Потім з’ясувалось, що я «трошки» не догледіла: статистика була за всіма спеціальностями, а за ІТ показник значно вищий — близько 50%. Тож за декілька тижнів мені довелось змінити номер телефону — мобільний просто розривався від дзвінків. Моя активність дала результат — дуже швидко я отримала два привабливих офери, навіть трошки поторгувалась між ними — і обрала першу роботу.

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

В 2011 році я запропонувала СЕО компанії зробити офіс в Україні, бо тут є кваліфіковані програмісти

Загалом в компанії я пропрацювала сім років. За цей час EZ Texting, що від початку складалася з одного інженера, стала компанією з офісами в трьох країнах: Америці, Англії, Україні. Коли я йшла з компанії, там вже працювало 200 осіб. За всі роки я також значно зросла професійно: від першого інженера до СТО. Нашу систему використовували і під час шоу American Idol — коли одночасно находили тисячі вхідних повідомлень, які треба було обробити.

В 2011 році я запропонувала СЕО компанії зробити офіс в Україні, бо тут є кваліфіковані програмісти. Основний аргумент — вони дешевші, кваліфіковані, і шукати їх швидше. За умов теперішнього перегрітого ринку в Україні не знаю, чи запропонувала б я цей варіант. Але тоді то була гарна ідея. Ми хотіли не просто робити аутсорсинг. Я працювала в такому форматі в Україні і розуміла, що в аутсорсингу люди не відчувають зобов’язання перед роботодавцем, причетність до роботи, не мають розуміння компанії та клієнта. Тож у 2011-2012 япросувала ідею, що в Україні треба створювати продуктові офіси: не offshore team, а office extension. Тоді ще не існувало такого поняття, як аутстафінг. Та, власне, ми використали саме такий формат, але називали його office extension.

Я вмовила СЕО прилетіти до України, і після купи різних перемовин, зважень усіх рішень, вирішення юридичних аспектів ми вийшли на Алекса Луцького з Innovecs. Проте на той час Innovecs існував просто в альбомі на моделях — його ще не створили. Алекс розповідав нам, якою крутою буде компанія і класним — офіс (тоді ще) на Тараса Шевченка, а ми розказали про свої плани. Отак зустрілися два мрійники і повірили одне одному. І за два місяці Алекс справді запустив офіс, а ми винайняли перших людей. Модель спрацювала: дехто з найнятих ще у 2012 році працює в компанії і дотепер.

EZ Texting був першим комерційним клієнтом MongoDB, які тоді займалися альфа-бета тестуванням. А мені якраз хотілось пробувати щось нове. Продукт був сирий, але по роботі я відвідала багато різних конференцій, де виступала і ділилась іншими нашими історіями успіху. І з самою компанією ми тісно співпрацювали — був період, коли я занурювалася в технологічну частину. Це був один з пікових періодів моєї публічності, тож у 2015 році кар’єрний портал Zippia включив мене до топ-50 жінок-розробниць Нью-Йорка.

Ми сміялись, що плітки про те, що Держдеп організував Майдан, не зовсім плітки

В 2013 році EZ Texting викупила CallFire — компанія, яка займалась голосовими повідомленнями. Я стала головним інженером текстингової платформи.

І якраз тоді в Україні починається Майдан. Я доволі скептично ставилась до тих подій: ми вже мали свою Помаранчеву революцію 2004 року, і я в курсі, чим воно закінчується. Та вважала, що кожному поколінню треба мати свій Майдан: моя молодша сестра активно брала участь у подіях, і я це схвалювала. Та в ніч побиття студентів моє ставлення змінилось. Першого грудня 2013 року я каталась на лижах, і коли спустилась і посерфила Facebook, натрапила на шквал повідомлень про побиття студентів. На щастя, з сестрою все було гаразд — вона пішла раніше, але тоді я зрозуміла, що не можу стояти осторонь. І в Україні починається нова хвиля Майдану.

Я почала думати, яким чином я можу з іншої країни включитися та допомогти. Перше, що спало на думку — наші потреби на Майдані 2004 року. Нам не вистачало електрики, щоб зарядити телефони і закип’ятити воду — тобто треба купувати електрогенератор. Я перекидаю сестрі гроші, вона купує електрогенератор і ставить його на Майдані. Отже, перший електрогенератор під стелою — мій обов’язок виконано. Та це був далеко не кінець.

На другий день мене додають до Facebook-групи «Закордонні українці для Євромайдану», де люди бідкались, що не знають, як допомогти. Я поділилась своїм досвідом, і до мене звернулись українці з Японії — щоб я через сестру придбала щось і передала для Майдану. Ми вирішили, що треба ще один електрогенератор: 700 доларів вони зібрали швидко. На ранок ми скинули японцям звіт, і гадали, що на цьому історія з допомогою закінчується.

Та це був момент вибуху: після того випадку мій PayPаl-акаунт поширюють фейсбуком, і мені без попередження починають надсилати гроші. Я не розуміла, що діється — навмисне коштів не збирала. Та з сестрою вирішили вести облік: записувати, скільки грошей надійшло, від кого, що на них купили, та зберігати чеки. Тоді все і закрутилося: спочатку я зрозуміла, що сестра сама не впорається — я почала підтягувати друзів та колишніх однокурсників. На місці організовували пари з машинами, з іншими українцями за кордоном влаштували інформаційний центр задля того, аби кожні дві години обдзвонювати всі приймальні пункти на Майдані і питати про потреби. Інколи доходило до смішного: хтось у Києві під’їжджає до КМДА, дзвонить мені і питає, куди віддавати привезене. Я з Нью-Йорка набираю КМДА, і до нього виходять зустрічати необхідне. Ми сміялись, що плітки про те, що Держдеп організував Майдан, не зовсім плітки.

Зрештою суми перелічених коштів перевалили за $2000 на день

Згодом на мене вийшли кілька американських корпорацій, які хотіли допомогти, але відкрито їм не можна було цього робити. Ці компанії прагли захистити ЗМІ від DDoS-атак. Саме тоді ми домовились про «щити» для захисту інформаційних видань «Українська правда», «Еспресо», «Громадське», а також про додатковий зв’язок.

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

Зрештою суми перелічених коштів перевалили за $2000 на день. Все це йшло на мій рахунок, тож я мала платити податки — а в США це немалі відсотки. До того ж, в США ми почали також робити протести на підтримку українського Майдану. І певної миті збагнули, що створення громадської організації спростить нам фінансову частину та процедуру отримання дозволів на протести. Спочатку ми спробували приєднатися до українських ГО, але довіри до нас не мали: ми місяць як об’єднались, і нас мало знали. Тож одного вечора ми сіли і придумали назву Razom for Ukraine — зареєстрували онлайн, подали документи на неприбутковий статус. Так і почали.

Усі ми мали роботу full-time, і вся діяльність з підтримки Майдану велась паралельно: кожен учасник був зацікавлений в автоматизації процесів. Раду директорів ми обирали на skype-зустрічах, голосування проводили онлайн, працювали в Google business suit, тобто застосовували свій досвід з бізнесу в нон-профіт секторі. Зараз НГО тільки приходять до цього. А ми мали обговорювати багато питань: бюджети, рішення, статут. Щоб не втратити неприбутковий статус, ми також мали діяти зважено — бо існували певні обмеження у діяльності.

Тобто організувалася американська частина, було ГО, і моя робота нікуди не зникла. Компанія, до речі, також динамічно зростала: була штаб-квартира, офіси в Лондоні, Нью-Йорку та Києві. Потім почалася війна, і події стали більш прогнозованими — можна було планувати на день-два, а на Майдані треба було приймати рішення за півгодини. Та простіше від того не стало.

Це був момент великого піднесення, ми ще жартували, що «впливаємо на політику США»

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

У 2014 році мало хто знав про Україну: ми не були на перших шпальтах газет. Тож ми намагалися просувати інтереси України в усякий спосіб. Наприклад, працювали з конгресменами: під час виборів до них могли записатися всі охочі (як в Україні — до депутатів). Ми підтягували українців з різних штатів — щоб вони записуватися на прийом до своїх конгресменів, брали друзів на ці зустрічі і говорили про те, що питання України їм важливе.

Якоїсь миті на нас вийшов молодий помічник Джордж Барроз, який мав родичів з України, тож прихильно ставився до нашої Батьківщини. Він і розповів, що треба робити для ефективного результату. На той момент створили законопроект 2828 про підтримку України: нам треба було його протягнути на голосування, бо він дуже допоможе Україні. Це документ, згідно з яким США матимуть законодавчу підставу надавати допомогу Україні, в тому числі військову. Без цього документу Америка не могла прийняти таке рішення. Наше головне завдання — зробити все, аби українське питання було на порядку денному якомога більшої кількості конгресменів. Адже вони підтримують ті законопроекти, які стосуються наболілих проблем своїх громадян. А оскільки багато американців — вихідці з України, шанс ми мали.

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

І нам вдалося: законопроект прочитали з трибуни, і за нього проголосували. Ми спочатку не вірили, бо тоді якраз були бюджетні слухання, коли на порядку денному стояли більш нагальні для США питання. Проте нам вдалося пролобіювати документ.

Та це був не кінець: другий рівень — добитися, щоб документ підписав Обама. Найгірше, що могло статися, — документ не відхилять і не підпишуть. Тобто він міг «зависнути», і все прийшлося б організовувати спочатку. Аби цього не трапилось, ми почали кампанію «подзвони президенту». Ми мали менше 10 днів на те, щоб переконати Білий дім, що цей документ важливий: у календарі створюємо графік, де кожні 10 хвилин хтось має телефонувати до офісу Обами. Мета — забити лінію Білого дому, щоб ніхто не міг додзвонитися. За графіком з 8:00 до 18:00 ми дзвонили, і на 8-йдень Обама врешті-решт підписав Ukraine Freedom Support Act, який став засадничим для надання допомоги Україні. Це був момент великого піднесення, ми ще жартували, що «впливаємо на політику США».

Приїхала без представлень, призначень і «корочок»: просто прийшла до ОДА

У такому режимі я жила до червня 2015 року: купа дзвінків по роботі, паралельно — по Майдану. І я зрозуміла, що більше не можу так розриватися: треба обрати щось одне. І я звільнилася. Причому пішла одразу до HR-департаменту, підписала всі необхідні папери — аби не можна було нічого відкотити.

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

Отже, я звільнилася, але не вирішила, чим саме займатимуся далі. Я поїхала додому і натрапила на пресконференцію Саакашвілі, якого тільки-но призначили губернатором Одеської області. Він говорив про те, що Україні допоможе електронне урядування. Треба діджиталізувати всі процеси, і тоді почнуться зміни на краще. Мене захопило це бачення: технічна частина — це сфера, де я фахівець з 12-річнимдосвідом. Це не просто моя тема: я можу робити те, що вмію, на благо України. І я починаю шукати контакти команди. Якоїсь миті я виходжу на Олександра Боровіка (радника Міхеїла Саакашвілі). Ми організовуємо скайп-кол, де дві години він розказує про поточну ситуацію. У нас є вибір: піти на держслужбу і бути трохи обмеженими рамками, чи піти волонтерами і робити те, що вважатимемо за потрібне. Я обрала другий варіант.

ІТ-шники, яких ніхто ніколи не кликав, хотіли долучитися до змін, і це дуже надихало

У серпні 2015 року я приїжджаю до Одеси. Я тоді до кінця не розуміла, що таке робота в держструктурі, з урядом — просто робила, як знала. Тому приїхала без представлення, призначень і «корочок»: просто прийшла до ОДА і заходила в кабінети, віталась, представлялась, хто я така, розпитувала. Багато хто дивувався і не розумів, чому я так просто поводжусь. І перші півроку приблизно в такому форматі в мене і минуло.

Для себе я бачила три головні завдання: i-government (автоматизація), ІТ-освіта, щоб виховувати кваліфікованих фахівців, та розвиток ІТ-кластера — об’єднання ІТ-компаній регіону.

Отже, перш за усе я пішла просто до канцелярії та спитала, що треба, аби перевести документи в електронний вигляд. Я сконтактувала з Мінекономіки, з’ясувалось, що ми можемо до них підключитися: вони впроваджують різні підходи і мають власну систему електронного документообігу. Мені сказали, що перш за все потрібен наказ на проведення конкурсу. Я людина не горда — пішла за папером, в інтернеті знайшла, як створювати накази, роздрукувала документ, підписала своїм іменем і віднесла до канцелярії. Щоб ви розуміли, на той момент я не мала жодної посади: я гадала, наказ — це формальність. А люди, коли побачили «офіційний документ», поставилися серйозно і почали виконувати. Я і не подумала, що він має бути від посадової особи. Це був мій перший не дуже справжній наказ.

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

Ми відібрали приблизно 20 сильних фахівців. Та девопсів у команді все одно не вистачало: з ними допомогли ІТ-компанії. Вони просто передали двох осіб, які волонтерили в ОДА, а по факту отримували ставку в себе на роботі. Я змогла отримати кімнату на +20 додаткових осіб: в адміністрації це не так просто, до речі. Та ось ми починаємо працювати в ОДА без всяких статусів. Для початку — на платформі, яку надає Google: вперше для українських шкіл вони дали можливість підключитися до Google apps для освітніх цілей. За весь час роботи нам вдалося підключити 160 шкіл, натренувати вчителів для роботи з платформою і провести силу-силенну занять з дітьми. Більшість шкіл продовжують працювати за системою і надалі.

Великий челендж: натренувати чиновників працювати з Confluence та Jira

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

Тож ми почали працювати з Confluence та Jira. Великий челендж: натренувати чиновників працювати на цьому софті. Звісно, йшло туго, а паралельно ми ще починаємо конкурс на електронний документообіг. В той час запускається Prozorro, і я наполягаю: щоб Одеська область була прогресивною, ми маємо долучитися до руху. Це був один з найскладніших кроків, бо ми почали наступати на фінансові інтереси. Ми отримуємо «добро» від Саакашвілі, і рухаємось в напрямку Prozorro.

За час роботи у держструктурі я зрозуміла головні проблеми системи. Одна з них — розмазана відповідальність в органах влади. Немає особи, яка б несла відповідальність, і через це виникає низка проблем. До прикладу, люди середньої ланки не ставлять жодних запитань, і просто роблять все автоматом. Адже і підписів вони не ставлять — все робить «керівник зверху». Та і він не проти перекласти відповідальність на когось іншого. Виходить, що ті, хто готують документи, відповідальності не мають; керівник також хоче зняти з себе «вантаж», тому просить, щоб інші люди завізували документ, поставили свої підписи, а він зверху поставив свій — наче розподіливши відповідальність між n-ною кількістю осіб. А це все час, сили, купа інстанцій, в яких паперові документи губляться «на ура» (особливо якщо є потреба, щоб ці документи загубилися).

Тому розпорядження про впровадження Prozorro на державному рівні в нас губилося п’ять разів. На різних стадіях: сьогодні можна було принести документ, а завтра отримати здивовані погляди на кшталт «у нас нічого немає, ми нічого не отримували». Тоді я дізналася про популярний у чиновників вислів: «приробити ноги документу». Це значить, якщо ти не носитимеш документ і не чекатимеш на підпис отут і зараз, нічого з місця не зрушить. І я носила, чекала на підпис — тільки так розпорядження підписали. Щоправда, коли воно пішло на друк, то внесли «випадкову» правку до суми: зі 10 000 грн вона зросла до 20 000 грн. Я переробила і пройшла всі кола заново. Це було складно, але ми розуміли цінність Prozorro: так, система не вирішує питання корупції, але вона робить її видимою. І це справді заважає корупціонерам.

Дев’ять місяців я була на держслужбі. За цей проміжок до Одеси вдалось залучити 650 млн гривень інвестицій

Я виробила для себе правило: з України треба вилітати принаймні кожні 100 днів. Бо якщо засидітися більше, складається враження, що все тут — норма. А треба дивитися, як буває інакше, розвиватися і прочищати мозок, а тоді вертатися. Я лечу до Нью-Йорка, повертаюся в січні 2016 року в адміністрацію. А на вході змінилась охорона, і мене не впізнають і не пускають. Виявляється, я пропрацювала півроку без жодної перепустки чи документу. Я подзвонила в апарат, попросила зробити мені якусь перепустку — волонтера, наприклад. На що мене питають: «А ти що, не заступник голови адміністрації?» Виявилось, що колеги, включно з топкерівництвом, вирішили, що я обіймаю саме цю посаду. Того ж дня мене роблять позаштатним радником, в мене з’являється посвідчення, і я можу спокійно приходити на роботу.

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

Декілька днів зі мною говорять посадовці, переконують. І ось якоїсь миті вони знайшли те, на чому мене можна зловити: «Якщо прийдеш не ти, то буде якийсь корупціонер. Краще ти більш ґрунтовно розберешся, ніж переконаний корупціонер, який вестиме не в той бік». І я пристаю на пропозицію, бо розумію: справді, мені є куди зростати, але є і ресурси, які мені в цьому допоможуть. Обдзвонюю своїх друзів-фінансистів, банкірів і прошу про бліц-курси, поради. Я підтягую декількох осіб зі Світового банку, МВФ, українських інвесторів та банкірів.

Загалом на держслужбі я була дев’ять місяців. За цей проміжок до Одеси вдалось залучити 650 млн гривень інвестицій. Ми жартували з журналістами: «Якою була б сума, якби цим займався хтось з більшим досвідом?» Насправді, в Одесі з інвестиціями було нескладно, і моїх компетенцій більш ніж вистачило.

Головна проблема з інвестиціями — корупція: великі інфраструктурні об’єкти мають там бути, є величезний попит і бажання вкладати, але все зупинялось через осіб, які хотіли мати з логічних процесів зиск. Інша — недокомунікації: з інвесторами треба розмовляти однією мовою — англійською. Паралельно постійно треба спілкуватися з місцевим бізнесом, аби їх звернення не йшли в нікуди. Коли я обійняла посаду, Одеса була лише на восьмому місці в Україні за інвестиційною ефективністю. І ми з командою вивели її на перше місце.

Траплялися і смішні, і страшні випадки — навіть рейдерські захоплення

У мій перший день на держслужбі я зрозуміла, чим вона відрізняється від волонтерства — мені принесли величезний стос документів на підпис. Я сказала, що фізично не зможу це все підписати, тому переходимо на електронний документообіг. Найскладніше працювати з тими, хто по 20-30років на держслужбі: показати їм, як працює система — що видно, в кого документ, як він готується, щоб бачити всі правки. І це спрощує життя всім — у тому числі і їм. Мій спосіб комунікації з людьми, які не хотіли мене розуміти — догани. Досі не знаю, як це працює, але працює: і хоча догана нічого не важить, люди її бояться.

Коли ми прийшли, багато проектів було «підвішено»: по декілька років люди чекали на рішення, необхідний документ тощо. І ми почали розбиратися: що треба, щоб це рішення з’явилось? Головна причина, чому так трапилось — корупція: коли я почала продзвонювати бізнеси і питати, що треба і чому не було прийнято те чи інше рішення, до мене ставилися недовірливо і питали, що мені треба. А коли пропонували забрати підписані (просто так) документи, надсилали юристів і шукали «підвох». Згодом люди звикли. Та траплялися і смішні, і страшні випадки — навіть рейдерські захоплення.

Весь цей час я жила на свої заощадження: ми продали EZ Texting, я мала гарний бонус, до того ж власні накопичення — десь $80 тисяч

До речі, на деякі я також їздила. Якось, незрозуміло з якої причини, сумнівний підрозділ поліції заблокував підприємство в порту Южний. Коли на заводі в гостях були інвестори з Сингапуру, приїхали люди в масках, перекрили всі виходи. Коли мені подзвонив очільник підприємства, ми одразу виїхали туди з адвокатом. На жодні наші переконування пустити адвоката «маски-шоу» не відреагували, тож ми були змушені його підсаджувати та запускати в приміщення через вікно. Ну а що? Врешті-решт, через меседжі Нефьодову, який в той час саме звітував Гройсману про інвестиційну привабливість, та інші види тиску ми домоглися, щоб завод принаймні розблокували та випустили інвесторів. На все про все пішло чотири години. До речі, потім з’ясувалось, що завод блокували за відверто замовним рішенням суду.

Весь цей час я жила на свої заощадження: ми продали EZ Texting, я мала гарний бонус, до того ж власні накопичення — десь $80 тисяч. Я знала, що можу дозволити собі рік перебування в Україні. Та довелося затриматися на півтора: коли я готувала свого наступника, Саакашвілі саме пішов з посади. Я не могла кинути власну команду: до того ж, в.о. голови адміністрації залишалася Соломія Бобровська. Через це я і затрималась на додаткові півроку. Щойно було призначено нового голову адміністрації, його першим наказом стало моє звільнення. За час роботи в уряді я коштів витратила як на хороший MBА: частину — на власні проекти, бо не звикла просити. Але якщо говорити про знання, то я їх отримала набагато більше.

Моя ідея — в тому, щоб показувати людям, що можна ставити питання «А чому ми так працюємо?» і робити інакше. Коли мене приймали на роботу, то попросили заповнити анкету від руки. Я сказала, що вже надіслала її електронною поштою, і можу продублювати, але заповнювати від руки анкету — марне гаяння часу. На що мені відповіли, що всі так роблять — навіть губернатор. Пишатися тим, що ви завантажили топ-менеджент зайвою роботою на півдня — це круто?

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

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

У січні 2017 я повернулась до Штатів. Адже усвідомлювала: я не знаю, як в Україні заробляти гроші — просто працювати в ІТ-компанії не бачила сенсу. Та і в Нью-Йорку я розуміла, що просто комерція мене більше не цікавить: у роботи має бути місія. Я пішла в стартап-інкубатор віце-президентом з інженерії. Мені сподобалась мета вирощувати нові компанії та стартапи. Перші місяці було страшенно цікаво — та потім стало зрозуміло, що в усіх стартапів приблизно одні і ті самі проблеми, і я просто циклічно виконую одну і ту саму роботу. Тому я звільнилася і почала шукати роботу через своїх агентів.

Зупинилася на компанії Flocabularly, яка спеціалізується на educational tech та робить навчальний хіп-хоп. Тобто предмети зі шкільної програми перекладають на хіп-хоп: співпрацюють з різними реперами, які з матеріалів уроків роблять речитатив, і паралельно ще існувала команда операторів та монтажерів. Працювали з різними предметами: фізика, хімія, історія. Клієнти — школи або school districts (шкільні управління). Я працювала там техлідом до жовтня 2019 року.

У липні 2019 року президент Зеленський з командою поїхав до Торонто. В команді був і Олексій Гончарук, з яким я знайома з 2014 року: ми багато співпрацювали по Одесі, коли він був радником з Мінекології. Він попросив мене зібрати в Торонто групу інвест-банкірів, людей з ІТ, щоб обговорити якусь ідею. Він презентував IT Creative: описав, що в ІТ-компаніях України є нестача кадрів, постійне змагання людей, яке сповільнює розвиток компаній. Що це відбувається через недосконалу систему освіти. Тож є ідея створити фонд розвитку ІТ-екосистеми, який може наповнюватися від податків або міжнародних донорів.

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

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

IT Creative — це платформа для обговорення та створення рекомендацій

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

Зараз немає остаточних варіантів, яким буде рішення: не треба очікувати, що прийде чиновник, який розкаже, що треба робити. Існує мільйон різних думок та поглядів. Також є купа практичних напрацювань на різних рівнях: місцевих та обласних. Усі їх треба зібрати та обробити. Чиновник зможе зібрати їх і підготувати найкращі напрацювання, але надавати інформацію — роль гравців ринку. Потрібно долучатися до діалогів, пропонувати, оскаржувати. Олексій почав діалог з ринком — так, результатом стало відторгнення, але люди почали про це говорити. І в дискусіях з’являються ідеї, які пізніше МінЦифри, яке є головним стейкхолдером, збере та оформить як напрацювання, за якими прийматимуться рішення. Нам треба змінювати бачення чиновників: це не люди, які спускають рішення; це — люди, які об’єднують всіх стейкхолдерів, розробляють кращі рішення, а потім імплементують їх на державному рівні. Це складний та міжгалузевий процес. Немає єдиного бачення — це робочий процес. Не можна за тиждень чи місяць придумати, як житиме галузь протягом наступних десяти років.

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

ІТ-галузь України досягла бар’єру, коли вона не збереже темпи зростання без кооперації з державою

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

Я відкривала офіс в Україні 2012 року — тоді були інші умови. Коли в останній компанії стало зрозуміло, що нам також треба робити аутстафінг, ми обрали Аргентину. Рівень володіння англійською мовою, часова різниця і ціна години роботи фахівців — три важливі фактори, на які звертають увагу компанії. У будь-якому разі винаймають junior чи junior to middle — senior в інших країнах не беруть, адже вони надто дорогі. Отже, за цими критеріями ми обрали іншу країну.

Так, Україні зараз є чим приваблювати: галузевими спрямуваннями, якістю експертизи — до прикладу, фінансової. Та якщо вирівняються з/п з Америкою та Канадою, то навіть у цих галузях буде важко конкурувати. Коли є office extension, компанії розуміють, що будуть незручності: перш за усе, часові. Але вони мають перекриватися вартістю чи кваліфікацією. А якщо ці незручності не будуть перекриватися — відповідно, обиратимуть інші країни. Швидкість винаймання — інший важливий показник. У Нью-Йорку — це три-чотири місяці, в Україні — до двох. Якщо ми зрівняємось за швидкістю винаймання з Америкою чи Канадою, Україна відставатиме ще більше. Тому ринок треба підтягнути — щоб наповнювати фахівцями, а ще — боротися зі стереотипами.

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

Цього разу я не можу волонтерити дуже довго — на жаль, я компанію не продала

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

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

Власне, моя поточна позиція також волонтерська. Цього разу я не можу волонтерити дуже довго — на жаль, я компанію не продала. Та мені б не хотілося кинути все на півшляху. Я бачу, що разом можна зробити багато корисного: прийшли нові люди і з бізнесу, і з університетів. Наша команда з різних країн може забезпечити робочі руки, експертизу, якої не вистачає — щоб була аналітика з-за кордону, з практиками оформлення тих чи інших рішень тощо. Зараз обмірковую варіанти, як я можу забезпечувати себе паралельно з роботою на державу. Є донорські організації, де я можу бути консультантом з фахових питань; також завжди існує можливість працювати part-time за фахом. Тим паче, зараз не обов’язково повертатися до США — в Україні багато своїх нових продуктових компаній.

Джентльменский набор инструментов для работы с Flutter и GraphQL

$
0
0

Приветствую! Последнее время я активно занимаюсь исследованием Flutter на предмет пригодности для продакшена с учетом наших потребностей. Одна из них — использование GraphQL для получения данных. Для этого я параллельно с разработчиками на ReactNative пишу то же приложение на Flutter (кстати, по ссылке — моя статья на DOU, посвященная сравнению Flutter и ReactNative). Я уже вдоволь наигрался и версткой, и анимацией, так что настало время переходить к разбору полетов в области GraphQL.

Вступление

Около 6 месяцев назад, когда я только начинал эксперименты с GraphQL, в экосистеме Flutter все было не так радужно. Основному плагину для работы с GraphQL был год отроду, а пакет artemis для генерации типов был в условном релизе всего пару месяцев. Документация разрознена, целостного решения нет, в общем — печаль.

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

Я буду рассматривать инструменты на примере Android Studio, что также подходит для всего семейства продуктов от JetBrains.

Начнем сначала: если вы не знакомы с Flutter и/или GraphQL (я не знаю, зачем вы открыли эту статью), начните с небольшой вводной:

Увидимся после прочтения :)

Подготовка

Что бы хотелось получить:

  • генерацию типов для GraphQL API;
  • полноценную работу автокомплита;
  • обновление схемы для генерации типов в один клик;
  • автодополнение и валидацию GraphQL запросов;
  • возможность работать с API, не дожидаясь имплементации на бэке.

Что для этого потребуется:

Практика

Создаем новый Flutter проект

File -> New -> New Flutter Project

В открывшемся окне оставляем выбранный пункт по умолчанию — Flutter Application.

Жмем Nextдо самого конца (ничего не меняя в настройках), и в конце — Finish.

Более красочно процесс описан в документации в разделе Test Drive.

В итоге у нас получится демо приложение с любимым каунтером.

Устанавливаем graphql_faker

npm install -g graphql-faker

или

yarn global add graphql-faker

Запускаем graphql-faker ./fake.schema --open

Запустится сервер, автоматически откроется страница в браузере для редактирования API.

Параметр ./fake.schemaуказывает файл, который будет взят за основу схемы. Так как у нас нет такого файла — за основу будет взят дефолтный мок, поставляемый с сервером.

Попробуем кое-что добавить: после 20-йстроки пишем id: ID! @fake(type: uuid)и нажмем кнопку Save, в папке с проектом появится файл fake.schema с внесенными вами изменениями. Его будет удобно в последующем использовать для старта сервера, закоммитить для шеринга между командой или как вам заблагорассудится.

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

Приятный бонус — проект поддерживает наш земляк Иван Гончаров. Сейчас активно готовится версия v2.0.0, нелишним будет поддержать коллегу пиаром или детальным баг-репортом.

Плагин JSGraphQL

Создаем файл .graphqlconfig в корне проекта. Заполняем копи/пастой

{
 "name": "Schema",
 "schemaPath": "my.schema.json",
 "extensions": {
   "endpoints": {
     "Default": {
       "url": "http://localhost:9002/graphql",
       "introspect": true
     }
   }
 }
}

Сохраняем изменения, переходим на вкладку GraphQL, дважды щелкаем на Default, выбираем Get graphql schema from endpoint:

Будет создан файл my.schema.json, содержащий свежую схему вашего АПИ.

Плагин будет удобен для контроля над ошибками и помощи в автозаполнении при написании запросов. Это легко проверить: создаем папку graphql в корне проект, в ней — файл employee_data.graphql, пробуем набрать несложный запрос:

query EmployeeData($id: ID!) {
   employee(id: $id) {
       firstName
       id
   }
}

...и радуемся работе автозаполнения.

Возвращаемся в редакторgraphql_faker, меняем у employee firstNameна firstName1, жмем Save, обновляем локальную схему и радуемся отображению ошибки.

Flutter-часть

Нам понадобится два плагина: flutter_graphqlдля работы непосредственно с GraphQL и artemisдля генерации типов.

Добавляем в pubspeck.yaml следующие строки:

dependencies:…
 graphql_flutter: ^3.0.0-beta.3
 path_provider: ^1.5.1
 equatable: ^1.0.2
 json_serializable: ^3.2.3
 gql: 0.12.0


dev_dependencies:
 ...
 build_runner: ^1.7.2
 artemis: ^2.1.4

Выполняем в консоли flutter packages get.

Artemis

Начнем с настройки artemis (подробнее о настройках — здесь).

Создаем файл build.yaml в корне проекта со следующим содержимым:

targets:
 $default:
   sources:
     - lib/**
     - graphql/**
     - my.schema.json
   builders:
     artemis:
       options:
         schema_mapping:
           - schema: my.schema.json
             queries_glob: graphql/*.graphql
             output: lib/graphql_api.dart

Запускаем генерацию типов

pub run build_runner build

или

flutter pub run build_runner build

Спустя 10-20секунд генерируется два файла:

  • graphql_api.dart;
  • graphql_api.g.dart.

flutter_graphql

Теперь попробуем добыть список компаний и посмотреть, как все работает в связке.

Возвращаемся в редакторgraphql_fakerи после 14-йстроки добавляем idдля компании id: ID! @fake(type: uuid) — это нам понадобится для корректной работы кеша. Сохраняем. Обновляем локальную схему.

Создаем новый файл graphql/companies_data.graphql.

targets:
 $default:
   sources:
     - lib/**
     - graphql/**
     - my.schema.json
   builders:
     artemis:
       options:
         schema_mapping:
           - schema: my.schema.json
             queries_glob: graphql/*.graphql
             output: lib/graphql_api.dart

Генерируем типы flutter pub run build_runner build.

Создаем файл lib/graphql_provider.dart.

import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:flutter/material.dart';

String uuidFromObject(Object object) {
 if (object is Map<String, Object>) {
   final String typeName = object['__typename'] as String;
   final String id = object['id'].toString();
   if (typeName != null && id != null) {
     return <String>[typeName, id].join('/');
   }
 }
 return null;
}

final OptimisticCache cache = OptimisticCache(
 dataIdFromObject: uuidFromObject,
);

ValueNotifier<GraphQLClient> clientFor({
 @required String uri,
 String subscriptionUri,
}) {
 Link link = HttpLink(uri: uri);
 if (subscriptionUri != null) {
   final WebSocketLink websocketLink = WebSocketLink(
     url: subscriptionUri,
     config: SocketClientConfig(
       autoReconnect: true,
       inactivityTimeout: Duration(seconds: 30),
     ),
   );

   link = link.concat(websocketLink);
 }

 return ValueNotifier<GraphQLClient>(
   GraphQLClient(
     cache: cache,
     link: link,
   ),
 );
}

/// Wraps the root application with the `graphql_flutter` client.
/// We use the cache for all state management.
class GraphqlProvider extends StatelessWidget {
 GraphqlProvider({
   @required this.child,
   @required String uri,
   String subscriptionUri,
 }) : client = clientFor(
         uri: uri,
         subscriptionUri: subscriptionUri,
       );

 final Widget child;
 final ValueNotifier<GraphQLClient> client;

 @override
 Widget build(BuildContext context) {
   return GraphQLProvider(
     client: client,
     child: child,
   );
 }
}

В файле main.dartдобавляем функцию host, которая в зависимости от платформы подправит адрес localhost’a.

String get host {
 if (Platform.isAndroid) {
   return '10.0.2.2';
 } else {
   return 'localhost';
 }
}

А MaterialApp (в том же файле main.dart) виджет оборачиваем в:

GraphqlProvider(
 uri: 'http://$host:9002/graphql',
 child: MaterialApp(...),
)

Параметр bodyменяем полностью на:

Query(
 options: QueryOptions(
   documentNode: CompaniesDataQuery().document,
 ),
 builder: (
   QueryResult result, {
   Future<QueryResult> Function() refetch,
   FetchMore fetchMore,
 }) {
   if (result.hasException) {
     return Text(result.exception.toString());
   }

   if (result.loading) {
     return const Center(
       child: CircularProgressIndicator(),
     );
   }

   final allCompanies = CompaniesData.fromJson(result.data).allCompanies;

   return ListView.builder(
     itemBuilder: (_, index) {
       return ListTile(
         leading: Icon(Icons.card_travel),
         title: Text(allCompanies[index].name),
         subtitle: Text(allCompanies[index].industry),
       );
     },
     itemCount: allCompanies.length,
   );
 },
)

Перезапустите приложение, и у вас получится что-то наподобие:

Немного подробностей реализации:

Виджет Query предоставляет нам возможность отправить запрос.

В параметр documentNode мы передаем непосредственно сам запрос, сгенерированный artemis.

options: QueryOptions(
   documentNode: CompaniesDataQuery().document,
 ),

После того как flutter_graphqlперешел в версии 3 на documentNode формат, а artemisдобавил генерацию кверей, эти две системы стали замечательно работать вместе.

В функции builderтри стандартных части:

Вывод ошибки

if (result.hasException) {
     return Text(result.exception.toString());
   }

Вывод спиннера

  if (result.loading) {
     return const Center(
       child: CircularProgressIndicator(),
     );
   }

Вывод содержимого результата

   final allCompanies = CompaniesData.fromJson(result.data).allCompanies;

   return ListView.builder(
     itemBuilder: (_, index) {
       return ListTile(
         leading: Icon(Icons.card_travel),
         title: Text(allCompanies[index].name),
         subtitle: Text(allCompanies[index].industry),
       );
     },
     itemCount: allCompanies.length,
   );
 },

Итог

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

Весь код по ссылке.

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

В комментариях оставляйте ссылки на свои любимые библиотеки для работы с GraphQL.

А также присоединяйтесь к нашей группе «Art Flutter»в телеграме — нас много, и мы рады помочь вам с решением проблем :)

IT-волонтери: як у Львові організували ІТ-курси для незрячих та популяризують вебдоступність

$
0
0

Чи можуть незрячі люди навчитись програмувати та працювати в IT? Відповідь на це питання знає Роман Боренько, співзасновник Inclusive IT у Львові. Разом з командою громадської організації він влаштував курси для незрячих з основ роботи з комп’ютером та Python. Як це переросло у соціальне підприємство, де працюють випускники курсів і до чого тут вебдоступність, Роман розповів для DOU.

Співзасновник Inclusive IT Роман Боренько

Офіційно в Україні 6-7%людей з інвалідністю. Ці люди є частиною економіки країни, хоч їхня купівельна спроможність і нижча. Бізнесу варто це враховувати, і ми прагнемо в цьому допомогти. Візьмімо, зокрема, інтернет-магазини. Люди з сенсорними порушеннями (зір, слух) не зможуть самостійно щось замовити.

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

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

Від Сенсотеки до курсів програмування для незрячих та людей зі слабким зором

Я був студентом і навчався на прикладній математиці в університеті імені Франка, посідав призові місця на олімпіадах. Так сталось, що потім на 7 років випав з громадського життя через хворобу. В 2011 році, коли настав час повертатись, я зрозумів, що хочу розвивати інклюзивність в Україні і впливати на покращення життя людей з інвалідністю.

Я зустрівся зі своїм однокласником Андрієм Максимовичем. Він разом із неймовірно цікавим незрячим активістом Миколою Пехом заснував «Інститут українських студій» — на той час організацію, що займалася міжнародними молодіжними навчальними обмінами. Я вирішив доєднатись.

У 2012-2013роках я надавав IT-допомогу організації, а потім почав впроваджувати власні ідеї і обіймати керівні посади. В 2014 році засновника Миколи Пеха не стало, і ми замислились, що робити далі, в який бік рухатись. Я на той час вже цікавився тим, як живуть і працюють незрячі, тому озвучив ідею створення Сенсотеки у Львові.

Сенсотека — це інклюзивний бібліопростір у Стрийському парку. Власне, це такий майданчик, де відбуваються інклюзивні практики, різні події для більшої включеності людей з інвалідністю у суспільство, наприклад, заняття для дітей з аутизмом, арт-терапія, літературні заходи. У Сенсотеці навіть з’явився аматорський театр третього віку, де старші люди ставлять свої вистави. Ми започаткували її діяльність у 2015 році за підтримки Львівської міської ради.

Дитяча арт-терапія у СенсотеціДитяча арт-терапія у Сенсотеці

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

Ми робили багато подій для соціалізації людей з інвалідністю, проте я давно замислювався про освіту та допомогу їм у побудові кар’єри. IT — це одна з найприбутковіших сфер діяльності, але вона малодоступна незрячим людям. Ми захотіли вирішити цю проблему і створити курси з програмування для незрячих людей та людей зі слабким зором. Так, це можливо за допомогою програм екранного доступу (наприклад, JAWS i NVDA), які озвучують усе, на що наводиться курсор.

Саме навчання заснувала Марта Дропа. Вона стажувалась у National Industries for Blind в США, де подивилась, як відбувається навчання, і побудувала систему для Inclusive IT, яка запустилася 2017 року. Звісно, постало питання, які саме курси робити: HTML, Java чи PHP, проте ґрунтовно ми зупинились на Python, тому що це найпростіша мова для незрячих, і при цьому доволі потужна. Крім того, ми виявили базові потреби у незрячих в користуванні комп’ютером, пакетом Microsoft, Google Docs, без яких працювати неможливо. Навчання триває 3-4 місяці.

На сьогодні ми маємо наступні курси:

  • користування програмою екранного доступу NVDA незрячими;
  • Word для незрячих;
  • Excel для незрячих;
  • англійська мова;
  • HTML/Javascript для незрячих;
  • Python для незрячих.

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

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

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

Більшість наших викладачів незрячі, вони краще можуть пояснити студентам необхідні речі. Англійську мову викладають Ольга Тельна (викладачка в Харківському університеті) і Марія Бекерська (шкільна викладачка). Андрій Бутенко (директор харківського підприємства СоцІнтел, займається друком книг шрифтом Брайля) — один з найпросунутіших користувачів комп’ютера, опікується базовими курсами.

Python викладає Руслан Іськов (програміст та тестувальник), який навіть створив підручник з Python для незрячих. Цей підручник — набір статей, в яких доступно пояснюється, як програмувати за допомогою асистивного програмного забезпечення.

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

Іноді на курси приходять люди, які вже десь працюють, але хочуть покращити свої навички, аби швидше працювати з комп’ютером. Наприклад, Марія Гогільчин з Івано-Франківська — незряча юристка, якій дуже допомогло знання Excel. Іноді курси допомагають людині змінити життя: зокрема, Оксана Войтко заснувала своє підприємство «Handmade-клубок»і веде сторінки в соціальних мережах, а Олександр Грищенко з Черкас працює Python-програмістом.

Засновниця «Handmade-клубок» Оксана ВойткоОксана Войтко

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

Руслан Іськов рекомендує використовувати для програмування Notepad++, і це не просто так, а тому що не всі програми добре працюють зі скрін-рідерами. Деякі програми, як і сайти, не адаптовані під потреби незрячих, це також намагається виправити Inclusive IT. Скрін-рідер — це просто озвучувач, який добре працює, якщо є забезпечення. Продукти від Microsoft, а також інструменти Google гарно пристосовані і запрограмовані з урахуванням потреб незрячих, тож ми можемо навчати ними користуватись. А все інше потрібно розглядати окремо.

Чим займається соціальне підприємство Inclusive IT та як сприяє розвитку вебдоступності

Отже, саме недоступність більшості сайтів і програм стала рушієм до створення соціального підприємства Inclusive IT. Те, чим ми займаємось, називається вебдоступністю. Ми тестуємо сайти і аналізуємо, наскільки вони доступні для людей з інвалідністю. Наші Accessibility QA`s мають сертифікати від провідних курсів з вебдоступності Deque Univeristy.

На сьогодні в команді вісім осіб: четверо тестувальників і тестувальниць, троє з яких незрячі, і адміністративний відділ. Я заохочую приходити до нас працювати студентів наших курсів. Наприклад, в Inclusive IT вже працюють випускниці Лариса Колот і Наталія Ульянова. Вони не лише тестують вручну сайти чи вебдодатки, але й враховують результати автоматичних тестів, які видає бібліотека axe-core. Завдяки курсу з англійської мови ми можемо писати баг-репорти, що дає нам переваги у роботі з іноземними клієнтами.

До нас часто звертаються з проханням протестувати сайт на вебдоступність, але набагато більше ми любимо, коли нас залучають на етапі створення сайту. Тоді ми можемо залізти в ТЗ і дати рекомендації з самого початку. Так було з нашим головним кейсом — музеєм Ханенків, створення інклюзивного сайтуякого підтримав Український культурний фонд. Цей проєкт ми робили у колаборації з командою музею, дизайнерами та розробниками з компанії BeOnline.Studio. Ми брали участь у створенні технічного завдання, аналізували дизайн, фронтенд-код для сайту. А після презентації готової роботи провели майстер-клас з доступного контент-менеджменту.

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

Якщо ви все ще не зрозуміли, що таке вебдоступність, поясню на кількох прикладах зі стандарту WCAG 2.1 (Web Content Accessibility Guidelines — Настанови з вебдоступності контенту).

  1. Чи є альтернативний текст до зображень?
    Незряча людина відкриває сайт і починає читати його за допомогою скрін-рідера. Програма озвучує весь наявний на сторінці текст, але фото саме по собі не перетвориться на текст, доступний до озвучування. Необхідно описати зображення, аби програма екранного доступу змогла його озвучити за допомогою text-to-speech. Те саме стосується і кнопок, їм теж необхідні підписи.
  2. Наскільки зручно користуватись сайтом лише з клавіатури?
    Як я згадував, незрячі користуються комп’ютером, в основному, з клавіатури. Але крім цього, є люди, які, наприклад, мають гіпс на правій руці або інші порушення опорно-рухового апарату. Вони не можуть користуватись мишкою, тож необхідно забезпечити повну функціональність сайтів та програм з клавіатури.
  3. Чи має сайт чіткі кольори та шрифти?
    Користувачі зі слабким зором можуть не помітити, наприклад, світло-сірий напис на білому фоні.
  4. Чи є можливість призупинки та відновлення для всієї анімації на сайті?
    Це необхідна вимога, що допоможе користувачам, які можуть не встигнути зрозуміти, що було на попередньому зображенні, коли насувається наступне.

Тема вебдоступності логічно увійшла до мого життя і громадської організації «ІУС», крім того, мене надихнули спроби незрячих колег працювати в IT. Мабуть, тому все і починає вдаватися. Крім того, ця тема затребувана в Європі та США, оскільки щомісяця збільшується кількість нормативних актів, що зобов’язують громадські місця, в тому числі і сайти, бути інклюзивними. Так само збільшується і кількість судових позовів для порушників. Я вважаю, що Україні слід підхопити цей рух. Необхідно надати людям можливості для освіти та працевлаштування, але на їхньому шляху перешкода — недоступні інструменти. Якщо оцінювати суб’єктивно, то в Україні невебдоступні щонайменше 90% сайтів.

Ви можете самостійно перевірити свій сайт за допомогою автоматичного тестування, яке доступне в інтернеті (плагін Axe для браузера, HTMLCodeSniffer, WebAIM та інші), але об’єктивно він виявляє не всі помилки. Наприклад, у тому полі, де має бути альтернативний текст до зображення, написано «зображення». І програма автоматичного тестування це пропустить, оскільки формально підпис є. Але це не те, що необхідно незрячому користувачу сайту. Ось чому наша команда не нехтує ручним тестуванням.

Ми хотіли б бути помічниками для будь-якого проєкту, який хоче зробити свої сервіси доступними для широкого кола користувачів. Запит на це на ринку потроху з’являється через розвиток нормативної бази, а також вплив західних практик. Є вагомі зрушення у питанні інклюзивності: наприклад, у супермаркеті «Ашан» 6% людей з інвалідністю серед всього персоналу. Або гарний приклад — пекарня Владислава Малащенка Good Bread from Good People, де люди з інтелектуальними порушеннями печуть кекси.

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

Заходи зі школярами

Третій напрямок Inclusive IT — робота зі школярами. Цього року у Львові ми активно співпрацювали зі школою-інтернатом № 100 для дітей з порушеннями зору. Зустрічі відбувались досить неформально, зі школярами ми обговорювали теми вебдоступності, інклюзивності, розбирали закордонні кейси, проводили дебати для розвитку софт-скілів.

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

Заняття зі школярами на тему вебдоступностіЗаняття зі школярами на тему вебдоступності

Ми починали організовувати курси з Python як такі, що допоможуть незрячій людині влаштуватись на роботу. А реальність виявилась такою, що спершу потрібно загалом опанувати комп’ютер, скрін-рідер та базові програми. Я щиро тішуся, що за допомогою наших курсів хтось може покращити рівень свого життя, будь це просто користування комп’ютером або працевлаштування чи заснування свого проєкту. У планах — заснувати регіональну мережу Inclusive IT, аби охопити більше міст та сіл освітніми програмами не лише через мережу Інтернет, але й живими зустрічами.

Що стосується вебдоступності, то я щасливий, що Inclusive IT є частиною великих змін в Україні, хочеться більше працювати над цим, розповідати спільноті та допомагати сайтам. Цього року ми напрацьовували експертизу, а наступного хочемо налагодити стабільний потік замовлень, працювати з IT-компаніями як аутсорсери чи з кінцевими клієнтами, а також почати створювати власний продукт. Мені хочеться, аби вебдоступність з якоїсь незвіданої ідеї перетворилася на щось повсякденне і звичайне в Україні, а на світовому ринку ми стали щонайменше впізнаваними.


Модель зрелости тестирования TPI Next: преимущества, недостатки и варианты внедрения

$
0
0

Всем привет! Меня зовут Вячеслав Сахаров, и сейчас я работаю на позиции Release Manager в компании Playtech. Начать я хотел бы с дисклеймера.

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

  • поделиться информацией о непривычных для украинского IT методологиях оценки и улучшения качества поставленных процессов;
  • рассказать о своем личном опыте внедрения TPI Next в проекты, о том, каких результатов удалось добиться и с какими подводными камнями пришлось столкнуться.

Каким образом я пришел к моделям зрелости

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

Оценка чего-либо — дело тонкое! Всегда есть опасность сделать поспешный вывод, что-то упустить, что-то недооценить. Чтобы избежать нежелательного diving into conclusions, я решил поинтересоваться, как эту проблему решали люди до меня.

После длительного периода изучения best practice в поисковиках я натолкнулся на модели зрелости управления проектами в целом. К моему удивлению CMM (Capability Maturity Model), которая является прародительницей всех ныне известных моделей зрелости, — явление родом еще с 80-х.Несмотря на то что у нас о моделях зрелости ни сном ни духом, в Америке она активно используется и показывает высокий уровень эффективности. Тут стоит отметить, что изначально эта модель была разработана по заказу вооруженных сил США, а это уже говорит о серьезности вопроса. Тем не менее использование какой-либо из этих моделей не могло ограничиться только моим отделом, а требовало вовлечения всей организации, особенно менеджмента. Мне нужно было более быстрое и узкопрофильное решение.

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

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

Модели зрелости тестирования

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

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

Среди них можно выделить три основные группы моделей зрелости:

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

Testing Maturity Model Integration (TMMi)

Дочерняя модель CMMi. Имеет те же ступени зрелости и отлично интегрируется со своей более крупной прародительницей. Если у вас в организации взяли курс на применение CMMi, то логично использовать именно ее. Из минусов: не особо гибкая и предполагает огромные массивы документации — некий привет из 80-хи CMM.

Critical Testing Processes (CTP)

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

Из минусов: есть сложности в актуализации модели, а последняя редакция сильно устарела.

Systematic Test and Evaluation Process (STEP)

Первоначально STEP была разработана из-за разочарования в стандарте IEEE, так как он не описывал, как создавать или разрабатывать процессы (планирование, анализ, проектирование, исполнение и т. д.). Методология STEP не устанавливает абсолютные правила, которые должны соблюдаться, а скорее, описывает основные принципы, которые могут и должны быть изменены, чтобы соответствовать потребностям и ожиданиям разработчиков программного обеспечения, использующих их.

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

IDEAL Model

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

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

  • инициация процесса улучшения;
  • диагностика нынешних обстоятельств;
  • разработка плана по улучшению процесса тестирования;
  • действие для выполнения улучшения;
  • ретроспектива и извлечение уроков из пройденного пути.

Test Process Improvement (TPI Next)

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

Большинство моделей зрелости (в том числе те, которых нет в этом списке) объединяет общий паттерн, по которому происходит работа с ними. У них есть 5 уровней зрелости, свои процессные области и требования, которым должна соответствовать организация для перехода на следующий уровень. Сам переход на следующий уровень в большинстве моделей предполагает соответствие организации требованиям во всех процессных областях. И тут мы плавно подходим к вопросу отличия TPI Next от родственных моделей.

Структура TPI Next

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

Модель TPI Next включает в себя:

  • 16 ключевых областей — разных составляющих процесса тестирования ПО в целом;
  • 4 уровня зрелости. Их условно можно считать этапами совершенствования процессов в компании. Цель всех моделей зрелости — переход на новый уровень;
  • 160 чек-пойнтов. Каждая из 16 ключевых областей обладает своими контрольными точками, которые служат для оценки процессов и помогают определить, к какому из 4 уровней зрелости они сейчас относятся;
  • 13 кластеров. Грубо говоря, это степень приоритетности выполнения тех или иных чек-пойнтов. Некая разбивка уровней зрелости на спринты, подразумевающие совокупность задач в разных процессных областях, которые стоит выполнять вместе.

Что отличает TPI Next от других моделей зрелости тестирования

Быстрая для старта

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

Матрица зрелости: слева — 16 ключевых областей, справа — приоритизированные чек-пойнты

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

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

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

Пример чек-пойнтов для ключевой области Test process management

Открытая документация

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

Понятные чек-пойнты

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

Сам инструмент TPI Next — Exсel-файл с простейшей матрицей (см. скрин ниже). В строку напротив ключевых областей расположены сами чек-пойнты, у которых есть своя приоритетность в алфавитном порядке (те самые кластеры). Сначала стремимся выполнить все чек-пойнты с отметкой A, затем B, C и т. д. Эту приоритетность определяете вы сами на этапе адаптации модели к своим реалиям.

Пример чек-пойнтов для ключевой области Test organisation

А теперь о самих чек-пойнтах. Каждый из них — это, по сути, требования, которые нужно выполнить. Вот, например, первые 4 чек-пойнта для области Test organisation:

A. People involved know where to find the persons (or department) responsible for test services.
B. There is a structure of control and accountability within the test organization.
C. Test tasks and responsibilities are defined (and documented) and are assigned to a person or organizational unit.
D. The products and services of the test organization are clear to its clients.

Это значит, что, выполнив все эти 4 требования, ваши процессы в этой области достигнут уровня зрелости Controlled и вы начнете переход на новый уровень зрелости — Efficient.

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

Требует дополнения и адаптации

Это однозначно самая интересная и ответственная часть работы с TPI Next. Матрица в том виде, в котором она есть, — инструмент, созданный под усредненного пользователя и его потребности. Это некий шаблон, при работе с которым вы столкнетесь с тем, что некоторые процессные области у вас напрочь отсутствуют, а некоторые чек-пойнты для вас вообще неактуальны. Грубо говоря, матрица, которую вы скачаете с сайта, — это не решение из коробки.

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

Теперь разберемся в том, что можно и нужно менять.

  • Сами чек-пойнты.Если вас не устраивают требования, описанные в чек-пойнтах, или вы находите их неактуальными для себя, перепишите их. Главное, чтобы вы были уверены в важности и достижимости каждого чек-пойнта, а их содержимое было понятно всем участникам команды.
  • Количество чек-пойнтов.Кому-то удобнее работать с более мелкими и узкими задачами, иным — смотреть на ситуацию более глобально и абстрактно. К какой бы группе людей вы ни относились, вы всегда можете подогнать под себя степень детализации чек-пойнтов и уменьшить или увеличить их количество.
  • Порядок и приоритетность.Вы уже знаете, что у всех чек-пойнтов есть своя приоритетность. Тем не менее если та или иная область для вас более значима или проседает больше других, смените приоритетность. Приоритетность всегда очень относительная и придается чему-либо только в частном порядке. Главное, чтобы вы всегда знали, за что браться далее.
  • Зоны.Несмотря на то что список ключевых зон у TPI Next исчерпывающий, некоторые из них могут оказаться для вас лишними. Или же, наоборот, некоторых областей может не хватать, как, например, мне не хватало автоматизации (которую мы добавили как 17-юзону).
  • Уровни. TPI Next построена на базовом для всех моделей зрелости количестве уровней зрелости, и, как по мне, оптимальном. Тем не менее если вас по каким-то причинам такая концепция не устроит, можно и это поменять.

Необходимо массовое вовлечение

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

  • Начальство.Для того чтобы практиковать подход TPI Next, так или иначе понадобится время. Время — это ресурс, который вам должны выделить. Во избежание дальнейших недоразумений убедитесь в том, что топ-менеджмент понимает, за что вы боретесь, поддерживает вас и готов способствовать вашим устремлениям. Как минимум некоторые чек-пойнты будут касаться вашего руководителя напрямую и требовать от него работы над собой (в случае пробелов по этой части).
  • Коллеги или подчиненные.Люди очень не любят перемены, это факт. И вам придется очень постараться, чтобы убедить их в целесообразности предлагаемых нововведений. Они будут упираться, говорить, что «раньше было лучше», что вам ничего не надо улучшать или что это не сработает. Но без них у вас ничего не получится. Совет один: убедите их попробовать, поставьте очень скромные и реалистичные цели для первого этапа и наберитесь терпения. Как только они увидят первые результаты и закрасят в табличке новые чек-пойнты зеленым цветом, энтузиазма прибавится.

Варианты имплементации TPI Next

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

Все за, а вы получаете полный карт-бланш.

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

Начальство за, а команда против.

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

Команда за, а начальство говорит «не сейчас».

Попробуйте вот что: сформируйте добровольный кружок качества (прямо как у Исикавы во время японского экономического чуда) и прикиньте, что каждый из вас может сделать, чтобы получить быстрый результат. Здесь будет рационально вспомнить и о законе Парето: 20% усилий дают 80% результата, а остальные 80% усилий — лишь 20% результата. Как только вы увидите первые плоды своих трудов, их можно использовать в качестве аргументов в повторной дискуссии с менеджментом. Если вы покажете, как это работает, то даже упрямых менеджеров удастся переманить на свою сторону.

Все против, и вы чувствуете себя Кассандрой XXI века.

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

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

Мой личный опыт внедрения

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

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

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

  • налаживание коммуникации с разработчиками и с бизнес-аналитиками;
  • тест-дизайн;
  • обучение и рост персонала;
  • ведение тестовой документации.

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

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

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

По большей части вся предстоящая работа вращалась вокруг следующих задач:

  • корректировка работы с требованиями;
  • внедрение автоматизации;
  • стандартизация документации;
  • налаживание коммуникации с разработчиками.

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

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

  • полноценное использование автоматизации;
  • организация литературного клуба для шеринга знаний;
  • подготовка команды к участию в QA-ивентах;
  • внедрение новых инструментов и процесса R&D внутри отдела.

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

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

Выводы

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

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

Даже если ваш энтузиазм в отношении моделей зрелости тестирования остался неразделенным, используйте TPI Next как инструмент оценки и разберитесь в том, какие перспективы работы в вашей компании. Если в ней все построено «кустарно», люди не стремятся к улучшению рабочего процесса и всегда против всего, стоит ли вам тратить на это свое время, ведь это ваша карьера и ваша жизнь и только вам решать, на что ее потратить.

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

Підбірка фан-відео від айтішників за 2019 рік

$
0
0

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

#MakeUsefulUnboring — гасло MacPaw.

Кажуть, у NIX відбуваються дива...

Цього року новорічний корпоратив NetPeak був у стилі весілля 90-х.Ось і відео.

Кажуть, обійми сприяють виділенню гормону щастя (серотоніну). У TeamDev перевірили цю гіпотезу. Про результати запитайте в них самостійно :)

А так у Poster зустрічають нових співробітників.


Привіт, PHP Developer!

І тобі привіт, Scrum Master!


ELEKS вирушає назустріч викликам на ракеті з педалями.

Redwork — головні фанати GoT. Дочекались виходу останнього сезону, а далі що? Фінал сподобався хоч?

Не зоовсім впевнені, що це таке, але курочка нормально співає.

А ви так можете? Давайте, спробуйте і покажіть відео #bottlecapchallenge

А так співробітники київського офісу SoftServe боролись з надмірною кількістю опадів. Плавзасіб лишився з корпоративу :)

Уявіть, якби сміття ожило і напало на вас... CleanMyMac показали, навіщо прибирати непотріб.

У ЛУН влаштували змагання: хто швидше добереться з м. Вишневе до найближчої станції метро.

IT Academy SoftServe — це коли на плейстейшн не залишається часу.

Про жінок в ІТ уже багато жартували, але так, напевно, ще ні.

AI & ML дайджест #16: data project чек-лист, научные статьи, что нас ждет в 2020

$
0
0

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

На улице зима, а это значит, что хочется быть поближе к горам. В связи с этим хочу всех пригласить на VITechGym митап, который пройдет 23 января во Львове и будет посвящен Computer Vision. А если вы любите кататься и планируете быть в Буковеле в период с 24 по 26 января, то команда спикеров митапа будет рада продолжить общение уже на склонах и вместе отлично отдохнуть ;) Присоединяйтесь! А пока предлагаю свежую подборку материалов.

Predictions

AI, Analytics, Machine Learning, Data Science, Deep Learning Technology Main Developments in 2019 and Key Trends for 2020 — редакция KDnuggets пообщалась с экспертами о том, какие были основные события в области машинного обучения и искусственного интеллекта в 2019 году и какие основные тенденции они ожидают в 2020 году.

Baidu Research: 10 Technological Trends in 2020 — прогноз 10 основных технологических трендов на 2020 год от команды Baidu Research.

Industry AI, Analytics, Machine Learning, Data Science Predictions for 2020 — мысли представителей индустрии, что нас ждет в 2020 году от таких компаний как: Alluxio, Alteryx, AppenGlobal, CasertaData, Circonus, dotDataUS, Infoworksio, Izenda, Lexalytics, Mathworks, Percona, Sisudata, and StreamSets.

Data Science Trends for 2020 — что нас ожидает в 2020, по мнению Hugo Lopes (SW Engineer & Data Science Manager at Google).

Статьи

Data project checklist — хороший список вопросов, который может вам помочь понять детали data-проекта перед его стартом.

Introducing Flyte: A Cloud Native Machine Learning and Data Processing Platform — о data-платформе, которую построили в Lyft.

NLP Year in Review — 2019 — хороший обзор NLP за 2019 год.

Open Sourcing Manifold, a Visual Debugging Tool for Machine Learning — обзор новой системы для отладки моделей от Uber.

ML4H 2019: Machine Learning for Health — обзор докладов воркшопа Machine Learning for Health, который прошел на NeurIPS 2019.

Anomaly Detection with Autoencoders in TensorFlow 2.0 — статья о том, как разработать нейронную сеть для обнаружения аномалий, используя TensorFlow 2.0.

Using neural networks to solve advanced mathematics equations

An Introduction to Biomedical Image Analysis with TensorFlow and DLTK — статья о том, как начать работать с медицинскими изображениями, используя TensorFlow и DLTK.

GPU Dashboards in Jupyter Lab — обзор расширения NVDashboard, которое позволяет мониторить GPU в Jupyter Lab.

Научные статьи

Начиная с сегодняшнего выпуска, я запускаю еще один блок, о котором просили многие. Сегодняшняя подборка научных статей — это статьи из канала #article_essence Slack-чата Open Data Science сообщества, к которому я приглашаю всех присоединяться.

Self-training with Noisy Student improves ImageNet classification

Momentum Contrast for Unsupervised Visual Representation Learning

Plug and Play Language Models: A Simple Approach to Controlled Text Generation

Analyzing and Improving the Image Quality of StyleGAN

Side-Tuning: Network Adaptation via Additive Side Networks

Stacked DeBERT: All Attention in Incomplete Data for Text Classification

Видео

Deep Learning State of the Art (2020) — MIT Deep Learning Series

2019 Conference on the Mathematical Theory of Deep Learning

Chai Time Data Science — Eugene Khvedchenya | Kaggle, Computer Vision & Best Code Practises

Конференции и митапы

VITechGym meetup: Tricks and hacks for Computer Vision — 23 января, Львов. На митапе поговорим про аугментацию и семантическую сегментацию изображений, а также про новые ML сервисы от AWS.

Data Science UA — 14 марта, Киев. Для читателей дайджеста скидка 7% по промокоду: DSdigest_7.

Data Science fwdays’20 — 13 июня, Киев. Для читателей дайджеста скидка 15% по промокоду: digest_dsfwdays.

Eastern European Computer Vision — 11-12 июля,Одесса.

Odessa Data Fest — 5 сентября, Одесса — бесплатная конференция сообщества Open Data Science. Бронируйте дату, регистрация скоро будет открыта. Если вы желаете выступить с докладом, пишите мне в личку.

На крутой healthcare проект в VITechмы ищем Data Engineer. По всем вопросам можно писать мне в личку.

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

Присоединяйтесь к Telegram-каналудайджеста и его страницам в соцсетях: Medium, Facebook, Twitter, LinkedIn.


← Предыдущий выпуск: AI & ML дайджест #15

Мотивація програміста. Як приборкати внутрішню мавпочку

$
0
0

Після тридцяти (а в декого й раніше), коли для нових проектів є вже все: і вміння, і час, і можливості, раптом виникає ситуація, що усього того, що планував на життя, усіх тих проектів, які стриміли попереду дороговказною зіркою, раптом перестає хотітися взагалі. Енергія, що раніше текла бурхливим потоком, з’являється зовсім ненадовго. І в короткі миті просвітлення хочеться тільки одного: знову чітко знати, чого хочеш. Хотіти хоч чогось.

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

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

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

Спочатку основним мотиватором було насильство

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

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

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

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

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

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

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

Ілюзія контролю

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

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

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

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

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

Звісно ж, наша свідомість не хоче визнавати своє підлегле становище й часто намагається раціоналізувати дії мавпочки, приписуючи їх собі. Наприклад, в одному експерименті людей гіпнотизували й примушували лягати на підлогу. Коли їх питали навіщо, ніхто не відповів: «Не знаю, що на мене найшло». Втрачати контроль над собою страшно. Тому один поважний чоловік «вирішив оцінити, наскільки в кімнаті м’який килим, щоб купити собі такий самий». А порядна матрона, виявивши себе на підлозі, заявила, що «просто перевіряла, як добре в кімнаті прибирають».

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

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

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

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

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

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

Чому не варто покладатися на мавпу

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

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

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

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

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

Уся наука про мотивацію — своєрідний перекладач з людської мови на мавпячу

Ну справді, скажете ви, придумаєш таке! Не вистачало мені ще з якоюсь мавпою всередині миритися. Як не буде слухати, можна ж примусити її. Узяти себе в руки, зібрати всю силу волі. Зробити ривок.

Так, звісно, можна. Тільки дуже ненадовго.

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

Насправді не зовсім. Інші дослідники копнули трохи глибше, і виявилося, що діти, котрі змогли себе стримати, були просто з багатших сімей. Для них солодощі були звичною річчю, як і довіра до батьків. Бідніші діти натомість знали справжню ціну обіцянкам і правильно вирішували, що краще брати, що дають, поки воно є. Особливо якщо це щось настільки незвично смачне. Ну а результат експерименту просто показував, що в багатших батьків діти досягають більшого. Уже не так цікаво, правда?

Горезвісне тренування сили волі — нонсенс

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

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

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

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

Найпростіший стимул — негативний

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

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

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

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

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

Рутина — це зрозумілий мавпочці мотив

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

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

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

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

Проте рутину ще треба встановити, а перші кілька разів ви, швидше за все, зіткнетеся із серйозним спротивом мавпочки. Особливо якщо вона не до кінця розумітиме, навіщо вам здалися ті м’язи, нова робота чи роман про космодесантників-зомбі. Може, краще заощадити енергію й залізти в редит? Там допаміном, кажуть, годують...

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

Як ми вираховуємо користь від дії

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

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

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

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

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

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

Але як мавпочка визначає цю ймовірність, особливо для досягнення тієї чи тієї мети? Для цього в неї є кілька критеріїв.

Самооцінка: підпишіться на Ілона Маска

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

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

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

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

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

З чітким планом — простіше

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

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

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

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

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

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

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

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

Еволюція: розмножитися й вижити

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

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

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

Розмноження, утім, часом мотивує навіть сильніше, ніж виживання. Тіло конкретної істоти рано чи пізно однаково зіпсується. А ось гени, які воно несе, можуть прожити куди довше.

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

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

Прагнення статусу

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

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

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

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

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

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

Модерні психологи навіть радять відповісти собі на запитання «Чи робив би я це, якщо ніхто про це не дізнається?» й визнають, що абсолютна більшість діяльності відбувається тільки для демонстрації своїх успіхів сусідам із соціальної групи.

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

Бажання, як відомо, мають властивість тільки нескінченно зростати й рано чи пізно призводити до вигорання рецепторів задоволення. А служіння високим ідеалам і визнання соціальної групи здатні тримати на плаву ціле життя.

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

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

Допамін та жага до пізнання

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

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

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

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

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

Усю науку створено не жагою до виживання, навіть не погонею за статусом, а простим бажанням розібратися, як працює світ. Для вченого запитання «Для чого ви змішали ці дві речовини?» звучить абсурдно. Що значить «для чого»? Щоб подивитися, що буде!

Я казав, що статус породив і мистецтво? Що ж, я збрехав, бо допаміновий складник там не менший, а то й більший. Деколи щось робиться не тому, що приносить користь, а просто тому, що це має бути зроблено. «Я пишу, бо не можу не писати». Знайомо?

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

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

Завдання, до речі, бувають не тільки особисті, але й колективні. Увесь тоталітарний устрій працює на зміщенні мотивації з власного добробуту на досягнення високих цілей. Часто вони апелюють до передання генів («майбутнє наших дітей»), але переважно жодного сенсу в собі не несуть. П’ятирічку — за чотири роки. Чому? Ну як чому, круто ж, хіба ні?

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

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

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

Насамкінець

Хочу додати ще одну ремарку.

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

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

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

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

А як ні, то ні. Може, воно вам просто не треба? Підіть краще поспіть.


Ілюстрації Каталіни Маєвської

Історичні паралелі розвитку automotive й IT

$
0
0

Я Ігор Стареправо, VP Delivery в Intellias, і відповідаю за automotive-вертикаль у компанії.

Automotive — один з доменів, що найінтенсивніше розвиваються завдяки ІТ-технологіям. Це досить традиційна індустрія, де відбуваються зміни, зумовлені входом в еру інформаційних технологій, і мені цікаво бути частиною цих глобальних трансформацій.

ІТ та automotive — дві, на перший погляд, різні індустрії, але, якщо придивитися уважніше, мають багато спільних історичних паралелей. Читаючи мемуари таких знакових осіб в автомобілебудуванні як Генрі Форд (Henry Ford) і Лі Якокка (Lee Iacocca), я помітив певну схожість в етапах їхнього розвитку, яку опишу в цій статті. Давно шукаю відповідь на одне важливе запитання: чи можливо обернути процес створення програмного забезпечення з яскравого індивідуального мистецтва програміста-одинака в індустріальну машину, що продукує якісний і функційний код, з ефективністю, властивою сучасній автомобільній індустрії?

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

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

В автомобільній індустрії все почалося з того, що 1806 року швейцарський винахідник Франсуа Ісаак де Ріваз (François Isaac de Rivaz) винайшов перший двигун внутрішнього згоряння. Через рік він збудував рухомий транспорт на базі карети, який приводили в дію через цей двигун. Навряд чи за цим одороблом хтось бачив майбутнє суспільства й світової економіки.

1886-гоКарл Бенц запатентував свій винахід — триколісний автомобіль Motorwagen, що рухався завдяки чотиритактному бензиновому двигунові, розміщеному між двома задніми колесами. Через три роки чоловік почав продавати свої автомобілі. До того часу такі продукти були справою ентузіастів, які у вільний від роботи час конструювали «саморухомі» апарати. Використання таких транспортних засобів не виходило за межі особистих інтересів аматорів, бо на вулиці панували «дорослі» парові машини.

Ранній розвиток ІТ-галузі теж не одразу здобув визнання користувачів. Він бере свій початок з експериментів у військовій галузі ще за часів Другої світової війни, з винайдення примітивних контролерів керування ракетами й систем шифрування. А 1969 рік уважають початком історії Інтернету. ARPANET — мережа, створена за дорученням міністерства оборони США, що об’єднала науково-дослідні й військові інститути в США для збільшення швидкості й поліпшення зручності обміну інформацією між ними. Цей винахід, як бачимо, теж був далекий від інтересів пересічного користувача.

1908 року компанія Ford створила Ford Model T — перше доступне авто для середньостатистичної американської родини. 241 компанія в проміжку 1904–1908 рр.виготовляла автомобілі для американського споживача, але вони коштували щонайменше вдвічі дорожче за машину Форда, були популярні в бізнесі, їх сприймали як «примхи для багатіїв». На зорі IBM PC, 1977 року, Кен Олсен, основоположник комп’ютерної індустрії, власник DEC, сказав: «Я не бачу ні найменшої потреби в комп’ютері вдома». Проте вже в 80-іроки PC почали масове проникати в малий бізнес, школи й домівки простих людей.

1913-гоГенрі Форд розпочав конвеєрне виробництво Ford Model T, зменшуючи час виготовлення одного авто до 93 хвилини, поділивши процес створення деталей на 45 кроків. Це відкриття було революційним для автомобілебудування, давши згодом новий напрямок розвитку для всього індустріального виробництва. 1918 року половина всіх американських автомобілів була Ford Model T. Це щось таке ж масове, як поширення Windows у 1990-хроках.

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

20–30-ті пам’ятають у США через Велику депресію. Автомобільне виробництво тоді зменшилося на 50%. Багато хто з нас пам’ятає dot-com bubble, коли за один рік понад 80% інтернет-компаній обернулися в порох.

У 1960-хавтовиробники сконцентрувалися на безпеці автомобілів. І в ІТ останні 10–15років спостерігається значне посилення уваги до інформаційної безпеки.

У 1990-хпочали порушувати питання поступового вичерпування ресурсів, що призвело до появи на дорогах електромобілів — технології, відомої з середини IX сторіччя. Поступове зростання потужності CPU і побудову масштабних ЦОД тепер змінюють гібридні процесорні архітектури, compute fusion, IoT та новий етап розвитку embedded-технологій.

1991-го Toyota започаткувала Lean Manufacturing. А ви, напевно, думаєте, що Agile — це унікальна ідея, що виникла в найліпших головах розробників програмного забезпечення?

Пропущена ланка

Сподіваюся, я не втомив вас своїми паралелями? Є, втім, одна дуже важлива ланка розвитку автомобілебудування, яку пропустили в ІТ. Повернімося в 1913 рік, коли конвеєрне виробництво стало причиною завоювання ринку Фордом. А що призвело до домінування Microsoft наприкінці 1990-х?З усією повагою до цих хлопців, але це не принципово новий метод розробки програмного забезпечення. Тут вплинуло багато чинників, зокрема й фокус на новий ринок домашніх PC, і партнерство з IBM, і низка досить далекоглядних вирішень, які на той час були доволі неочевидними. Однак факт залишається фактом — Microsoft ні до, ні після не винайшли принципово інших методів розробки ПЗ, і дотепер це «жупел» якості програмних продуктів.

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

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

Чому ж в ІТ досі немає свого «конвеєрного виробництва»? Одна з версій: ІТ-продукт не має проблеми тиражування, властивої автоіндустрії. Так, але навіть Model T пережила близько сотні модифікацій і редизайнів, водночас залишаючись надійним агрегатом. Інша версія — це значно більша кількість і сувора відповідність стандартам. Безумовно, уся сучасна виробнича індустрія базується на сотнях галузевих норм, стандартів і типових вирішень. Ми не замислюємося, чому болт не може бути автомобільним чи паротяговим — він такий, бо його конструкція довела свою життєздатність. У софті немає ні своєї гайки, ні болта. За більш ніж 30 років існування індустрії програмного забезпечення ми перейшли від функційного до об’єктно орієнтованого (і назад), до методів машинного навчання та розподілених мікросервісів. Але нічого конкретного так і не вибрали.

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

Висновок

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

Viewing all 8482 articles
Browse latest View live