Подія відбулась
Подія відбулась

Квитки на наступну конференцію Конференція JavaScript fwdays’24 вже у продажу!

# Re: щодо міграції на Vue.js 3 – лист самому собі у минуле [ukr]

Презентація доповіді

Вітаю, Ілля з 2021. Я знаю, як в тебе свербить скрізь, коли ти дивишся на Vue.js 3 та передчуваєш як будеш хедлайнером цієї міграції в свої компанії. Як на тебе чекає слава, підвищення та гордість від технічних досягнень – ще ніколи ти не стикався с завданням такої складності.

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

Ілля Климов
JavaScript.Ninja
  • 18 років пише на JavaScript, вже пʼятий рік – у GitLab
  • Мейнтейнер @vue/test-utils та bootstrap-vue
  • Наразі розвиває проект україномовного контенту JavaScript.Січ, щоб україномовні javascript-розробники були одними з найкращих в світі
  • Twitter, GitHub, Medium

Транскрипція доповіді

Ну що, всім привіт. У нас дуже мало часу, тому я не буду довго представлятися. Хоча, як кажуть, я вже так довго виступаю на фреймворку, що це варто трошки оновити. Маю за плечима 18 років загального досвіду. Цього року жартували, що мій досвід можна відокремити від мене і називати окремо. Так що, навіть якщо ви мене не знаєте, нічого, все, що вам потрібно знати, я розкажу в рамках цієї доповіді. Працюю в GitLab вже п'ятий рік і зараз займаюся, можливо, найскладнішим завданням у своєму професійному житті. Я є функціональним керівником групи, яка мігрує з Vue 2 на Vue 3.

Проте наша доповідь не буде про Vue. Вона буде трошки, лише трошки, стосуватися JavaScript. Чому? Тому що JavaScript-екосистема, на жаль, дуже молода. У цій екосистемі питання про такі масштабні оновлення є дуже болісними. Можливо, тільки React з самого початку, з версії 0.x, постійно стикається з питанням, як правильно оновлюватися. Хоча зараз, коли ми говоримо про зміну парадигми React з введенням React Server Components, це також призводить до великої зміни в кодовій базі. І якось останні роки Angular, можливо, ті, хто пам'ятає, має проблеми з оновленням. Сучасний Angular теж дуже уважно ставиться до цього питання.

Отже, якщо виключити ці два фреймворки, скрізь є проблема, і Vue, на жаль, не є винятком. Тому, насправді, якщо ви слідкували за програмою, дуже довго вона виглядала як To Be Announced, тому що первинна версія звучала саме так. Великі завдання, 50 відтінків болю. Ті, хто слідкує за мною, знають, що я люблю робити доповіді в останній момент, але це було дуже важко. Спойлер, до речі, ми ще не завершили міграцію, навіть за моїми оцінками, і тому ця доповідь є таким проміжним етапом, коли ми дивимося і через 5-10 місяців можемо оцінити, чи був я правий чи ні.

Але я розробив близько 50 пунктів того, про що я планую розповісти, і про що я хочу знати, починаючи цю міграцію. Питання, коли я розпочав цю міграцію, досить філософське. Воркінг-група була утворена цього року, але я особисто працював над міграцією, навіть поза GitLab, у власний час, приблизно два роки. За цей час я став мейнтейнером Vue Test Tutorials, основного тестового фреймворку для тестування Vue, і Bootstrap Vue, бібліотеки, яка реалізує Bootstrap у Vue. Чесно кажучи, я не хотів обидвого. Це було вимушеною подією.

Але, на жаль, якщо я спробую розповісти все це за 30 хвилин, я, можливо, перевершу Тіна Канделакі, яка в свій час була найрозумнішою. Треба відсікти, як кажуть, обсяг нашої доповіді, тому ми розглянемо тільки ці 15 пунктів. Проте, якщо ви хочете більш детальну доповідь, ось посилання на канал JavaScript Seed, де я просуваю українське JavaScript Community. Ми щотижня випускаємо JavaScript-балачки, де я роблю огляд новин. І банк. Як завжди, підтримуємо ЗСУ, завдяки яким ми можемо жити, особливо я, в Харкові.

