Чому ніхто не зміг помножити кота на собаку? Фіналіст DEV Challenge розповів про участь у конкурсі та особливості програмістських змагань
Сергій Журавель — Front-end розробник, який щойно завершив участь у фіналі DEV Challenge XVIII — найбільшому європейському ІТ-змаганні, і не збирається зупинятися на цьому конкурсі. В інтерв’ю для DOU Сергій детально розповів про проходження усіх етапів від тестування і до фіналу, описав створення музичного програвача у браузері та технічні деталі задачі з котами й собаками, яку повністю не вирішив жоден із фіналістів. Можливо, свій розв’язок запропонуєте ви?
Я працюю в ІТ понад 10 років. Здебільшого як Web-розробник. Починав із Full Stack, а згодом зосередився на фронтенді. Останні кілька років моя позиція називається Front-end Lead. У мене так виходить, що зазвичай я починаю працювати просто розробником, а потім мені кажуть: «Давай ти щось полідиш, офіційно чи ні». На минулу роботу мене брали саме лідом. На поточному місці я працюю Senior-розробником і повністю керую розробкою UI для клієнта.
Моя перша комерційна мова — Java. Після неї довелося працювати з різними: PHP, C#, Python, Ruby і багатьма іншими. Але останні чотири роки моя спеціалізація — JavaScript та React. У певний момент я зрозумів, що знаю багато усього, але нічого на суперкласному рівні, тож обрав вужче спрямування.
Щодо компанії, в якій я працюю, то це звичайне питання, на яке українському розробнику буває складно відповісти. Наприклад, нерідко працюєш ніби на українську компанію, а по факту на аутстафі на іноземну. Так і я: в Україні працюю у Temy, по факту — на американську Absio.
Про DEV Challenge я дізнався випадково
Я точно не пам’ятаю, як саме дізнався про конкурс. Здається, побачив чи то рекламу, чи то допис у соцмережах. Зацікавився, почав гуглити. Інформації було небагато: лише сайт, де є опис події та вказано етапи конкурсу.
Я глянув: 18 сезонів, у яких брали участь понад 20 тисяч учасників. Змагання для всіх — без обмежень за професійним рівнем, тож приймати участь могли як Junior так і Senior. Серед номінацій — Frontend & Backend Code, Manual QA, Big Data, DevOps, Product Design & UI Design та розробка ігор: Unity & Artist.
Front-end — це якраз по моїй частині, і я давно хотів випробувати себе у схожому конкурсі. Тим паче було цікаво взяти участь в українському: я раніше не чув, щоб у нас проводили щось подібне, хіба хакатони. До того ж підкупив опис «найбільший DEV Challenge для розробників у Європі». І я такий: «Ну нічого собі, треба спробувати».
З етапом кваліфікації впорається будь-хто
Я зареєструвався, обрав свою категорію — Front-end code. Потім пройшов етап кваліфікації у вигляді тесту. Він єдиний для кожної категорії й на рівні на кшталт Junior/Middle/Senior не розбивається.
Щоб отримати доступ до задач, потрібно було набрати мінімальні 11 балів з 19 можливих. Я склав першого разу на мінімум. Здивувався, я ж бо вважаю себе спеціалістом у JavaScript. Перфекціоніст у мені загорівся бажанням скласти тест ідеально, тож згодом я спробував ще кілька разів, підвищуючи бал. Так можна, адже кількість спроб пройти тест не лімітована.
Тому етап кваліфікації виконує радше формальну функцію: враховуючи нескінченні шанси, впоратися може будь-хто. Зате це показник, що людина хоче взяти участь і готова витрачати свій час.
Не всі завдання були прості. Було кілька «tricky-питань». Наприклад:
Що виведе консоль на такий запит?
requestAnimationFrame(() => { console.log('r'); }); setTimeout(() => { console.log('s'); }, 0);
- A: r s
- B: s r
- C: залежить від браузерної технології
- D: неможливо визначити
Для плавності відтворення анімацій необхідно і достатньо, щоб кожен крок циклу очікування подій займав не більше як...
- A: 10 мс
- B: 16 мс
- C: 16.7 мс
- D: 60 мс
Та все одно максимальні 19 балів я так і не набрав. У кількох питаннях просто потрібно було уважніше переглядати варіанти відповідей. В одному, як з’ясувалося згодом, була помилка. І ще кілька питань були з вельми неоднозначними відповідями. Вже після конкурсу я обговорив це з розробником, який підтримує сайт конкурсу, і він виправив спірні моменти.
Онлайн-завдання
Після проходження тесту ти отримуєш повідомлення з таймлайном: коли і які етапи відбуватимуться, коли надійде перше завдання, дата дедлайну здачі та оцінювання тощо.
За етапом кваліфікації йде онлайн-раунд. На виконання завдання дають приблизно тиждень. Коли мені надійшов лист із задачею, я був приємно здивований: вона виявилася вельми цікавою, а ще веселою.
Треба було написати простенький UI-програвач. У результаті мала вийти програма, де користувач вводить у текстове поле мелодію (відповідно до американської системи нотації) й темп і може її прослухати.
Одна з тестових мелодій — «Імперський марш» із «Зоряних війн» — мала такий вигляд: E4/4 E4/4 E4/4 D#4/8. A#4/16 E4/4 D#4/8. A#4/16 E4/2 D5/4 D5/4 D5/4 D#5/8. A#4/16 F#4/4 D#4/8. A#4/16 E4/2.
Щоб виконати задачу, мені потрібно було почитати про аудіоконтекст — спеціальний API у браузері, який може програвати музику через частоти. За його допомогою можна моделювати та змінювати звукові хвилі. Почитав, розібрався і почав робити.
Створив основний варіант. Згідно з критеріями оцінювання, в основну задачу входили можливість програвати дві тестові мелодії, вибір тембру (музичного інструмента) з
Але були ще й бонусні завдання. Додаткові бали давали за поліфонію (можливість паралельно програвати дві мелодії з двох текстових полів) та ADSR — моделювання сигналу.
Я глянув і збагнув: виконати можу все, але щоб заробити бонусні бали, мені потрібно трохи змінити архітектуру основного застосунку.
Спочатку я робив усе через тайм-аут. У кожної ноти є певний таймінг: скільки вона має програватися для певної мелодії. І запускати наступну ноту, коли закінчилася попередня, здавалося найпростішим варіантом. Але потім це все не працювало з поліфонією: проблема була в тайм-аутах та event loop. Такі особливості JavaScript. Тож довелося математично розраховувати, скільки яка нота має програватися. Грався з часом, налаштуваннями часу в акселераторі та контексті.
Звісно, у задачі були обмеження. Їхня специфіка, найімовірніше, залежить від категорії, тож я говоритиму лише про свою номінацію. У Front-end code можна було використовувати найпростіші допоміжні бібліотеки, які не впливають на алгоритми, а лише скорочують час розробки: Lodash, jQuery, Underscore тощо.
Бібліотеки для побудови інтерфейсів на кшталт Angular, Ember, React тощо були заборонені. Тільки JavaScript, тільки хардкор. Ну й HTML та CSS, звісно :)
Також забороняли використовувати тематичні бібліотеки. Наприклад, завдання із музичним програвачем: є багато готових бібліотек і їхніх компонентів для роботи з мелодіями. З ними створити відповідний застосунок — питання кількох хвилин. І, звісно, нульової цінності виконаної роботи для проєкту і власного досвіду. Тож за використання Tone.js і їй подібних роботи учасників дискваліфікували.
Щодо витраченого часу на саме завдання, то я сидів над ним близько трьох вечорів після роботи і загалом це зайняло
Здається, це завдання сподобалося всім: по-перше — це весело, по-друге — його реально виконати. І, звісно, актуально — спробувати себе з новим API (у цьому разі AudioContent API), якого тепер виходить дуже багато.
За цей етап я набрав непогану кількість балів — 280 із 308 можливих. Думаю собі: «Ну, нічого, хоча можна було й краще. Поглянемо, що буде у фіналі». Та моя робота виявилася однією з найкращих, про що мені написали у листі з оголошенням результатів. За кількістю балів в онлайн-турі мене спрямували у категорію Hard фіналістів. Є ще Lite.
Відчуття можливої перемоги зникло у перший же день фіналу
Після вдалого онлайн-туру я був переконаний, що на фінальному етапі завдання буде схоже: знайти API, розібратись із ним та запрограмувати фановий застосунок, щоби показати — код писати вмієш, застосовувати нове можеш. І попри своє внутрішнє налаштування «головне прийти, взяти участь та отримати задоволення від процесу», я відчував, що перемогти цілком реально. Однак це відчуття зникло у перший же день фіналу.
Коли я вперше поглянув на завдання, то подумав, що воно прикольне. Коли вивчив вимоги до нього, то зрозумів, що воно ще й складне.
Задача полягала ось у чому: написати програму, яка може створювати й розв’язувати системи рівнянь з графічними зображеннями. Знаєте ці математичні приклади, які нині популярні у соцмережах? Де умовний котик + собачка дорівнюють певному числу. На кшталт такого:
Такі задачі подібні до системи рівнянь із виразом у кінці, який треба обчислити, і ми мали створити вебзастосунок, який дає можливість вводити та обчислювати такі системи виразів.
Вимоги до програми: користувач може ввести до шести виразів для обчислення, користуючись кнопковим інтерфейсом. Той, своєю чергою, має забезпечити щонайменше п’ять аргументів графічного типу: котик, собачка, кінь, півник і корівка, та чотири математичні операції: додавання, віднімання, множення та ділення, знак дорівнює і символ «?», який вказує, що саме треба обчислити.
Готова програма мала графічно виводити результат. Звичайний одним числом — для Lite-рівня, та результат з поясненнями для рівня Hard. Як бонус можна було додати можливість зберегти результат у вигляді картинки. На виконання нам давали 8 годин + 30 хвилин на обідню перерву.
І на виході мали отримати щось таке:
UI я зробив за дві години: можна було додавати котиків, собачок. Множити їх між собою, ділити, віднімати та додавати. І почав думати, як все це розв’язувати. Все-таки це нелінійні рівняння. Якби вони були лінійні, розв’язати їх було б легше. Я ще приблизно пам’ятаю з інституту їхні розв’язки за методами Гауса та Крамера.
Колись запрограмовував їх на Delfi. Для лінійного рівняння ми брали інпути і знали, де яка константа. І знали, в яке місце що вставити, коли система нормалізована і все на своїх місцях.
А тут змінних було багато. Мінімальна кількість — 5, а для Hard-рівня їх могло бути безліч. І от я сиджу, дивлюся на все це й уявляю, як ми будемо тестувати програму: людина може ввести змінні у будь-якому порядку. А отже, потрібно приводити все до нормального рівняння.
Це було нелегко: нелінійні системи рівнянь вирішуються лише дуже складними методами приблизного розв’язання. Тож я почав думати та шукати варіанти. Хотів почати з формування матриці для системи рівнянь. Але коли став міркувати, як це можна зробити для всіх варіантів вхідних даних, то зрозумів, що вхідні дані будуть надто складними. Отже, їх доведеться спрощувати і доводити до впорядкованого вигляду. І знову думав, як те все рахувати з безліччю змінних.
Я витратив на пошуки рішення багато часу. Коли дедлайн почав наближатися, один голос у моїй голові наполегливо говорив: «Візьми та спрости задачу, зроби більш лайтову версію, щоб виконати хоч щось». І це було б правильним підходом у тій ситуації.
Але голос внутрішнього перфекціоніста досить довго суперечив: «Ні. Треба лише знайти потрібний підхід — і я зможу все вирішити та перемогти». Моя проблема полягала у переконанні, що для Hard-номінації завдання потрібно виконати обов’язково саме з нелінійними рівняннями. І раптом я не розв’яжу саме з ними — отримаю 0 балів.
Врешті, коли часу залишилося обмаль, я таки спростив задачу: взяв приклади простих лінійних рівнянь і працював уже з ними. Встиг розв’язати лише прості рівняння, навіть не системи. Суто використовуючи логіку і базову математику. До цього зробив одне бонусне завдання: додав можливість користувачеві завантажувати власну картинку. У нас котики-собачки, а людина, можливо, хоче бачити у рівняннях Губку Боба.
Після цього протестував застосунок і здав — з розумінням, що зробив дуже-дуже мало. Результат фінальної задачі, як і застосунок з онлайн-раунду, я завантажив на GitHub. Та важко було не лише мені. Судді згодом жартували: «Дивимося, всі сидять по 8 годин у конференц-залі, ніхто нікуди не виходить, очей не піднімають від екранів, рук не відривають від клавіатур».
Зрештою другого дня фіналу я дізнався, що повністю це завдання не вирішив ніхто. Передчуття, що кейс складний, якщо виконувати його повністю, мене не підмануло. Судді після фіналу погодилися, що завдання виявилось важким. Іронічно, спочатку вони переймалися, чи не буде воно надто простим. Кілька суддів пообіцяли, що згодом виконають це завдання для себе і поділяться з нами результатом у чаті конкурсу в Slack. Чекаємо.
Чув про випадки, коли учасників дискваліфікували за порушення обмежень. Є готові бібліотеки, які дають змогу вирішувати окремі рівняння та системи рівнянь, з уже вбудованими розв’язками. І деякі учасники таки здалися і зробили застосунок на бібліотеці. Такі роботи не розглядали.
Ще був випадок, коли людина виконала задачу кількома способами. Перший — за допомогою бібліотеки. Другий — з форс-перебором для простих рівнянь. Учасника не дискваліфікували, але я й не впевнений, що зарахували роботу.
Щодо мене, то я вважав, що програв, одразу після здачі проєкту. Втім мала надія все ж жевріла: це конкурс, а отже, треба зробити не геть усе — треба виконати краще за інших.
До речі, брати участь у фіналі можна було як офлайн, так і онлайн. Хоча людей закликали все ж до участі наживо. Кілька останніх челенджів проходили повністю в онлайн-форматі, тож це було перше зібрання за тривалий час. Згодом чув від суддів, що у моїй номінації перемогли саме онлайн.
Не дотягнувся я лише до трійки переможців. За результатами фінального завдання я був третім. Але у загальному заліку став четвертим, бо хлопець, який посів третє місце, набрав більше балів у онлайн-раунді. Та все одно з першого разу потрапити у фінал і майже в трійку — вельми непоганий результат.
Спроба будь-що вирішити завдання повністю була моєю помилкою. Працювати треба було в напрямку набору найбільшої кількості балів, одразу спрощуючи задачу.
Friend`s day: Як проходив другий день фіналу
Після фінального раунду на нас чекав Friend’s day — це другий день фіналу, коли оголошують і нагороджують переможців. Поміж тим ще проводили тематичні презентації, виступи та панельні дискусії. Пам’ятаю про NFT, low та nocode продукти — досить цікаві та актуальні речі. Ще була доповідь про базу даних Victoria Metrics від її творця. І, звісно, куди ж без нетворкінгу та афтепаті, на яких можна почути безліч цікавих історій.
Фото моєї розмови з автором Victoria Metrics
Я тоді познайомився з учасником-викладачем, який розповів кумедну історію, що сталася під час попереднього сезону. Він оголосив своїм студентам про конкурс, порадив взяти участь. Одна з його студенток до поради прислухалася, пішла у ту ж номінацію, що й він. І виграла. А він програв. Така чудова ілюстрація «учень перевершив свого вчителя».
Незвично було у номінації Big Data, яка на конкурсі була вперше: там до фіналу дійшла лише одна конкурсантка. А на онлайн-турі було 12 людей. То їхній суддя дуже бідкався: чи не надто складне дав завдання. Задачі для конкурсу складають самі судді. Часто вони переможці минулих сезонів. Детально про всіх них можна прочитати на сайті челенджу.
Люди були дуже різні й дуже круті. І відбір — серйозний. Якщо реєстрацій на конкурс було понад 1300, до фіналу дійшли 109 людей. Що цікаво, вікових обмежень на конкурсі, здається, немає. У номінації на Back-end Lite переміг
У деяких номінаціях спонсором виступала «Дія». Їхній представник запросив усіх фіналістів на екскурсію до свого офісу. Здається, вони активно придивлялися собі людей. У кількох номінаціях, зокрема з бекенду й дизайну, завдання були пов’язані саме з «Дією». Наприклад, дизайнери мали розробити концепт спрощеної PhotoID.
Щодо призового фонду, то від «Дії» були тисяча доларів переможцям у номінаціях, за другі місця — путівки на іноземні конференції, за треті теж непогані подарунки.
Ще одним головним спонсором була компанія Readdle. Вони за перші місця давали iPad, за інші — річні підписки на їхній софт. У них близько 10 різних застосунків, і вони більше пов’язані зі скануванням та PDF-файлами. Для тих, хто користується — корисні речі.
Про враження від участі та плани
Це справді був виклик. Враження, знайомства, досвід — усе було круто. І тепер я маю чіткіше розуміння, в яких напрямах мені розвиватися.
Конкурсні завдання — непоганий тренажер для problem solving skills і навичок з побудови алгоритмів та структур даних, які ми в роботі майже не використовуємо. Тим часом ринок все більше цього потребує.
Для себе я вирішив підтягнути навички розстановки пріоритетів та розподілу часу на подібні задачі. Потренувати парсинг математичних виразів. Алгоритми, що використовують для токенізації та парсингу виразів, також застосовують при написанні мов програмування. За іронією долі у мене в браузері вже кілька місяців висить вкладка з тематичною статтею з парсингу, до якої я все ніяк не міг дійти. А ще хочу потренувати реалізацію розв’язання лінійних і нелінійних систем рівнянь.
Для усіх, кого цей матеріал надихне піти моїм шляхом, підсумую кілька порад:
- Не варто фокусуватися на розв’язанні всього завдання, якщо воно видається складним. Починайте з простих варіантів.
- Обов’язково тестуйте та використовуйте TDD-підхід, навіть для окремого найпростішого рішення.
- Нароблюйте більше кейсів, тим самим нарощуючи функціонал. Дивіться, за що саме дають бали та намагайтеся добирати їх на додаткових завданнях.
- І, звичайно, варто практикуватися, розв’язувати різні задачі — просто для власного розвитку. І не фокусуватися лише на робочих завданнях. Щонайменше варто вивчати нові API, які з’являються у браузері.
- А ще не варто ставитися до всього цього надто серйозно. Передусім конкурс — це просто фанове проведення часу у колі колег по цеху. Ми майже два роки вдома. І коли сидіти там вже несила, а повертатися в офіс бажання немає, такі події — чудовий спосіб повернутися у реальний світ. Обов’язково візьму участь і у наступному сезоні — треба ж перемагати.
Щодо інших івентів, то хотілося б випробувати себе у хакатоні, але для цього потрібно зібрати команду і добряче із нею спрацюватися. А це не так уже й легко. Схожих за масштабом і формою конкурсів в Україні чи неподалік ще не спостерігав. Знаю, що вони є у США та Індії. Раптом коментатори підкинуть ідей щодо таких челенджів — буду радий :)