Назад в будущее Хабра. Трекер 3.0 / Хабр | Веб-студия Nat.od.ua
Назад в будущее Хабра. Трекер 3.0 / Хабр
Приветствуем вас, наши дорогие пользователи! Без долгих предварительных ласк: новый трекер, налетайте 🙂
Назад в будущее
Отгадайте загадку:
Маленький, с зелёной точечкой
Появился 11 лет назад
Ну или через 6 лет после создания Хабра
Посчитали? Ага, и эти 8 лет он проработал практически без изменений
Если бы не заголовок публикации, то вы бы точно не сразу догадались, что речь идёт про трекер. Всё так — первая версия трекера появилась на Хабре в далёком 2012 году. И с тех пор он почти не менялся: ну разве что цвет счётчика событий был зелёным, а стал красным, ну и так, ещё всякое по мелочи.
Казалось бы, зачем трогать то, что и так работает? Аргумент, но если всегда ему следовать, то будет довольно сложно эволюционировать и меняться — в итоге легко оказаться на ровной лужайке и порасти мхом. Поэтому в 2021 мы представили на суд общественности новый трекер (назовём его 2.0), который стал доступен вместе с запуском новой версии Хабра. И если к новой версии Хабра многие привыкли довольно быстро (сейчас ей пользуется 99.5–99.7% посетителей), то новый трекер зашёл далеко не всем.
И что не так?
Трекер 2.0 был основан на «соцсеточной модели», когда пользователь отслеживает конкретные дискуссии (например, пары‑тройки пользователей между собой в одной ветке комментариев) в рамках объектов контента (постов в соцсетях или мессенджерах). А вот отслеживать целиком дискуссию под публикациями (что более характерно для форумов и в том числе Хабра) с такой моделью оказалось менее удобно. Ну или как говорят некоторые, совсем неудобно.
Как решили
Видимо, это тот случай, когда нужно было последовать правилу «работает — не трогай», ограничив изменения в трекере адаптацией механики под новую версию Хабра. Так мы и решили поступить с трекером 3.0, который, по большому счёту, является обновленной (и немного дополненной) версией 1.0.
Это ли не УРА?! 🙂
Интерфейс трекера 3.0
Колокольчик никуда не делся: как и прежде, он индикатор наличия новых событий внутри трекера. При наличии таковых трекер выводит число в формате от +1 до 99+, которое является суммой событий во всех разделах трекера.
Нажатие на колокольчик в трекере версии 2.0 открывало меню, в котором события группировались определённым образом (и да, иногда это было не очень удобно — например, если событий накопилось очень много):
Меню трекера 2.0
Сейчас нажатие на колокольчик будет открывать страницу трекера. К внешнему виду раздела перепривыкать не придётся — это всё те же горизонтальные табы, на которых будет выводиться счётчик новых событий (при наличии таковых). Давайте освежим в памяти содержимое табов — тем более что появился один новый.
Публикации
В этом разделе выводятся последние 20 публикаций (если больше, то появится пагинатор), с которыми вы взаимодействовали. Все уведомления можно отметить как прочитанные с помощью чекбоксов и появляющейся в шапке кнопки:
Можно просмотреть все публикации или только свои.
Нажатие на шестерёнку откроет настройки трекера.
Новый трекер позволяет отслеживать не только статьи и новости (в трекере выводятся их заголовки), но и новую сущность, посты, у которых выводятся первые 60 символов содержимого (так как у них нет заголовка).
Сначала в разделе идут все непрочитанные события с сортировкой по последнему комментарию от ранних к поздним, а потом — прочитанные с сортировкой по последнему комментарию от ранних к поздним. Публикации, которые были скрыты в черновики, пропадают из трекера до того момента, пока не будут опубликованы снова.
Новый раздел — Уведомления
Раздел для различных системных уведомлений, среди которых:
Модератор опубликовал вашу статью из Песочницы.
Модератор вернул статью в Песочнице на доработку.
Модератор отклонил публикацию.
Пользователю становится доступна ППА.
Администратор компании одобрил (или отклонил) заявку на вступление в ряды сотрудников компании.
Если публикация была отправлена модераторам сезона (о прохождении модерации сообщается в личных сообщениях).
В будущем планируем добавить сюда ещё больше уведомлений, полный перечень которых опубликуем в справочном разделе.
В разделе уведомлений та же сортировка (от новых к старым), те же 20 элементов на страницу.
Упоминания
Этот раздел существовал ранее и по сути не изменился — в нём собираются уведомления в том случае, если вас кто-то упомянул в статье или в комментарии. По клику вы попадаете или в статью, или сразу на конкретный комментарий.
Подписки
Сюда попадают уведомления, связанные с вашими подписками или подписчиками. Например, здесь окажется событие, если автор, на которого вы подписаны, выпустил новую публикацию или добавил что-то в избранное. В этом разделе также добавились посты.
Приложения
Хоть у нас пока и было только одно приложение (Анонимный Дед Мороз), мы всё же оставили этот раздел. На вырост.
Мы настроили обратную совместимость между версиями: уведомления из трекера в старой версии должны перенестись в новую.
Надеемся, это изменение добавит вам удобства при использовании Хабра и наконец‑то поможет решить вопрос со старой версией сайта — по нашим опросам, трекер был последним, что заставляло пользователей переключаться на неё.
Пользуйтесь на здоровье! Будем рады любой обратной связи — пишите в комментариях или в личку.
Нашли опечатку в тексте? Выделите и нажмите CTRL/⌘+Enter.
как я выбросил 10-месячный проект после 2 месяцев в должности / Хабр | Веб-студия Nat.od.ua
как я выбросил 10-месячный проект после 2 месяцев в должности / Хабр
Когда я принял управление командой, её участники находились на 8-м месяце реализации 3-месячного проекта по перезапуску коммерческого сайта компании. Спустя два месяца ведения этой команды, я решил отказаться от всего достигнутого и начать сначала. Это история о том, почему я это сделал, как, и что в итоге получилось.
Перезапуск нашего сайта преследовал одну цель: обеспечить быструю отрисовку на стороне сервера.
В удачное время размер нашего JS-бандла составлял 168 МБ. На топовом MacBook Pro среде разработки для начала быстрого реагирования требовалось 3 минуты. Приходя на работу, инженеры уже по привычке вводили npm run dev и шли пить кофе, пока кулеры их компьютеров изо всех сил пыхтели, обслуживая нагрузку, возложенную на них нашим раздутым проектом.
Где же всё пошло не так?
▍ Предыстория
Первым сайтом компании было одностраничное приложение на AngularJS. AngularJS не поддерживал отрисовку на стороне сервера (SSR, server-side rendering), поэтому первая загрузка страницы происходила медленно, и только потом уже всё начинало работать быстро.
А поскольку в интернете играют роль даже миллисекунды, особенно в случае сайтов электронной коммерции, нам нужно было уменьшить время первой отрисовки.
Команда подумывала об использовании Angular 2, и хотя этот фреймворк значительно отличался от AngularJS, он казался логической основой для нового сайта. Мы даже следили за экспериментальной веткой разработки этим проектом функциональности SSR. Естественно, к моменту готовности сайта она тоже должна была быть готова.
Команда создавала сайт, регулярно внося последние изменения из этой экспериментальной ветки в код и разбираясь с возникающими нестыковками.
Я присоединился к ней за две недели до завершения этой функциональности. На тот момент дедлайн нас уже нагонял, но большинство страниц были готовы, и все критические функции работали. Моей задачей было вывести проект в продакшен.
Команда Angular приблизилась к завершению функциональности SSR, и мы привносили последние штрихи в критические маршруты пользователей. Всё шло если не отлично, то по крайней мере… шло. Пока не встало.
У нас был рабочий сайт. Единственное, чего не хватало – это полноценной поддержки SSR. Отрисовка на сервере работала, но не при встряхивании дерева, а AOT-компилятор (критический этап в сборочном конвейере Angular) выдавал бандлы невероятного размера.
Три недели ушло на то, чтобы поставить «приятные бонусы» из списка отложенных задач, включая реально впечатляющее кэширование образов с помощью Nginx (это отдельная история). Мы каждый день проверяли репозиторий Angular в надежде, что там появится критическое исправление.
В итоге приятных бонусов для добавления не осталось, и мы две недели потратили на копание в SSR-ветке команды Angular, но раскидистая, незнакомая база кода и непоправимые ошибки всё сильно затрудняли. Поскольку проект был экспериментальным, толковой документации к нему не было.
Мы тратили время и ни к чему не приходили, хотя чувствовалось, что сдаваться сейчас, когда финиш так близок, будет глупо.
Спустя неделю без какого-либо значительного прогресса и ощутимых действий в апстриме, мои силы были на исходе. На меня всё больше давило руководство, а наши конкуренты определённо не дремали, так что бизнесу нужен был готовый проект.
У нас не было чёткого понимания, как мы сможем поставить имевшийся у нас на тот момент продукт, и встал вопрос: «Можем ли мы позволить себе начать его с нуля?»
Мы оказались в ловушке невозвратных затрат, вкладывая всё больше денег, времени и ресурсов в провальный проект из страха потерять уже вложенные средства.
Если ситуацию не исправить, она неизбежно приведёт ко всё большей потере.
Я не спал ночами, обдумывая решения, которые привели к этому раскладу. По собственному опыту я знал, что React & Redux имели полноценную поддержку SSR.
Я лично видел, как быстро мотивированная команда продвигалась, используя этот стек, но выбрасывание коту под хвост целого года работы очень сильно покачнуло бы дух команды и явно не понравилось бы руководству, которое ожидало от вложенных усилий результатов.
Кроме того, эта мысль противоречила всем инстинктам, которые у меня были относительно масштабных переделок.
▍ Начинаем заново
Самая большая сложность этой затеи заключалась не в технических аспектах, а в личностных. Первым делом нужно было получить одобрение от учредителей. Мне удалось добиться этого, пообещав две вещи:
- Что я буду продолжать следить за проектом Angular SSR, и в случае его выпуска мы тут же запустим сайт на Angular.
- Сайт на React будет доведён до работоспособного состояния за 6 недель, а через 10 мы его уже сможем запустить. Если мне это не удастся, то я пойду на понижение и найду себе замену.
Первое обещание было здравомысленным, а второе отражало мою уверенность, исходящую из личного опыта. Я уже создавал на React сайт с отрисовкой на сервере, и знал, что всё сработает. Если же смотреть с позиции учредителей, то у них имелся чёткий стоп-лосс на случай, если что-то пойдёт не так.
Но самым сложным всё же было получить одобрение от команды. Они провели много месяцев, трудясь над проектом ещё до моего прихода, и теперь я предлагал выбросить всю их кропотливую работу, притом ещё и устанавливая безумный дедлайн на новую. Им нужно было поверить в реалистичность этой затеи и, самое главное, в правильность этого выбора.
Мне требовалось убедить команду использовать стек React, и единственным способом для этого была платформа DevEx. Они должны были увидеть, насколько продуктивно можно работать, если не опираться на их текущие отсталые инструменты.
Я набросал схему проекта React с SSR и выбрал для реализации один поток, установив амбициозную цель создать нашу домашнюю страницу – полностью отзывчивую и с поддержкой SSR – в течение дня моб программирования.
В итоге все были поражены возможностями горячей замены модулей и повторного рендеринга в реальном времени. После проекта, в котором им приходилось ждать отображения изменений вплоть до минуты (в удачный день), это выглядело как магия. Среди команды ещё витал некий скептицизм относительно того, сохранится ли такое быстродействие после создания остальной части сайта, но этой демонстрации было достаточно, чтобы участники команды решили вложиться в реализацию идеи.
Все ценят быстрый цикл обратной связи. Даже короткое ожидание результата изменений может загубить весь рабочий поток.
Вложение усилий в ускорение вашего тестового набора или поиск более производительной системы сборки сокращает этот цикл, а также напрямую повышает вовлечённость и продуктивность команды.
Во второй день мы поделили сайт на 20-30 ключевых пользовательских историй – многие были взяты из первого проекта – приоритизировали их и начали поставлять.
Процесс создания нового сайта происходил онлайн, будучи открытым для всей компании, и к концу первой недели остатки скептицизма испарились, когда все увидели, как далеко продвинулась команда за столь короткий срок.
▍ Поставка
Новый сайт мы поставили, спустя 7 недель сосредоточенных усилий, как раз к одному из самых активных покупательских периодов года. Он был невероятно быстр, в нём использовалось меньше ресурсов, чем в оригинальном сайте на AngularJS, и написанный нами код, спустя несколько лет, до сих находится в продакшене, хотя с тех пор сайт сильно изменился.
Angular Universal с первоклассной поддержкой SSR в итоге был добавлен в Angular v5, вышедший в апреле 2018 года, где-то через шесть месяцев после завершения нашего сайта.
В этом проекте было нарушено два фундаментальных правила управления программными проектами:
1. Не создавайте рабочие приложения с помощью экспериментальных технологий
Версия сайта на Angular как раз создавалась на экспериментальной, неподтверждённой технологии и до сих пор находится в активной разработке.
Это был очень значительный внешний риск, который оставался полностью вне нашего контроля, поскольку мы никак не могли знать, когда никак не отвечавшая перед нами команда Angular поставит свой продукт.
Если бы мы решили продолжать ждать, то простаивали бы вхолостую, не обеспечивая никакой бизнес-ценности в течение 9 месяцев, удвоив продолжительность реализации проекта.
2. Не идите на масштабное переписывание проектов
Решение переписать сайт на Angular 2 без требования следовать поэтапным релизам завело команду в ловушку, вынудив создавать весь сайт до столкновения с основным риском.
Если бы в условиях реализации проекта было заложено требование выпускать поэтапные релизы, то понимание о том, как нужно создавать сайт, возникло бы гораздо раньше.
Здесь внимательный читатель может сказать: «Подождите-ка. Разве проект на React не стал масштабным переписыванием?»
Отвечу так: «Изучайте правила, чтобы знать, когда их можно нарушать».
Я пошёл на сознательное нарушение этого правила, чтобы сохранить мораль команды.
В этом случае я сделал ставку на то, что передовой проект на React сможет сохранить в её участниках мотивацию. Втискивание React в легаси-проект на AngularJS не привело бы к достижению цели, а возвращение к старому коду после нескольких месяцев создания нового нанесло бы сильный удар по духу команды.
Это было очень ситуативное решение. Если бы мы не переходили с провального проекта на Angular 2, то я бы с самого первого дня пошёл на использование одной из прослоек совместимости между React и AngularJS, чтобы перенести сайт постепенно.
Как менеджеру вам нужно играть с той рукой, которая вам выпала, а не с той, какую бы вы хотели получить. Каждая ситуация уникальна, и каждое принимаемое вами решение должно учитывать не только продукт, но и людей, его создающих.
Порой это означает, что вам нужно нарушить устоявшиеся правила. Но помните – у всяких правил есть свои причины, так что не стоит возводить это в привычку.
Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх 🕹️
новая архитектура для ресурса с большой нагрузкой / Хабр | Веб-студия Nat.od.ua
новая архитектура для ресурса с большой нагрузкой / Хабр
К нам обратился заказчик, который хотел улучшить архитектуру высоконагруженного ресурса на основе Moodle. Сайт имел привычку падать при высокой нагрузке. Ничего необычного, подумали мы. Берем.
Нетривиальность задачи оказалось в том, что кейсов инсталляции сервисов Moodle на ресурсы с нагрузкой >10 тыс. человек нет ни у Яши, ни у других сервисов, к которым мы привыкли. Из коробки ничего не работало, документации тоже не нашлось. Предыдущий исполнитель с задачей не справился и оставил сервис в печальном состоянии.
Срок выполнения задачи – 2 месяца, что добавило остроты проекту перед Новым годом…
Исходные данные
Легкое ощущение запутанности
Ресурс (сайт) для проведения онлайн-тестирования с использованием системы Moodle со следующими характеристиками:
нагрузка на ресурс периодическая: в пиковые нагрузки – до 12 тыс. онлайн пользователей, в период простоя ~200 человек.
проблема: в пиковые моменты сайт замедлял работу и падал. При этом недостатка в вычислительных ресурсах не было, а вот вопросов к архитектуре – множество.
архитектура: 20 постоянно работающих серверов с разными базами данных в разных дата-центрах, где каждый сервер находился в регионе присутствия компании. Это огромная, неповоротливая архитектура, где для любого обновления нужно делать привязку к каждому отдельному серверу.
подготовка сводной аналитики: данные раз в несколько дней выгружали из каждой базы данных и скриптами сводили вместе все отчеты.
базы данных представляли собой модульную объектно-ориентированную динамическую среду обучения – Moodle.
Налицо неэффективная система обработки данных.
Заказчик столкнулся с проблемой перегрузки серверов и решил ее, просто увеличив количество серверов в 5 раз (хехе). Решение ожидаемо привело к расходам и сложностям со сведением данных с разных серверов в одну базу.
Далее кривая вывела заказчика к другой компании, которая создала множество инстансов баз данных и каждого отдельного Moodle, но проблему так и не смогли решить.
Тут, собственно, задача и попала к нам.
Задачи разработки
Основной запрос – оптимизация архитектуры ресурса. Мы предложили спроектировать архитектуру с динамически изменяемым количеством серверов в зависимости от нагрузки.
Ресурс должен быть представлен в виде единой базы данных, без деления по регионами, иметь единую систему отчетов и выдерживать пиковую нагрузку до 12 тыс. пользователей.
Итак: знаем что делать, но не знаем как. (пока)
Обратный отсчет
Мастера планирования в деле
Для решения задачи наштормили несколько вариантов. Времени делать сложносочиненные решения не было…
Вариант 1: использовать Yandex Cloud (YDB) для создания отдельного программного модуля – коннектора, поддерживающего нативный интерфейс MySQL.
Для Moodle-системы это выглядело как подключение к базе данных MySQL, а коннектор транслировал запрос в YDB.
Сложности подхода: часть функций не поддерживалась, т.е. невозможно было реализовать полную совместимость с MySQL очевидными и быстрыми методами, из коробки. Нагрузочное тестирование показало слабые результаты. Показатели были существенно ниже обычных для MySQL.
От идеи быстро отказались и погнали дальше.
До сдачи 52 дня.
Вариант 2: использование оркестратора базы данных Vitess. Vitess был создан в 2010 году для решения проблемы масштабируемости MySQL, с которыми тогда столкнулась команда YouTube. Пиковая нагрузка превышала пропускную способность базы данных, а использование прокси-сервера между приложением и базой данных для маршрутизации и управления взаимодействием с базой данных позволило решить эту проблему.
Вдохновившись этой историей, мы попробовали взять в работу Vitess.
Ограничивающим фактором стало отсутствие адекватной документации. В результате тестирования получили схожие с первым вариантом результаты. Решение просто не стало работать в режиме кластера!
Мы обратились бизнес-поддержку YDB и выяснили, что и они тоже не работали с такими кейсами. Что ж, отрицательный результат – тоже результат.
До сдачи 41 день.
Настало время последнего варианта. Скажем прямо – на первый взгляд он выглядел так себе… Но, параллельно с работая над предыдущими вариантами, мы проводили ресерч и тесты и постепенно пришли к мысли, что при качественной проработке это может стать хорошим решением.
Лучшее – враг хорошего
Когда ты уже свой в бардаке
Вариант 3: остаться на используемой базе MySQL в режиме кластера из одной ноды (экземпляра). Тут следует заметить, что предыдущий исполнитель, к которому обращался заказчик, решить такую задачу не смог. Он ушел с используемой заказчиком базы и создал множество инстансов баз данных и сервисов Moodle. Его подход, конечно, не нашел продолжения в новой архитектуре. Но идея с базой данной прижилась!
Нам удалось применить однонодовую конфигурацию кластера базы данных MySQL. Мы проверили ее оптимизацию и доработали конфигурации для работы с максимальной нагрузкой на ресурс.
Такой результат был получен за счет “тонкой” конфигурации кластера MySQL в соответствии с поставленной задачей, что позволило достигнуть требуемой пиковой нагрузки на одном экземпляре базы данных
Вова Завьялов, архитектор проекта
Использовали Yandex Managed Service for MySQL® на базе инфраструктуры Yandex.Cloud в качестве платформы для управления кластером базы данных. Конфигурация сервера была следующая:
CPU 96 ядер;
RAM 192 ГБ;
SSD 512 ГБ.
Создание централизованного хранилища
Когда на карту поставлены все котики
До сдачи 30 дней…
Исходная архитектура заказчика была примерно эры динозавров, поэтому мы провели миграцию всех структур и данных на современную контейнерную архитектуру. Но и тут появились проблемы, с которыми мы просели еще на неделю как минимум..
Проблема 1
После миграции перед нами встал серьезный вопрос о хранении данных, т.е. документов, изображений, внутренних файлов. Головоломка была в том, что с увеличением количества серверов мы не должны потерять скорость передачи этих данных.
Оптимизация и адаптация подразумевала необходимость централизовать хранилище, сведя все кластеры серверов в единую систему.
Проблема 2
Проблемой заказчика была трудоемкость работы с базами. Каждый сервер имел свой отдельный moodle, базу данных и файловые системы.
Чтобы свести все данные с каждого сервера использовались заклинания скрипты. Как понимаете, это приводило к хаосу. Идентификаторы связанных серверов пересекались и происходила перезапись данных.
Из хаоса в систему
Чтобы исключить подобные ситуации мы создали сетевое централизованное хранилище.
Хранилище имеет максимальную скорость чтения и записи до 8 Гбит/сек.Доступ к дисковому хранилищу организован через протоколы NFS (network file storage). Настроили RAID-массив и выделили хранилище в отдельный сервер, работающий на CentOS. После проведения тестирования мы перевели платформу на новый уровень порядка и организации и получили достаточно высокопроизводительное хранилище, которое гибко интегрировалось со всеми серверами.
Ищем равновесие
Системе был необходим дирижер динамической архитектуры. В его роли выступил балансировщик нагрузки (!!!), который при росте количества пользователей автоматически создает новые сервера, а при снижении – удаляет сервер через несколько минут после того, как нагрузка спала.
Мы использовали в проекте L7-балансировщик, что позволило в нагрузочном тесте сгладить итоговые результаты за счет поддержки функции Session Affinity, когда балансировщик запоминает пользователя и закрепляет его за определенным сервером бэкенда, что в свою очередь снижает нагрузку на файловый кэш.
По срокам мы вроде еще успевали, но нельзя недооценивать последние этапы.
Итоги
Еще около 12 дней ушло на развертывание сервисов, нагрузочное тестирование и ввод в эксплуатацию. Еще одна непредвиденная проблема и мы бы жестко пролетели со сроками. К счастью, ее не случилось.
По итогу мы собрали пазл из разрозненных серверов в централизованный ресурс.
Для этого:
провели централизацию базы данных;
выполнили оптимизацию конфигурации кластера базы данных MySQL для работы с пиковой нагрузкой до 12 тысяч пользователей;
вывели кэш сессий в Redis;
использовали L7-балансировщик для распределения нагрузки между серверами;
для хранения пользовательских временных файлов создали отдельный NFS-сервер, который может работать на скорости до 8 Гбит/сек.
Заказчик получил централизованную систему, единый Moodle, который может работать при максимальной нагрузке (см пикчу)
Структура управляющей программы
Решена проблема сведения результатов онлайн тестирования из разных баз: теперь данные отображаются в единой базе и администратору доступны сразу все отчеты.
По цифрам
Резко упала стоимость ресурсов в момент простоя платформы. Это главное.
Учитывая сезонность работы сайта, когда большую часть года ресурс работает с минимальной нагрузкой, и только несколько месяцев в году происходит резкий рост пользователей, методы балансировки нагрузки позволяют мощно сократить финансы.
Когда нагрузка отсутствует, ненужные сервера не запущены и заказчик за них не платит.
Сэкономленные деньги – это заработанные деньги
Расчет стоимости ресурсов идет в зависимости от нагрузки на сайт за 1 секунду.
Итого сервис располагает серверами:
баз данных;
файлового хранилища;
сервисные сервера;
сервера бэкенда;
сервера-балансировщики нагрузки, которые создаются под обработку запросов.
Серверов-балансировщиков в пиковые нагрузки может быть до 24 шт. В момент простоя работают только сервер базы данных, сервер хранилища, сервер кэша и один сервер для обработки пользовательских запросов.
Проведя изменения на материнской виртуальной машине необходимых нам данных по веб-интерфейсу, по формам, спискам мы устранили все танцы с бубнами и сделали ее единой точкой входа для всего кластера.
Нагрузочное тестирование показало предельное RPS 200 (Requests Per Second – количество запросов за одну секунду). Цифра превзошла наши ожидания: для нашего проекта это эквивалентно работе 16 тысяч пользователей.
Валера Ковальский, разработчик
Когда разработал в срок в канун НГ
В итоге, Заказчик получил сайт 30 декабря. А мы ушли восстанавливаться 🙂
ADI в пользовательском интерфейсе | Веб-студия Nat.od.ua
ADI в пользовательском интерфейсе
ADI (Artificial Design Intelligence) – это технология, использующая искусственный интеллект (ИИ) для автоматизации дизайна и графики. Её можно применять не только в дизайне, но и в веб-дизайне, архитектуре, производстве и других областях. Основная идея заключается в ускорении и упрощении создания дизайн-проектов, делая их более эффективными и доступными.
Стоит отметить, что ADI – относительно новая технология с постоянно расширяющимися возможностями. Она позволяет исследовать и использовать ИИ для улучшения дизайна и сделать его более инновационным и эффективным. Искусственный интеллект также влияет на дизайн пользовательских интерфейсов (UI).
В настоящее время существует ряд различных инструментов на базе ИИ, которые могут помочь дизайнерам создавать более качественные пользовательские интерфейсы и включают в себя такие аспекта ADI как:
Читать далее
Почему тип поля enum на уровне базы — зло / Хабр | Веб-студия Nat.od.ua
Почему тип поля enum на уровне базы — зло / Хабр
Часто разработчики интересуются почему не рекомендуется использовать тип поля enum в базе данных, и в этой статье мы рассмотрим все плюсы и минусы данного типа.
Тип колонки enum используется для хранения данных, которые могут принимать определённые значения из заранее определённого набора. Он обеспечивает ограничение значений, которые может принимать колонка, и позволяет более строго контролировать данные. Это может быть полезно для хранения статусов, категорий, типов или любых других значений, которые могут быть заданы только из ограниченного набора вариантов.
Но это в теории. А что на практике? Давайте рассмотрим.
Допустим у нас есть таблица со списком игр, содержащая колонку “жанр” (“genre”) со следующими значениями:
CREATE TABLE `games`(
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NOT NULL,
`genre` ENUM(‘action’,’adventure’,’shooter’,’rasing’) NOT NULL,
KEY(`id`)
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Через какое-то время была замечена грамматическая ошибка в слове “racing” и принято решение её исправить.
Нюанс изменения enum поля в том, что при его редактировании сбрасываются значения колонки в null для всех строк таблицы, а то и вовсе получим ошибку `Data truncated for column ‘genre’ at row 3`. То есть, чтобы корректно изменить enum поле, нужно куда-то сохранить данные. План действий будет таков:
Создать новую enum колонку с правильным набором данных;
Скопировать значение из старой колонки в новую и сразу применить исправление значения;
Удалить старую enum колонку;
Переименовать новую enum колонку.
При использовании фреймворка Laravel это будет выглядеть следующим образом:
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesDB;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
public function up(): void
{
// Создаём новую колонку
Schema::table(‘games’, function (Blueprint $table) {
$table->enum(‘tmp_genre’, );
});
// Копируем значения из enum колонки в новую с корректировкой значения
DB::statement(‘UPDATE games SET tmp_genre = (IF genre = ‘rasing’ THEN ‘racing’ ELSE genre END IF)’);
// Удаляем старую колонку
Schema::table(‘games’, function (Blueprint $table) {
$table->dropColumn(‘genre’);
});
// Переименовываем колонку
Schema::table(‘games’, function (Blueprint $table) {
$table->renameColumn(‘tmp_genre’, ‘genre’);
});
}
};
На языке SQL эти действия будут выглядеть следующим образом:
ALTER TABLE `games`
ADD COLUMN `tmp_genre` ENUM(‘action’,’adventure’,’shooter’,’racing’) NOT NULL AFTER `genre`;
UPDATE `games` SET `tmp_genre` = (
IF `genre` = ‘rasing’
THEN ‘racing’
ELSE `genre` END IF
);
ALTER TABLE `games`
DROP COLUMN `genre`;
ALTER TABLE `games`
CHANGE `tmp_genre` `genre` ENUM(‘action’,’adventure’,’shooter’,’racing’) CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;
И, кроме этого, всё-равно нужно будет на стороне приложения обрабатывать значение либо как константу класса, либо как enum класс. Например:
class Game extends Model
{
protected $casts = ;
}
enum GameGenreEnum: string
{
case Action = ‘action’;
case Adventure=”adventure”;
case Shooter=”shooter”;
case Racing = ‘racing’;
}
А теперь представьте, что как только эта задача выполнена, пришла новая – добавить новую категорию – `Fighting`…
Альтернатива этой боли – полный отказ от полей типа enum в пользу integer. В этом случае как при изменении названия, так и при добавлении нового всё что нужно будет сделать – это изменить содержимое самого enum класса. Например:
// До
enum GameGenreEnum: int
{
case Action = 1;
case Adventure = 2;
case Shooter = 3;
case Rasing = 4;
}
// После
enum GameGenreEnum: int
{
case Action = 1;
case Adventure = 2;
case Shooter = 3;
case Racing = 4;
case Fighting = 5;
}
И всё. Никакой боли и задача закрывается буквально за несколько секунд.
Именно поэтому многие разработчики отказываются от использования колонок типа enum в базе данных сохраняя не только время, потраченное на задачу, но и нервы и, в качестве приятного бонуса, шанс потерять данные сводится к нулю.
Также можно ответить на вопрос “почему integer, а не string”: дело в том, что поля типа string подвержены грамматическим ошибкам и всё что они дают – лишь удобство чтения таких данных в одной конкретной таблице без использования SQL запросов. Но если в слове будет допущена ошибка или слово нужно будет заменить на другое – придётся отправлять запрос в базу, чего не нужно делать при использовании целочисленных значений.
Таким образом, тип полей enum в базе – это лютое зло.
Добавление server side Open Graph и прочего SEO в существующую SPA / Хабр | Веб-студия Nat.od.ua
Добавление server side Open Graph и прочего SEO в существующую SPA / Хабр
Представьте себе следующую ситуацию: у вас на руках есть SPA с рендерингом полностью на клиенте, и вам необходимо сделать так, чтобы в зависимости от URL было разное содержимое у тега
.Например, ваш шеф просит вас сделать так, чтобы при вставке в Телеграм ссылки на французскую версию сайта с query параметром ?hl=fr появлялась превью с французским заголовком и описанием сайта.
Как раз в такой позиции я оказался некоторое время назад, и мне на растерзание попался сайт на чистом, старом-добром, клиентском Vue.
У любого разработчика, знающего отличия SSR и CSR, первым инстинктом будет сказать, что это просто невозможно, а если и возможно, то надо переписывать сайт на Nuxt или хотя-бы на Vite SSR, на что уйдет парочка спринтов.
Но если вы не боитесь замарать руки о костыли, то есть и другой способ! Идея очень проста – пишем сервер на Node, который будет отдавать наш сбилженный сайт, но подменять в зависимости от запроса часть index.html.
Туториал
В первую очередь установим зависимости:
yarn add koa koa-static
Создаем файл entryServer.js. Из него мы будем отдавать наш сайт. В моем случае содержимое папки dist.
// entryServer.js
const Koa = require(‘koa’);
const fs = require(‘fs’);
const app = new Koa();
app.use(async (ctx, next) => {
const distHtml = fs.readFileSync(‘dist/index.html’, ‘utf8’);
ctx.body = distHtml;
});
const PORT = 3000;
console.log(`Listening on port ${PORT}`);
app.listen(PORT);
Если запустить node entryServer.js, то на https://localhost:3000 будет пустая страница. Это потому что все ассеты и скрипты недоступны, и сервер отдает вместо них index.html. Чтобы это исправить используем koa-static.
// entryServer.js
const Koa = require(‘koa’);
const fs = require(‘fs’);
const serve = require(‘koa-static’);
const app = new Koa();
app.use(async (ctx, next) => {
// Если запрашивается файл,
// то переходим к мидлваре,
// которая отдает статические
// ассеты
if (ctx.request.url.includes(‘.’)) {
await next();
return;
}
const distHtml = fs.readFileSync(‘dist/index.html’, ‘utf8’);
ctx.body = distHtml;
});
// Отдаем содержимое каталога dist
app.use(serve(‘dist’));
const PORT = 3000;
console.log(`Listening on port ${PORT}`);
app.listen(PORT);
Теперь наш сайт работает, как должен, но все еще только на клиенте. Давайте добавим логику на стороне сервера! Создадим несколько файлов в которых содержатся вариации SEO тегов для разных языков, например:
// entryServer.js
const Koa = require(‘koa’);
const fs = require(‘fs’);
const serve = require(‘koa-static’);
// Файлы, которые содержат только
// теги, которые мы собираемся локализовать.
//
const heads = {
en: fs.readFileSync(‘./head/en.html’).toString(),
de: fs.readFileSync(‘./head/de.html’).toString(),
fr: fs.readFileSync(‘./head/fr.html’).toString()
};
const app = new Koa();
app.use(async (ctx, next) => {
// Если запрашивается файл,
// то переходим к мидлваре,
// которая отдает статические
// ассеты
if (ctx.request.url.includes(‘.’)) {
await next();
return;
}
// Здесь мы смотрим на параметр hl
// и выбираем необходимый набор тегов.
// Английский выбирается по умолчанию.
const lang = ctx.request.query.hl;
let head = heads.en;
if (Object.keys(heads).includes(lang)) {
head = heads;
}
const distHtml = fs.readFileSync(‘dist/index.html’, ‘utf8’);
const body = distHtml.replace(‘‘, `${head}n`);
ctx.body = body;
});
// Отдаем содержимое каталога dist
app.use(serve(‘dist’));
const PORT = 3000;
console.log(`Listening on port ${PORT}`);
app.listen(PORT);
Вот наш законченный сервер! Если пользователь вставит my-spa.com?hl=fr в сайт или приложение, которое парсит Open Graph, то превью будет на французском. И нам даже не пришлось тратить сотни часов на миграцию на SSR фреймворк!
История создания уникальной платформы Batur / Хабр | Веб-студия Nat.od.ua
История создания уникальной платформы Batur / Хабр
Меня зовут Андрей Машуков, и я являюсь генеральным директором компании Open Soft. Наше начало относится к 2020 году, когда мы основали компанию в самом сердце России — в Москве. Несмотря на то, что 2020 год был сложным для многих из-за мировых вызовов и нестабильности, мы решили рискнуть и начать новое направление в IT.
С самого начала нашего пути, мы стремились выделиться на рынке, предлагая инновационные решения и качественное программное обеспечение. Хотя наш путь начинался не в гараже, как у многих стартапов, вызовы, с которыми мы сталкивались, были не менее сложными. От бюрократических препятствий до быстро меняющегося рынка — каждый этап требовал от нас гибкости и профессионализма.
На протяжении всех этих лет, ключевой фактор, который делал нас выдающимися, был наш коллектив. Собрав команду настоящих профессионалов, каждый из которых является экспертом в своей области, мы обеспечили себе репутацию компании, предоставляющей превосходные продукты и услуги. Наш девиз всегда был: «На шаг впереди технологий». Благодаря такому подходу, даже за короткий период существования, Open Soft заняла лидирующие позиции на рынке, устанавливая новые стандарты в IT-сфере.
Переезд на Бали и зарождение идеи
Сентябрь 2022 года ознаменовался для меня особым событием: я отправился на Бали. На фоне активной работы и быстрого роста Open Soft в Москве, моё решение уехать могло показаться немного неожиданным. Однако мне было важно найти некий оазис вдохновения, новые горизонты для самосовершенствования и, возможно, для будущего направления нашего бизнеса.
Прибыв на Бали, я был поражен красотой и уникальностью этого места. Однако, как и многие другие иностранцы, я столкнулся с определенными трудностями. Поиск жилья, адаптация к новой культурной среде, выбор транспортных средств и даже простое ориентирование в местных объявлениях и событиях оказались задачей не из простых. Все это стало толчком к рождению идеи нового проекта.
Так, погружаясь в культуру и быт Бали, мне стало ясно, что есть реальная потребность в создании интегрированной платформы для помощи как местным жителям, так и приезжим. Платформа, которая могла бы объединить все основные потребности: от поиска жилья до рекомендаций по мероприятиям. И именно такой опыт, такие наблюдения стали основой для зарождения проекта «Batur».
Подача объявлений и поиск на сайте Batur
Проект Batur был создан с учетом потребностей русскоязычных пользователей, желающих найти или предложить различные услуги на острове Бали. Несмотря на то, что на момент его создания на рынке уже было много различных ресурсов для поиска жилья, транспорта и других услуг, Batur выделяется на их фоне. Главное его отличие — это адаптация под русскоязычную аудиторию, а также высокое качество предоставляемой информации.
На платформе Batur представлены разнообразные категории объявлений, чтобы удовлетворить потребности как местных жителей, так и гостей острова Бали. Вот более подробное описание ключевых категорий:
Транспортные средства. Автомобили: От легковых автомобилей до специализированных машин; Мотоциклы: Различные типы двухколесного транспорта; Грузовики и спецтехника: Для строительства и других отраслей; Водный транспорт: Лодки, яхты и другие суда; Запчасти и аксессуары: Все для ремонта и тюнинга транспорта.
Недвижимость. Квартиры: Различные варианты для жилья или инвестирования; Виллы: Роскошные дома для отдыха или постоянного проживания; Комнаты: Для короткосрочной аренды или долгосрочного проживания; Дома, земля, гаражи и парковка: Различные варианты недвижимости; Коммерческая недвижимость: Офисы, склады, магазины и пр.
Электроника. Телефоны, аудио и видео: Последние модели и популярные бренды; Компьютерные товары и игровые консоли: Все для работы и развлечений; Ноутбуки, ПК, фототехника: От бытовой техники до профессиональной.
Услуги. Логистика, строительство, ремонт: От перевозки грузов до капитального строительства; Обучение и курсы: Разнообразные программы обучения и тренинги; Услуги для дома и бизнеса: От уборки до организации мероприятий.
Личные вещи и продукты. Одежда, обувь, аксессуары: Для мужчин, женщин и детей; Товары для детей и игрушки: Все для комфорта и развлечения ваших малышей; Красота и здоровье: Косметика, парфюмерия и медицинские товары.
Питание и рестораны. Доставка еды, магазины продуктов, рестораны: Все для гурманов и тех, кто просто хочет вкусно поесть.
Туры и путешествия. Разнообразные туры: От отдыха на пляже до экстремальных приключений.
Это лишь краткое описание категорий, доступных на Batur. Каждая категория содержит множество подкатегорий, чтобы упростить процесс поиска и сделать его максимально эффективным. Независимо от того, что вы ищете или предлагаете, Batur — ваш надежный партнер на Бали.
Чтобы разместить объявление на сайте Batur, достаточно выполнить несколько простых шагов:
Регистрация: Прежде всего, необходимо зарегистрироваться на сайте, указав свои контактные данные.
Создание объявления: В личном кабинете вы сможете создать новое объявление, заполнив все необходимые поля. Это может быть предложение по аренде жилья, услуги перевозки или любое другое предложение, актуальное для жителей и гостей Бали.
Модерация: Все объявления проходят проверку нашей командой на соответствие стандартам качества и достоверности информации. Это гарантирует, что наши пользователи получат только актуальную и полезную информацию.
Если же вы ищете что-то для себя, то благодаря удобной навигации и простому интерфейсу сайта, вы без труда найдете то, что вам нужно. Каждое объявление содержит детальное описание, фотографии и контактные данные продавца или арендодателя.
Отличительная особенность проекта Batur — это отсутствие конкурентов с таким же уровнем качества и адаптации. Многие аналогичные ресурсы либо не предоставляют информацию на русском и английском языках, что затрудняет их использование, либо имеют ограниченное количество информации.
Batur наполняется благодаря усилиям профессионалов из команды Open Soft, которые, разрабатывая веб и мобильные приложения, уделяют особое внимание качеству продукта. Это гарантирует не только удобство и безопасность использования сайта, но и его актуальность для пользователей.
Отношение к качеству и команда
Для Open Soft качество не просто приоритет — это наша карточка визитная. В эпоху быстро меняющихся технологий и растущих потребностей пользователей, только высокое качество продукта может гарантировать его успех на рынке. Именно поэтому мы делаем основной упор на разработку веб- и мобильных приложений, которые не просто удовлетворяют, но и превосходят ожидания наших клиентов.
Наши разработчики владеют передовыми технологиями, позволяющими создавать продукты, отвечающие современным требованиям безопасности, производительности и пользовательского опыта. Однако, даже самые совершенные инструменты не могут заменить человеческий профессионализм и тщательность. Именно поэтому, в дополнение к высококвалифицированной команде разработчиков, мы используем автоматизированное тестирование.
Автоматизированное тестирование позволяет нам выявлять и устранять ошибки на ранних этапах разработки, что существенно сокращает время на отладку и увеличивает скорость выхода продукта на рынок. Кроме того, внедрение технологии CI/CD (Continuous Integration / Continuous Deployment) гарантирует постоянное обновление и оптимизацию наших приложений, предоставляя пользователям только самые свежие и качественные версии продукта.
Наши специалисты:
Разработчики веб и мобильных приложений, которые используют передовые технологии для создания надежных и масштабируемых решений.
Инженеры по автоматизированному тестированию, обеспечивающие стабильность и высокую производительность наших приложений.
Специалисты по CI/CD, гарантирующие быструю и бесперебойную доставку обновлений для наших клиентов.
Такой подход позволяет нам создавать продукты, которые отвечают самым высоким стандартам качества, и удерживать позиции лидера в отрасли веб- и мобильной разработки. Наша команда — это коллектив единомышленников, которые объединены одной целью: предоставлять клиентам лучшие решения на рынке.
Заключение
Batur — это не просто платформа для объявлений, это место, где каждый может найти то, что искал на острове Бали, будь то уютное жилье, надежный транспорт или интересные мероприятия. Мы, в команде Open Soft, приложили максимум усилий, чтобы создать действительно удобный и функциональный инструмент для всех, кто связан с этим прекрасным островом.
Если вы нашли для себя что-то полезное или просто хотите поддержать наш проект, не забудьте подписаться на нас. Ваш лайк и комментарий помогут нам понять, что мы движемся в правильном направлении и стимулировать нас к дальнейшему развитию. Ваши отзывы и пожелания — лучший компас для нашего проекта. Благодарим за ваше внимание и доверие! Надеемся, что Batur станет вашим незаменимым помощником на острове Бали.
Добавьте 𝚍𝚒𝚛="𝚊𝚞𝚝𝚘" к полю ввода / Хабр | Веб-студия Nat.od.ua
Добавьте 𝚍𝚒𝚛="𝚊𝚞𝚝𝚘" к полю ввода / Хабр
Разработчикам, живущим в пузыре под названием «США» трудно воспринимать остальные страны. Но мне очень часто напоминают, что снаружи тоже есть мир. Это введение может показаться похожим на совершенно необязательную мотивационную речь перед изложением чего-то крайне простого, но одна маленькая деталь может стать разницей между тем, что вашим приложением пользуются люди со всего света, или только люди вроде вас. Разницу между этими мирами я постоянно безуспешно пытаюсь осознать; к счастью, те, кто занимается разработкой качественных веб-браузеров, делают за нас всё самое сложное.
С самого начала разработки Standard Notes я получал просьбы о добавлении поддержки языков с написанием справа налево (RTL; это такие языки, как иврит, арабский и урду). И каждый раз, когда я начинал изучать необходимые для этого действия, это казалось нетривиальной задачей.
Чаще всего в решениях предлагалось добавлять в поля ввода слушатель символов, а при обнаружении символа RTL переключать направление ввода с dir=”left” на dir=”right”. Звучит довольно логично, но вручную реализовывать это страшновато. Для меня Unicode, ASCII и весь мир кодировок не стал тем, в чём бы я хотел разбираться на низком уровне. Поэтому каждый раз, когда я могу избежать написания низкоуровневого парсинга языков, я пользуюсь этой возможностью.
Тема добавления поддержки RTL всплывала каждые несколько месяцев, и каждый раз, когда я изучал этот вопрос, совет всегда был одинаковым: напишите парсер символов, используйте вот такую стороннюю библиотеку или dir=”right”, но ничем этим я заниматься не хотел. Если вы выполните поисковый запрос “textarea rtl” или “textarea right to left” или другие похожие запросы, то ни в одном из них не будет упоминания dir=”auto”. Вместо этого вы увидите ответы типа «используйте в теге dir=”rtl”», или «возьмите эту стороннюю библиотеку», разработанную Twitter, которая обещает, что сделает всё за вас.
Первая страница результатов Google никогда не лжёт, поэтому я думал, что эта проблема требует прямого вмешательства, и никогда не давал ей высокого приоритета.
И лишь несколько недель назад я решил, что больше медлить нельзя. Проблему нужно решить. Я выполнил ещё несколько поисковых запросов, и наконец нашёл пост на GitHub, в котором какой-то неоценённый герой написал: «Можно просто добавить dir=”auto” к textarea.»
Что? Не может быть. Это не может сработать. После года поисков решений всё оказалось так просто?
Ага. Я вставил код, проверил, и всё заработало блестяще.
Ничего себе.
Итак, я должен сделать небольшое, но важное публичное заявление: Google лгал нам о поддержке RTL в полях ввода. Она намного проще, чем можно было представить.
И теперь вы это знаете.
Очень сложное демо.
Документация Mozilla по dir.
Как мы создали игру в эстетике киберпанка / Хабр | Веб-студия Nat.od.ua
Как мы создали игру в эстетике киберпанка / Хабр
Всем привет! Меня зовут Кирилл, я фронтенд-разработчик. В этой статье я расскажу о том, как мы с однокурсниками из разных уголков страны делали игру в рамках обучения на курсе «Мидл фронтенд-разработчик».
Во фронтенде я около двух лет. До этого в основном писал бэкенд на .net — мне было скучно, но подозреваю, дело не в бэкенде, а в конкретном проекте. Во многом поэтому я решил попробовать себя во фронтенде — и ни разу не пожалел.
Когда работаешь в продуктовой команде, так или иначе всё крутится вокруг одного воркфлоу/стека — ты привыкаешь к этому. В какой-то момент у меня появилось желание пойти учиться, чтобы освежить свои знания и погрузиться во что-то новое. Я стал мониторить различные курсы, разбил их по критериям «программа/длительность/стоимость» и остановился на курсе «Мидл фронтенд-разработчик» от Яндекс Практикума. Мне понравилась программа, потому что в ней планировались два отдельных проекта, много новых технологий, новый для меня язык — React, погружение в системные вещи, а также полный цикл разработки проектов от инициализации до деплоя. А второй модуль программы подразумевал командную работу и написание игры. Мне кажется, каждый программист мечтает попробовать написать игрушку.
Начинаем работать над игрой
Благодаря случайному распределению наша команда получилась разношерстная. Я — с опытом на Angular, Максим — единственный из нас имеющий коммерческий опыт на React, Антон, который работает с Vue, и Алексей без коммерческого опыта в разработке. После знакомства с командой необходимо было решить организационные вопросы и распределить задачи.
Огромный плюс обучения в Практикуме в том, что ты можешь примерять на себя различные роли и экспериментировать. Даже если что-то пойдёт не так, ничего критичного не произойдет. На работе, к сожалению, так нельзя, ошибки часто бывают очень дорогостоящими. Недолго думая я вызвался быть лидом в команде — хотелось попробовать себя в руководящей позиции.
Распределяем нагрузку в команде
Еще один важный нюанс в начале пути — это синхронизация в работе. Все живут в разных часовых поясах, у всех есть семьи, основная работа, личная жизнь, поэтому нужно было определиться со временем для созвонов. Также необходимо было оперативно понять темп каждого участника и всей команды в целом. В течение двух спринтов мы нашли свою оптимальную «формулу». Спринты длились по две недели, в начале спринта мы созванивались и распределяли задачи, ещё пару раз в спринт созванивались, чтобы обсудить успехи, вопросы, проблемы по задачам. Кроме того, мы обсуждали общие вопросы в чате и фиксировали статусы.
Сначала нужно было распределить задачи, чтобы не случалось провисаний. Необходимо было минимизировать простои каждого члена команды. Всё как в реальных проектах. Конечно, случались и проколы, но мы оперативно выравнивались. Приложение росло и делилось на отдельные модули, за каждый из которых был ответственен конкретный член команды. Постепенно у всех сложилось видение проекта.
Новые задачи почти всегда логически продолжали предыдущие, поэтому мы могли заранее распределить их внутри команды. Конечно, при таком подходе часть информации и технологий, которые ты изучаешь на курсе, проходят мимо: если ты занимаешься «прикручиванием» Redux, то тебе некогда пощупать Docker. Опять же, время бежит и тебе уже нужно сдать на ревью свои задачи. Но я не жалею, что не успел изучить всё, — думаю, это справедливая цена за большой объём материала и технологий.
Придумываем игру вместе
Теперь о самом важном — о проекте. Первое, что нужно было сделать после знакомства и распределения ролей, — придумать концепт игры. Что это за игра, какой у неё жанр и стилистика, что за историю она рассказывает? На эти вопросы нам нужно было ответить довольно быстро. Перед нами стояла нетривиальная задача: хотелось придумать что-то интересное, но в то же время не переборщить, поскольку время и силы были ограничены. Изначально я хотел сделать что-то сложное и эффектное, например, в стиле Alien Shooter, но после обсуждения с командой мы решили уделить больше внимания деталям игры, не делая её слишком сложной. Таким образом, благодаря ребятам нам удалось соблюсти баланс.
Вот так выглядел процесс голосования. На тот момент в команде был ещё один участник, но по личным причинам после первого спринта нас осталось четверо.
Основные метания были между клоном BattleCity и динозавром из Google Chrome. После голосования выбор пал на динозавра, но со своим блэкджеком и спрайтами. Сказано — сделано. Набросали дизайн, решили, что киберпанк и пиксель-арт — это то, что нам нужно. Захватывающий сюжет о том, что невесту главного героя похитили и единственный шанс её вернуть — это догнать злодеев. Как говорится, «Run, Forrest, run!». Оффтоп: в данной реализации наш герой так и не спасает свою возлюбленную 🙂
Интерфейс, основное меню и форум
Решаем сложности в процессе
Конечно, в начале проекта всё идет легко. Команда горит, задачи решаются, баги правятся на ходу, рефакторинг и тесты присутствуют. Но спустя какое-то время приходится возвращаться в реальный мир, где у всех есть семья, работа, желание позаниматься своими делами на выходных, а не разбираться, почему не заводится Server Side Rendering. Поэтому энтузиазм = темп падает, кто-то отсеивается. Но, несмотря на различные ситуации, которые возникали в процессе, и нервотрепку, нам удавалось сохранять боевой настрой в команде до самого конца.
Были моменты, когда все вставали в ступор: ничего не работает, промежуточная защита уже на горизонте, а задачи на спринт не убывают. Тут, как говорится, с миру по нитке. На помощь приходят куратор, ментор, другие команды в чате — и вот что-то начинает собираться и в итоге работает. Думаю, все разработчики знают это приятное чувство, когда твои усилия приводят к нужному результату.
Конечно, ошибки были разные, как простые, допущенные по невнимательности…
…Так и подобные, при настройке nginx + http2 + ssl, которые были вызваны кривыми руками, и, как обычно, все было просто из-за того, что я указал нестандартные порты 80 и 443 в nginx.config…
…а облако, куда мы деплоились, ожидало именно стандартные по умолчанию, соответственно много времени было убито впустую
Я люблю писать код, и, когда я работал над движком, мне было не жаль потратить больше времени: я добавлял различные фишки в игре, работал над визуальной составляющей и физикой в целом. В этой области я чувствую себя уверенно. Но когда мы приблизились к SSR, деплою, Nginx и Docker, то тут всё для меня было в новинку. Я, конечно, сталкивался с этим раньше, но никогда не поднимал всё это с нуля. Соответственно, количество затрачиваемых сил и времени стало увеличиваться.
Было легко запутаться в прокидывании портов, что за чем стоит и где точка входа, БД, Docker, backend, nginx, но, как говорится, терпение и труд… и клубочек распутывается
До сих пор помню это крутое ощущение, когда ты завернул всё в Docker, настроил прокси через Nginx, задеплоил на реальный сервер — и всё это открывается по реальному адресу в интернете! Уверен, ребята из команды со мной согласны. Конечно, матёрые синьоры сейчас скажут, что они делают это каждый день в перерывах на обед, но мы пока ещё лишь в начале нашего пути.
Игровой процесс
Долгожданный релиз и защита проектов
Финальное демо: напряжение нарастает, добиваются последние задачи, распределяются приоритетные баги. Всё как в реальной жизни — вот бы ещё платили деньги за это! И наступает момент релиза и оценки.
Мне самому было очень интересно, что получилось у ребят из других команд. Все работали на одинаковых условиях, у всех были одни и те же сроки на реализацию. Мы живые люди — соревновательный дух нам не чужд.
Я был в восторге от каждого проекта. Понравилось, что все они были очень разные. Была и настольная карточная игра, и головоломка 2048, и всеми любимые танчики, тетрис. В каждом проекте чувствовались приложенные усилия и старания участников команд. Помимо радости от окончания курса и возможности наконец-то немного выдохнуть, мы с командой получили приз зрительских симпатий! Спасибо участникам других команд за то, что оценили нашу работу, и команде Яндекса за такой опыт. Это было незабываемо!
Долгожданный момент
Напоследок хочется ещё раз поблагодарить мою команду, вместе мы дотащили весь проект, и сделали это достойно, по крайней мере, у нас получился проект, который при желании можно дальше развивать. Конечно, оглядываясь назад, я вижу, что можно было бы сделать иначе, лучше, изящнее, и ещё несколько подобных эпитетов, но ведь именно для этого мы и учимся:)
Подборка VS Code-плагинов для Frontend-разработчиков и не только / Хабр | Веб-студия Nat.od.ua
Подборка VS Code-плагинов для Frontend-разработчиков и не только / Хабр
Одним из наиболее ценных аспектов Visual Studio Code является его расширяемость с помощью плагинов, которые значительно облегчают и улучшают рабочий процесс. В этой статье мы собрали инструменты – от простых до продвинутых – которые сделают вашу разработку более продуктивной и приятной, позволяя сосредоточиться на творческой части процесса.
Color Info — Предоставляет краткую информацию о цветах CSS. По умолчанию расширение работает с любым документом css, sass, scss. Распознает все основные цветовые форматы, включая именованные цвета. Есть возможность настроить инструмент под собственные задачи.
VSCode Icons — Поможет быстрее сориентироваться среди множества файлов. Добавляет иконки папкам и файлам. Нет нужной иконки? Не беда — можно добавить свою.
Git History — Покажет историю изменений коммита, файла или отдельной строки. Поддерживает горячие клавиши, сравнения файлов и поиск по истории.
Prettier — Автоматически форматирует ваш код приводит его к единому стилю, расставляет табы, пробел и отступы. Поддерживает множетво языков, фреймворков и интеграций.
Peacock — Изменение цвета рабочей области. Идеально подходит, если у вас есть несколько окон или используете VS Live Share. Имеет обширную документацию и множество вариантов настройки.
Peacock
VS Faker — Генерирует фейковые данные (адреса, имена, числая и другую информацию), используя библиотеку Faker. Отлично подойдёт для быстрого тестирования.
Live Server — Предоставляет локальный сервер с функцией живой перезагрузки для своего проекта. Прост в использовании, имеет горячие клавиши и множество вариантов настройки.
Live Server
GitLens — Расширяет возможности Git в VS Code. Позволяет взглянуть на кого, почему и когда была изменена строка или блок кода, а затем перейти к истории, чтобы получить аналитические сведения о развитии кода.
Bookmarks — Поможет ориентироваться в коде, легко и быстро перемещаясь между важными местами с помощью закладок. Имеет обширный и удобный функционал.
ESLint — Проверяет код и выделяет ошибки для обеспечения согласованности и правильности JavaScript-кода в соответствии со стандартами.
Quokka.js — Обеспечивает мгновенную отладку и вывод результатов JavaScript-выражений в реальном времени.
Quokka.js
Path Intellisense — Предоставляет автозаполнение путей файлов и папок. Теперь не нужно лазить по папкам в поиске нужного файла.
npm Intellisense — Предоставляет подсказки при работе с npm-пакетами.
🔥 Ежедневные тесты, статьи и многое другое для frontend-разработки на канале: Frontend Formula