Отже, дуже амбіційна ціль - 100 тисяч. Якщо ми зберемо цю суму протягом цієї доповіді та під час спілкування у Діскорді, то вже завтра о 16:30 я проведу з вами прямий ефір тривалістю 2-3 години, де розповім про всі ці 50 пунктів. Якщо зберемо менше, то всі подробиці будуть розписані. Проте не поспішайте з донатами, оскільки цей QR-код та посилання будуть на кожному слайді. Подивіться, що я розповідаю, і чи є сенс чи ви зацікавлені. Тим, хто вже почав донатити, я бачу за нотифікацією на моєму телефоні, висловлюю свою особисту повагу. Вас чекає особиста поіменна подяка у Діскорді, а зараз переходимо до контенту.

Три головні категорії. Перша категорія, яку я називаю "Всесвіт". Це все, що оточує нас. Наприклад, я, як лінійний розробник і старший фронтенд-інженер, питав себе, чому мені б хотілося, щоб у GitLab був Vue 3. Чому - це не так важливо, це нецікаве питання, але я маю право хотіти що завгодно. Щоб це здійснилося, потрібна співпраця багатьох людей. Перед тим як ми продовжимо, важливо внести зауваження. Одне з найчастіших питань, яке мені ставлять, - як відрізнити junior від middle та від senior. І ось моя відповідь: їх відрізняє ефективний горизонт планування. Якщо ви junior, ви розумієте, що робитимете наступного тижня; якщо middle - ви розумієте, що робитимете наступного місяця; якщо senior - ви розумієте, що робитимете наступного року.

І ще одне. Тому, коли я бачу senior'ів, які працюють в кожному місці по півроку, у мене виникає багато питань. Для того, щоб побачити наслідки прийнятих рішень, потрібно багато часу. Якщо ви junior і щось накодили, вас можуть покрити по голові на кодрев'ю, якщо ви senior+, ви прийняли рішення, і чи воно працює, ви побачите, можливо, через рік. Так що, якщо ви приймаєте рішення, що GitLab потрібен Vue 3 або ваш проект потрібно рефакторити, це надзвичайно важка задача.

Що таке надзвичайна задача? Це та, яку ви не зможете виконати самостійно, не повністю розумієте, як її виконати, і вона несе ризики, які важко оцінити на початку. Перше питання, на яке вам потрібно відповісти: "Чому це потрібно?". Я спеціально написав його так, ігноруючи український правопис, бо так воно звучить пафосніше. Коли ви пропонуєте ідею комусь, навіть своєму колезі, менеджеру чи тімліду, вам трошки інакше потрібно поставити це питання. Це звучить як "чому б не вийшло". Ви повинні мати розуміння, чого ви хочете досягти, і вірити у це.

Що до кого? Зазвичай, програмісти люблять казати дві речі. Перше - це "це покращить нашу продуктивність". Але повірте мені, якщо продуктивність вас зараз не турбує, ви цього не продасте. Як перевірити, чи вас турбує? Просто відкрийте свій трекер задач і перевірте, чи є відкладені задачі по продуктивності, не просто загальні ідеї, а конкретні завдання. Якщо їх немає, можливо, вашому проекту це не так важливо. І друге, що люблять казати, це "це важливо для майбутнього, бо це легасі". Коли нові технології приходять, ми будемо краще вибирати і привертати таланти. І вам можуть сказати: "Чому б просто не використати нову, більш гіпстерську технологію?". А вам треба буде довести, що вам це дійсно потрібно, а не просто для "гіпстерства". Технологія нова, досліджень немає, і прийняття рішення на основі нової технології може призвести до проблем.

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

Отже, я говорю: "Подивіться, для успішної продажу GitLab дуже важливо бути безпечним. Тому що будь-яка компанія, яка дбає про безпеку або вимагає її, наприклад, державні установи, особливо в Америці, або медичні організації, безпека є критично важливою бізнес-величиною. Бізнес важливий, не просто абстрактно гарний, а справжній для бізнесу. А ви знаєте, Vue 2 завершує свій життєвий цикл, включаючи оновлення безпеки, в кінці цього року. І що ви будете робити? Як ви будете пояснювати клієнтам?

Вони можуть сказати: "Ну, буде компанія HeroDevs, яка буде підтримувати після завершення". І я кажу: "Що це означає?" У вас буде так, наче ми делегуємо питання безпеки фундаментального фреймворку, який є в основі продукту, якимось невеликим, маловідомим компаніям. Ну, якось не дуже, розумієте? Тому, доки ви не знайдете щось, де бізнесу болить, це надзвичайно важко. Можна й не починати. Друге, тімлідам. Тільки не показуйте їм цей малюнок, який ви показуєте менеджерам, тому що зазвичай менеджери вважають, що вони ведуть команду в світле майбутнє, хоча, на мій погляд, це роблять тімліди. Тому тімлідам теж потрібно знайти свій сильний момент.

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

Потрібен план або хоча б переконання, що це не буде глобальним переписуванням, що це буде послідовним ітеративним покращенням. Це надзвичайно важливо. І дедлайни. Якщо ви, це дуже важливо, чому? Тому що, а, нам потрібно, ми хочемо переписати на Vue 3. А доколи? Та ну не знаю, це дуже велика задача, дуже важко прогнозувати. Тобто ви приходите до тімліда і кажете, у тебе інженерна команда буде зайнята чимось, не знаємо скільки і не знаємо з яким результатом. Ви приходите до бізнесу і кажете, а ми будемо займатися цією річчю, але не знаємо коли. Дедлайн важливо поставити такий, щоб ви в нього вірили. Ви не зможете поставити адекватний дедлайн. У нас зараз стоїть дедлайн 31 жовтня чи листопада цього року, я не пам'ятаю. Я в нього не те, щоб дуже вірю, але це чому? Тому що на початку в мене було набагато менше розуміння тих проблем, які є, аніж зараз. З цим я працюю і йдемо далі. Ми ж все-таки інженери, конференція для інженерів про код. Якщо ви вважаєте, що писати поганий код, то погано, краще не починайте. Краще не починайте займатися ось таким послідовним рефакторингом, бо ваше завдання – це єдиний шлях, який я поспілкувався десь з 12 людьми, які займалися завданнями подібного розміру у компаніях у Фаанзі, у компаніях рівням трішки менше на кшталт Uber, на кшталт Booking.

Так от, якщо ви… процедура міграції є однозначним погіршенням архітектури системи. В ній будуть з'являтися костелі, пов'язані з тим, що це можна, я знову і знову буду підкреслювати, зробити тільки ітеративно, а це означає, що треба підтримувати і те, і те, тож струнка «Система милить» на вас чекає. Найжахливіше, що вас чекає, це неявні поведінки. Як кожна система має у себе неявні поведінки, про які мало хто замислюється. Ну, можливо, хіба що розробники на C++ та C, де прямо окремий розділ стандарту описаний, що оце undefined behavior, але ж ми JavaScript-хіпстери, в нас такого немає, тому готуйтесь до того, що будь-яка неявна поведінка між версіями може бути зламана і, скоріше за все, зламана, особливо якщо автори взяли це, переписали з нуля, як це було з Vue 2 та Vue 3. Найпростіший приклад, який можна пояснити, навіть якщо ви не знаєте Vue зовсім.

Отже, у вас є компонент, і у Vue є механізм, за допомогою якого можна робити двобічне зв'язування. Тобто, коли змінна foo оновлюється, у компонент приходить нове значення, а коли компонент, генеруючи подію з назвою input, генерує її, значення цієї події автоматично оновлює змінну foo. Ну, двобічне зв'язування, якщо прив'язали до input, ви міняєте зміну, змінюється текст у input, ви у input щось набираєте, змінюється зміна. Дуже просто. Але от такий код, коли у коді до вашого компонента одночасно ви прив'язали v-model і реагують на подію input. І у Vue 2 спочатку оновлюється v-model, а потім виконується подія, а у Vue 3 навпаки. Здається, хто в адекватному стані буде так робити? Повірте, коли код розвивається ітеративно, це все буде будь-яка неявна поведінка, будь-яка дичина у коді, що компілюється, буде там.

І на підтвердження отакий маленький шматочок MergeQuest'у з того, що я робив, хтось, не знаю, як це виникло, а у Vue-шних шаблонах, виводив результат виклику функції локалізації, після нього стояла кома. Оскільки Vue 2 був, як-то кажуть, використовував StringlyTyped, тобто компілятор шаблонів, побудований суто на комбінації цього-всього у рядки та eval його, це працювало у Vue 2 і радісно розвалюється у Vue 3. Тому готуйтесь до того, що будь-яка неявна поведінка тепер стає явною і важливою для вас. Їх треба документувати, але ми до того ще дійдемо. Сюди треба зазначити, що якщо у вас немає тестів, то теж не треба починати, тому що я не знаю, як контролювати адекватність поведінки системи без тестів. Ну або ваша команда QA в 10-ро більше, ніж розробників, і вони озолотяться. Тому що коли я роблю маленькі, незначні зміни у системі, я ніколи не знаю, де я зламаю це, тому що знову ж таки, неявні поведінки. Зміни, які, скоріш за все, ні на що не впливають, скоріш за все, щось ламають.

Якщо ви не готові писати код АБИЯК, я знову це підкреслюю, то теж не починайте. У мене написана ціла окрема милиця. Дехто не знає слово милиця, це костиль. Тому що в процесі роботи виявилося, що друга версія тестових утілів для Vue 2 містить у собі помилку, яку чотири роки, і яка призводить до того, що в одній ситуації заглушка компоненту, коли ви тестуєте, рендериться одним чином, а коли іншим, в іншій ситуації, хоча це не має жодної логіки під собою, іншим чином. І тепер ви хочете того чи ні, ви потрібні якось мімікрувати цю поведінку, хоча у новій версії поведінка правильна. Але якщо ви одразу виправите це на правильну поведінку, то ви порушите головну ідею. Вам потрібно, щоб максимально довго одна й та сама кодова база працювала у новій версії і у старій. Причому головною білью будуть, головним полем, будуть залежності.

Що з залежностями? Я спеціально забив слово dependencies у Unsplash, здається, щоб взяти цю картинку, але насправді всі ми розуміємо, що коли ми оновлюємо щось на мажорну версію, то ось ця картинка щодо залежності підходить куди більше. Тому що питання оновлення залежності для будь-якого проекту, що живе доволі довго, це капець. Ви думаєте, чому я став мейнтейнером Bootstrap Vue? Виявилося, що наша дизайн-система дуже-дуже-дуже і дуже залежить від Bootstrap Vue. А Bootstrap Vue, та там його закинули, ніхто і не думав починати підтримку Bootstrap Vue. Ви зараз, якщо слідкуєте за цим, скажете, Ілля, ти трішечки неправду кажеш. Він є Bootstrap Vue Next, хлопці з нуля переписали, та тепер вони підтримують Vue 3 та Bootstrap Vue 5. Ага, скажу я вам. Тож ви пропонуєте продукту розміром з GitLab, оновити одночасно Vue 2 до Vue 3, Bootstrap версії 4 до версії 5, так, ми досі сидимо на Bootstrap версії 4, тому що згідно влання складу. Bootstrap Vue замінити на Bootstrap Vue Next, де хлопці, які його пишуть, я до того не дотичний, кажуть з філософії, ну ви знаєте, ми на 80% сумісні з Bootstrap Vue. Ми тільки там трішечки змінили, там, де це не має сенсу.

Я думаю, всі, хто трошечки зрілий, а хто зрілий, я маю у вазі з точки зору досвіду, хто там 4-5 років в індустрії, а ті, хто ні, ще повірте мені на слово, коли вам кажуть про 80% сумісності, це типу вони думають, що на 80% сумісно? Ні. А насправді у тих 80%, що вони думають, що сумісні, ще певна кількість неявних несумісностей. Коли в Vue 3 випустили пакет Vue Compat, який каже, що сумісність Vue 2 з Vue 3, ну десь там процентів 90, то, ну що я вам кажу, от вже рік пройшов, ми ще досі не можемо мігрувати на Vue Compat. Тому будьте дуже скептичні щодо залежностей і будьте готові до того, що певні залежності, можливо, доведеться підтримувати самим, або думати, як їх замінити. Саме тому, можливо, великі проекти іноді дуже і дуже панікують щодо того, щоб тягнути великі залежності.

Тут ще окремим нюансом, як кажуть, спойлер до того, що не увійшло, є так звані втрачені знання у системі. Коли ви бачите компонент, але людина, ваш компонент, ваша кодова база, але людина, яка написала його, звільнилася два роки тому та поїхала до Австралії розводити кролів. Невигадана історія. І тому запитати нікому і всі там ці два роки оминали цей компонент з філософії «Боже збав». Воно хоч якось працює, тільки не чіпає. Але тепер з міграцією воно не працює ж ніяк. Welcome to the pain. Так от, давайте розберемося із всіма цими 'мавплі штучками' та фічами JavaScript, які ви використовуєте. Влазити до чужого коду та змінювати його на льоту – це справжня магія та одночасно потенційна зона ризику. Я розумію, що це може дати вам необхідний контроль та можливості, але слід пам'ятати про можливі проблеми, такі як порушення стабільності, неперевірені зміни та складність утримання.

Щодо тестів і змін, внесених у Vue Test Tutorials, я припускаю, що ви відмінно розумієте, які можливі наслідки виправлень та змін. Важливо залишати коментарі та документацію, щоб ваші зміни були зрозумілі для інших розробників. Тестування на двох версіях Vue (2 та 3) – це велика задача, і я раджу тримати це все під контролем. Щодо Mav5 та вставлення 'паличок у колеса' – це може бути неоднозначним. З одного боку, це надає вам широкі можливості. З іншого боку, це може ускладнити код та збільшити його об'єм. Якщо ви знаєте, що це необхідно для досягнення ваших цілей, то, можливо, це варто.

Щодо втрачених знань у системі та флешбеків – це загострює важливість гарної документації та передачі знань між командами. Зокрема, коли людина, що працювала над якоюсь частиною коду, залишає команду. Щодо групової динаміки та мотивації – ви точно праві, тут складно знаходити золотий стандарт. Деталізація задач і розподіл відповідальностей можуть допомогти утримати високий рівень мотивації, але це не завжди працює. Важливо підтримувати комунікацію, створювати затишне робоче середовище та взаємодіювати з командою.І на завершення, щодо флешбеків – іноді, пам'ять народжує найцікавіші ідеї та рішення. Бажаю вам успіху у всіх ваших великих та маленьких викликах у світі JavaScript та розробки програмного забезпечення!

Це важливо, щоб кожен раз люди ставили галочку, галочку, галочку. Це значуще для бізнес-власників, оскільки як виміряти міграцію? З точки зору інженера, бінарно, воно або працює, або ні. З точки зору розуміння, чи корисне воно на 90%? Ні. Проте, існує неочевидний нюанс для багатьох інженерів, який і мені не завжди був зрозумілим. Якщо ви знаєте, що минулого разу задача була виконана на 90%, а тепер на 91%, незалежно від того, наскільки абсурдний механізм вимірювання, наприклад, кількість тестів, то важливою є позитивна динаміка. Навіть якщо точність ваших вимірювань та інструмент, яким ви вимірюєте, за точністю нагадує копіювання файлів у Microsoft Windows, наприклад, залишилося 5 секунд, залишилася година, залишилося 3 секунди, залишилося 24 години, все одно це показує, чи є динаміка, чи ні. І якщо ви не будете хоч щось вимірювати, якщо ви не зможете намалювати красиві графіки, то люди будуть розходитися, тому що працювати за ідеєю, коли ви не бачите результат, це надто важко.

Документація. Ми вже трішки навіть перевищили час, але дві прості речі. По-перше, ви маєте документувати всі нюанси, які ви винайшли. Як хочете. Хочете, залучайте chat.jpg до цього. Хочете ще щось, але інакше ви будете при реченні знову і знову пояснювати речі, які є у вас в голові. І десь на п'ятий раз, повірте мені, ви будете пояснювати їх дуже погано. Проте Ілля написав такий гайд у GitLab, злитий це, скопійований мердж-реквест, детально пояснюючи, як ми інтегруємо бібліотеки, які потрібно також оновлювати разом із версією Vue, як ми забезпечуємо їх сумісність. Запам'ятайте три важливі речі. По-перше, документація повинна існувати, але ніхто не читає документацію. Це прямо важливо. Тому потрібно придумувати хитрі способи, як змусити людей читати документацію. Уявіть собі, що ви починаєте нове завдання. Ви ж не йдете до документації, де ви її там зберігаєте, Confluence у GitLab тощо, і дивитеся, чи не оновилася документація, як правильно виконувати таке завдання? Ні. Таким чином, документація повинна існувати, але її все одно ніхто не читає. І якщо хочуть, то читають її дупою. Ну ви ж знаєте це. О, господи, все зрозуміло, погнали. Тому, не дивлячись на показову абсурдність та конфлікти цих трьох речей, повірте мені, якщо людина хоч раз прочитає її дупою, вона прийде до вас і скаже, що не працює. Ось тут в документації, я читав. Ти просто йому Ctrl-C, Ctrl-V. А, от я не зрозумів. Дуже важливо, тому що ви будете намагатися пояснювати одне і те саме, повірте мені, я на ці граблі наступив ще рік тому. І тоталітаризм. Навіть якщо у вас немає важливих впливів, як у мене, ви повинні вести себе так, ніби вони є.

Тобто, я стикнувся з такою проблемою. Люди прийшли, у нас є там докупи завдань. Певна частина завдань є складні, тобто там треба ризікувати. І є купа завдань, які легкі. Просто вони займають час. І здається, що люди, розуміючи, що і прості завдання принесуть користь. Але ні. Брати ці завдання поганенько, тому що, чому? Ось ці завдання, які складні, несуть в собі великий фактор невизначеності. Дивіться, ось тут у нас якась бісова помилка. Біс його знає, чому вона виникає. І оскільки ви не знаєте, чому вона виникає, ви не знаєте, скільки зусиль потрібно буде, щоб їх виправити. Тож це впливає на дедлайн і т.д. Тому людей потрібно мотивувати, щоб вони брали ці завдання. Я взяв цю ідею, ой, я не пам'ятаю, в якійсь книзі з філософії впливу і т.д. Там сказано було, що якщо, наприклад, вам потрібно просити допомоги, то потрібно не просто казати "допоможіть мені", а сказати "ось ти, людина в синій футболці, будь ласка, допоможи мені". І людині в синій футболці набагато важче відмовити. От так само. Найлегший спосіб, що не працює. Я тут набрав сто п'ятсот ось цих тасків. Беріть, коли будете готові. Спосіб трошки кращий. От ці таски є найпріоритетнішими, хто їх візьме. Найманіпулятивний, але найефективніший спосіб. От ця таска, мені здається, гарно підійде Андрію. Андрій, що ти думаєш щодо того, щоб її взяти? Чи може ти порадиш ще когось? Знаєте, як гаряча картопля передати. Маніпулятивно, можливо, так. Але якщо всі люди, що прийшли до робочої групи, або висловили свою зацікавленість у цьому, якщо всі вони долучаються до цієї ідеї, то вони вже заявили, що вони цього хочуть. Тому наша справа — допомогти їм досягти цього, можливо, і трошки сумнівними методами. Ну що, ось це все. Як бачите, як відчуваєте, дуже галопом по Європах, тому що за 30 хвилин я в 38 вписався. Дуже складно вписати все це.

Увійти
Або поштою
Увійти
Або поштою
Реєстрація через e-mail
Реєстрація через e-mail
Забули пароль?