как оформить спецификацию, чтобы не запутаться самому и не выбесить коллег / Хабр | Веб-студия Nat.od.ua
как оформить спецификацию, чтобы не запутаться самому и не выбесить коллег / Хабр
Привет, на связи Ефим Иванов — Product Owner, а в недавнем прошлом системный аналитик на финтех-проектах Outlines Tech. Делюсь своим опытом, как составлял спецификации и облегчал работу команде. Я выявил два подхода: «все по полочкам» и «история создания решения». В статье найдете объяснение, чем отличаются методы, как выглядят и насколько удобны для каждого звена команды разработки.
Начну с азов: что такое спецификация на разработку?
Спецификация — это описание разрабатываемой/разработанной части системы. Документ создают на этапе проработки задач, чтобы адаптировать требования бизнеса под системный язык и передать команде разработки.
В спецификацию включают описание архитектуры, интерфейса, отдельных микросервисов, данные для тестирования, нефункциональные требования и прочее. Обычно спецификации создают системные аналитики и технические писатели, в редких случаях — продвинутые бизнес-аналитики. Составляют её на странице confluence, в swagger или в отдельном word-документе.
Кому нужна спецификация?
Системным аналитикам
Они создают спецификацию, чтобы адаптировать требования бизнеса и описывать процесс создания системы.Бизнес-аналитикам
Они использует спецификацию, чтобы обозначить требования бизнеса и сравнить их с итоговом работы. А еще они исследуют документы других команд, чтобы изучить готовые решения для нового или дорабатываемого процесса.Программистам
Разработчики извлекают из спецификации информацию обо всей логике планируемой работы, чтобы понять задачу: поля, запросы, форматирование и преобразования, обработку ошибок, коды систем и прочееQA-инженерам
Спецификация позволяет определить логику работы, чтобы просчитать все возможные сценарии допущения ошибки.Сопровождению
Они просят спецификацию, чтобы в случае возникновения ЧП оперативно локализовать проблему.
Сразу отмечу, что не существует идеальной документации, которая удовлетворяет требования сразу всех стейкхолдеров. А с учетом внедрения гибких методологий, создание исчерпывающей спецификации в довольно сжатые сроки — задача не из легких.
Я выявил для себя два подхода ведения документации: один назовем «все по полочкам», а второй — «история создания решения».
Подход «все по полочкам»
Первый способ подразумевает строго повторяющейся шаблон спецификации. Например, при создании нового модуля в confluence используется шаблонный набор страниц: «Описание экранных форм», «Описание микросервисов», «Архитектура», «Интеграции», «Чек-лист внедрения» и подобные.
На наших проектах это выглядело так:
Главная особенность подхода — подробное описание. Если это экранные формы, то текст содержит название компонента, его тип, источник данных, преобразование, маску, обязательность. Спецификация на микросервисы содержит сценарии вызовов, «маппинг» полей, а обработку ошибок вводят, используя макрос swagger.
Подход «все по полочкам» также описывает доработку старого модуля. Достаточно открыть статьи и внести изменения. Корректировки, которые внедряют, помечают красным цветом, а после завершения работы снимают выделения.
Плюсы подхода
Описание кажется исчерпывающим. Когда знаешь, что где лежит, без проблем отслеживаешь весь путь запроса: от извлечения данных из базы до окрашивания полученного значения в интерфейсе. Подход унифицированный, что ускоряет наполнение разделов, и все участники смогут найти требуемую информацию.
Недостатки
Подход задвигает на второй план бизнес-требования к разработке. Конечно, у нас есть страница с описанием процесса и пожеланий. Однако она выглядит сильно обособлено от остальных и не гарантирует выполнение задач. Проблему решает усложнение страницы: установка якорей, добавление ссылки на задачи в Jira, дублирование части логики на страницу с требованиями.
Второй недостаток — при изменении требований проблематично отследить, когда и почему произошли перемены. Мы увидим только последние задачи.
Подход «история создания решения»
Второй способ более анархичный. Создается центральная страница, в которой идет «повествование», как прорабатывали и создавали решение. На первом этапе её наполняет бизнес-аналитик. Он описывает пользовательский сценарий, планируемую логику работы разработки, как часто операция выполняется, роли в приложении и прочее. После этого рисуют макет интерфейса, который прикладывают к странице.
Далее в дело вступает системный аналитик. Он определяет набор микросервисов, пробегается по статье и проставляет в таблице атрибутов поля сервисов и логику форматирования. Делает ссылки на другие страницы, где добавляют подробные описания.
Также в статью добавляют задачи на разработку, чтобы понимать, в какой части сделан тот или иной функционал. Для тестировщиков в документ вносят информацию по поиску тестовых данных, которые понадобятся.
Оглавление такой страницы выглядит примерно так:
В итоге статья выглядит как большая история требований бизнеса с множественными вкраплениями системных вещей. Сравнить ее можно с длинным и пёстрым полотном:
Плюсы подхода
Метод решает главную проблему «все по полочкам». Мы открываем статью и видим, как и когда решали конкретную проблему бизнеса. По опыту отмечу, подход удобен тестировщикам: он позволяет понять контекст. А еще комфортен бизнес-аналитикам: коллеги спокойны, что их требования услышаны.
Недостатки
В подходе «история создания решения» смещен фокус с разработки. Если в задаче сделать ссылку на спецификацию, программисту потребуется прочитать весь документ, чтобы понять, что от него требуется. При этом ему достаточно, чтобы конкретно написали, что важно добавить и куда. Конечно, коллеги сразу указывают пожелания в письме, но так теряется один из смыслов спецификации — постановка задачи разработчику.
Второй недостаток — в одной статье невозможно описать всю логику поведения приложения, запросы, стенды, балансировщики и прочее. Поэтому спецификация всегда будет иметь некоторую неоднозначность и неопределенность, и все детали уточняются именно при анализе кода приложения. Ну и размер статьи стремится к плюс бесконечности.
Сравнение двух подходов
«Все по полочкам»
«История создания решения»
Унификация
Полная
Почти нет
Количество информации
Расписано все
Отсутствуют некоторые технические детали
Связанность с бизнес-требованиями
Минимальная, не гарантировано
Максимальная.
Одна статья, есть ссылки на задачи, где выполнялись
Поддержание актуальности при доработках
Выделение цветом правок, которые внедряются. После завершения работ – снятие выделений
Добавление ссылок на задачи, где вносятся описанные доработки
Версионность правок
Отсутствует (присутствует только версионность страницы confluence)
Присутствует. Описана доработка и дана ссылка на задачу
Удобство для системного аналитика
Удобно: один стандарт
Необходимо изучать весь документ и вписывать ключевые моменты
Удобство для разработчиков
Единый стандарт, не нужно вникать в суть задачи
Требуется больше времени на изучение, зато происходит большее погружение в проблематику и увеличивается вероятность нахождения несостыковок в логике
Удобство для QA-инженеров
Есть отдельная страница, слабая связанность с конкретными атрибутами
Обычно в статье пример ответа и ссылка на сценарий и скрипт поиска – это удобно. Плюс виден весь контекст процесса
Удобство для сопровождения
Неудобно все, когда ПРОД-дефект закроете? 🙂
Вместо вывода
Мне, как бывшему системному аналитику, больше нравится первый метод. Он позволяет быстро найти запрос. Плюс всегда знаешь, где что лежит. Если вы только выбираете подход, то продумайте, на кого больше ориентируетесь: бизнес или IT-команда.
А если давно составляете спецификации, то расскажите, как оформляете и почему. Интересно обменяться опытом в комментариях.
7 плагинов Figma для оптимизации дизайн-процессов / Хабр | Веб-студия Nat.od.ua
7 плагинов Figma для оптимизации дизайн-процессов / Хабр
Figma, лидер в мире программного обеспечения для дизайна, предлагает множество плагинов для расширения функциональности и удовлетворения разнообразных потребностей дизайнеров. В этом посте я собрал несколько плагинов для Figma, которые помогут оптимизировать подготовку мокапов на каждом этапе.
Grammar Checker & Rewriter: улучшение качества контента в дизайне
Важно, чтобы контент был не только визуально увлекательным, но и грамматически правильным и четко сформулированным. Именно здесь вступает в игру плагин Grammar Checker & Rewriter для Figma от Linguix. Он умеет не только осуществлять многоязычную проверку грамматики, но и переписывать целые предложения. Плагин работает с контентом на разных языках, включая английский, французский, немецкий, испанский, португальский и польский.
То, что отличает этот плагин, – это его способность в режиме реального времени обнаруживать грамматические ошибки и немедленно улучшать контент. Ошибки в написании или предложения, которые можно улучшить в данном объекте Figma, подчеркиваются. Пользователи могут применить исправления одним щелчком или раскрыть их для получения дополнительного контекста. Все работает прямо внутри пространства Figma и только там – то есть установив плагин, не нужно потом настраивать его и на других сайтах.
Unsplash: автоматизация поиска картинок
Графический контент играет ключевую роль в дизайне, часто определяя атмосферу и общее восприятие всего проекта. Понимая важность первоклассных визуалов, этот инструмент для Figma выступает в качестве революционного актива для дизайнеров. Созданный в партнерстве с Unsplash плагин предоставляет пользователям мгновенный доступ к обширной коллекции потрясающих изображений высокой четкости, которые можно использовать бесплатно.
Больше нет необходимости переключаться между несколькими платформами или загружать изображения отдельно; с плагином Unsplash потрясающие визуалы находятся всего в одном клике прямо в рабочем пространстве Figma.
Figma to Code: от прототипа в работающий MVP
Переход от визуального прототипа к функциональному коду может быть сложным процессом. Figma to Code предлагает революционный инструмент, который стремится упростить этот переход и способствовать более совместной работе между дизайнерами и разработчиками. Этот мощный плагин позволяет дизайнерам преобразовывать свои дизайны Figma непосредственно в используемый код для различных платформ, включая HTML, Tailwind, Flutter и SwiftUI.
Ушли дни утомительного ручного кодирования или недоразумений с элементами дизайна. С Figma to Code дизайнеры могут гарантировать, что их первоначальное видение точно переводится в конечный продукт, сохраняя целостность дизайна. Более того, автоматизируя процесс генерации кода, этот плагин не только ускоряет сроки проекта, но и снижает возможные ошибки, обеспечивая более плавный и эффективный рабочий процесс.
Mockup: Поднимая уровень демонстрации дизайна
В области дизайна отображение имеет важное значение. Здесь не только создается захватывающий дизайн, но и представляется его суть и практичность. Плагин Mockup для Figma выступает как бесценный инструмент в этом контексте, позволяя дизайнерам превратить плоские дизайны в красивые, реалистичные макеты буквально за секунды.
С обширной библиотекой устройств, от смартфонов до настольных мониторов, дизайнеры могут легко выбирать наиболее подходящий кадр для своего дизайна, обеспечивая тем самым, что их презентации будут как визуально привлекательными, так и контекстно актуальными. Интуитивный интерфейс плагина и безпрепятственная интеграция с Figma делают его легким в использовании, исключая необходимость во внешних инструментах или программном обеспечении.
Icons8 Background Remover: легко удаляем фон в изображении
Для дизайнеров способность легко удалять фоны из изображений бесценна. Плагин Icons8 Background Remover для Figma предоставляет пользователям эту точную возможность, обеспечивая возможность дизайнерам сосредотачиваться на своем креативном процессе, не забивая себя утомительной задачей ручного удаления фона.
Интегрируя передовую технологию искусственного интеллекта, этот плагин эффективно изолирует объекты на изображениях, что делает его неотъемлемым инструментом для дизайнеров, стремящихся к более чистому и профессиональному виду своих проектов. Независимо от того, работаете ли вы над веб-дизайном, маркетинговыми материалами или любым другим визуальным контентом, Icons8 Background Remover может значительно улучшить качество и четкость ваших дизайнов.
Illustrations: бесплатная библиотека изображений
Доступ к разнообразному спектру иллюстраций может стать разницей между хорошим и отличным проектом. Плагин Illustrations для Figma вступает в игру, предоставляя дизайнерам богатую библиотеку художественных активов прямо у них под рукой.
Этот плагин гордится собой наличием коллекции высококачественных иллюстраций, охватывающей различные стили и темы, обеспечивая дизайнерам всегда подходящий визуальный элемент для своих проектов. Независимо от того, хотите ли вы внести намек игривости, экспертности или что-то среднее, плагин Illustrations представляет богатство выбора. Это важный инструмент для тех, кто стремится поднять свои дизайн-усилия на новый уровень и вдохнуть своих зрителей удивительными изображениями.
Image Palette: извлечение доминирующих цветов из изображения
Цвета играют ключевую роль в дизайне, часто задавая настроение, тон и общее восприятие проекта. Плагин Image Palette для Figma – это помощник дизайнера в этой области, позволяя извлекать доминирующие цвета из любого изображения без проблем. Просто выбрав изображение в Figma, этот плагин создает палитру, захватывающую его основные оттенки, предоставляя дизайнерам гармоничный набор цветов для работы.
Это не только обеспечивает визуальную согласованность, но и экономит драгоценное время, которое в противном случае было бы потрачено на ручной выбор цветов. Для дизайнеров, стремящихся создавать последовательные и визуально привлекательные дизайны, плагин Image Palette является незаменимым инструментом, совмещая изображения и теорию цвета.
***
А какие еще полезные расширения для Figma знаете вы? Пишите в комментариях – соберем самый подробный список в одном месте.
как создать оптимизированные веб-приложения. Чайник для чайников в SEO / Хабр | Веб-студия Nat.od.ua
как создать оптимизированные веб-приложения. Чайник для чайников в SEO / Хабр
Начнем с того что эта статья была написана на основе моего последнего собеседования и я не смог ответить на вопрос “Какой фреймворк использовать для SEO оптимизации, что бы абсолютно все поисковики индексировали сайт, если у нас 15 000 страниц?”. Правильным ответом было: Nuxt.js
SEO (Search Engine Optimization) – это важный аспект любого веб-проекта, который помогает улучшить видимость вашего сайта в поисковых системах. Оптимизация SEO может быть сложной задачей, но при использовании правильных инструментов и практик она становится более управляемой. В этой статье мы рассмотрим, как использовать фреймворк Nuxt.js для создания веб-приложений с учетом SEO.
Что такое Nuxt.js?
Nuxt.js – это фреймворк для создания универсальных (universal) веб-приложений с использованием Vue.js. Он предоставляет множество инструментов и функций для упрощения разработки веб-приложений, включая рендеринг на стороне сервера (SSR), статическую генерацию (SSG) и многое другое. С помощью Nuxt.js вы можете создавать мощные и быстрые веб-приложения, которые также будут оптимизированы для поисковых систем.
Преимущества использования Nuxt.js в SEO
Улучшенная производительность: Nuxt.js позволяет выполнять SSR и SSG, что улучшает скорость загрузки страниц и оптимизирует производительность вашего сайта. Это важно для SEO, так как быстрая загрузка страниц является одним из ключевых факторов ранжирования поисковых систем.
Удобное управление метаданными: Nuxt.js предоставляет удобные инструменты для управления метаданными, такими как заголовки страницы, описания и ключевые слова. Это позволяет легко оптимизировать страницы для поисковых запросов.
SEO-оптимизированные маршруты: Nuxt.js предоставляет возможность определения SEO-оптимизированных маршрутов, что упрощает создание человеко-читаемых URL-адресов и структуры сайта.
Как использовать Nuxt.js для SEO1. Установка Nuxt.js
Для начала вам нужно установить Nuxt.js. Вы можете сделать это с помощью команды npm:
npm install create-nuxt-app -g
create-nuxt-app my-seo-appСтруктура приложения Nuxt.js
Прежде чем мы углубимся в SEO, давайте рассмотрим структуру типичного приложения на Nuxt.js. Оно состоит из следующих частей:
Папка pages: Здесь находятся страницы вашего приложения. Каждый файл в этой папке представляет собой маршрут, который будет доступен в вашем приложении. Например, файл pages/index.vue будет доступен по адресу /.
Файл nuxt.config.js: Этот файл содержит конфигурацию Nuxt.js, включая настройки SEO.
Компоненты и стили: Вы также можете создавать компоненты и стили для вашего приложения в соответствующих папках.
SEO в Nuxt.js
Nuxt.js предоставляет несколько инструментов для улучшения SEO вашего веб-приложения. Рассмотрим их подробнее:
1. Мета-теги
Мета-теги играют важную роль в SEO, и Nuxt.js предоставляет удобный способ их управления. В файле nuxt.config.js вы можете определить мета-теги для каждой страницы вашего приложения. Например:
// nuxt.config.js
export default {
head: {
title: ‘Моя Страница’,
meta: ,
},
}
Здесь мы задаем заголовок страницы и описание, которые будут видны в результатах поиска.
2. Человекопонятные URL
Nuxt.js автоматически создает человекопонятные URL для ваших страниц на основе структуры файлов в папке pages. Это помогает улучшить SEO, так как URL-адреса, содержащие ключевые слова, более привлекательны для поисковых систем.
Ваш файл pages/index.vue будет автоматически доступен по URL /. Это создает URL-адрес, который хорошо подходит для SEO.
3. Server-Side Rendering (SSR) и Static Site Generation (SSG)
Одной из сильных сторон Nuxt.js является его способность к серверному рендерингу и статической генерации страниц. SSR позволяет поисковым системам легко индексировать ваш сайт, так как контент формируется на сервере и отправляется поисковикам в готовом виде. SSG, с другой стороны, позволяет создавать статические версии страниц, что также улучшает производительность и SEO.
Пример 3: Server-Side Rendering (SSR)
Добро пожаловать на мою страницу
{{ pageContent }}
В этом примере мы используем asyncData для выполнения запроса на сервере и получения контента. Это помогает улучшить SEO, так как контент будет доступен для индексации поисковыми системами.
Заключение
Nuxt.js может быть полезным инструментом, если у вас есть большое количество страниц на вашем сайте, таких как 15 000 страниц. Он поможет вам управлять контентом и улучшить SEO вашего сайта. Вот как Nuxt.js может помочь в данной ситуации:
Server-Side Rendering (SSR): Nuxt.js предоставляет поддержку SSR, что означает, что каждая страница будет рендериться на сервере перед отправкой ее на клиентский браузер. Это может существенно улучшить SEO, так как поисковые системы могут легко индексировать содержимое страниц, а также улучшить производительность сайта, так как клиенты получают готовые HTML-страницы. SSR позволит вам обрабатывать множество страниц без существенного влияния на производительность.
Статическая генерация (Static Site Generation, SSG): Если ваш контент не часто меняется, вы также можете использовать SSG, что позволит предгенерировать HTML-страницы для всех ваших 15 000 страниц на этапе сборки. Это снизит нагрузку на сервер и улучшит скорость загрузки. Nuxt.js предоставляет поддержку SSG и динамической маршрутизации, что делает его мощным инструментом для сайтов с большим количеством страниц.
Автоматическая генерация мета-тегов и человекопонятных URL: Nuxt.js упрощает создание человекопонятных URL и управление мета-тегами для каждой страницы. Это важно для SEO, так как позволяет оптимизировать каждую страницу для поисковых запросов.
Динамическая маршрутизация: Если у вас есть динамические данные, такие как блоги или товары, Nuxt.js позволяет вам создавать динамические маршруты и генерировать страницы на лету, когда пользователь запрашивает определенную страницу.
Управление состоянием: Nuxt.js также предоставляет удобное управление состоянием приложения с использованием Vuex, что может быть полезно для обработки большого объема данных.
Разделение кода: Nuxt.js может автоматически разбивать ваше приложение на несколько частей, что помогает улучшить производительность, особенно при большом объеме кода.
Кеширование: Вы можете настроить кеширование для уменьшения нагрузки на сервер и ускорения загрузки страниц.
Оптимизация изображений: Nuxt.js также предоставляет инструменты для оптимизации изображений, что может быть полезно при наличии большого количества изображений на сайте.
Не забудьте также провести анализ ключевых слов и контента, чтобы оптимизировать каждую страницу для поисковых запросов вашей аудитории. Важно учесть, что хорошая SEO-оптимизация требует не только технических решений, но и качественного контента и стратегии продвижения.
Если вы знаете более находчивое решение чем Nuxt или же поможете мне более углубится в эту тему подскажите литературу и т.д. буду признателен.
Всем спасибо!
Добавили бота в свой Telegram канал? Будьте готовы с ним попрощаться / Хабр | Веб-студия Nat.od.ua
Добавили бота в свой Telegram канал? Будьте готовы с ним попрощаться / Хабр
Изучая безопасность мессенджера Telegram, меня поразила одна его “особенность” при работе с ботами – выяснилось, что при добавлении в канал бота никак нельзя ограничить его в правах на удаление подписчиков. То есть, говоря прямо, любой бот может вычистить всю аудиторию канала за считанные минуты.
Добавлять ботов в Telegram-каналы можно только как администраторов с целью автоматизации выполнения различных сервисных действий – например, планирование публикации постов и сбор всевозможной аналитики по каналу.
Почти все администраторы Telegram-каналов пользуются сторонними ботами от разных сервисов вроде Telemetr или Telepost и аналогичных. Причем сервисы часто специально навязывают добавление своего бота в канал. Например, всевозможные биржи рекламы вообще отказываются работать с каналом без наличия их бота – без него нельзя автоматизировать публикацию рекламы.
Таким образом администаторы добавляют к себе в канал бота за ботом, уповая на то, что следующая настройка прав не оставляет ботам никаких возможностей, кроме как работать с постами:
Редактирование прав из официального клиента Telegram
Однако, даже забрав у бота все права, доступные для редактирования из официального клиента, бот все еще будет оставаться администратором и иметь возможность не только читать любую администраторскую информацию о канале, но и выкидывать подписчиков.
С точки зрения Telegram API удаление подписчика из чата выглядит как бан с помощью API-метода editBanned. Т.е технически у всех ботов, которые попадают в канал, есть “несгораемые” права по бану участников.
Самое странное в этой ситуации то, что в Telegram API присутствует “скрытая” возможность отнимать у ботов права на удаление подписчиков, но в официальной версии Telegram она скрыта из интерфейса:
Неофициальная возможность в официальном API
Если же сделать этот API-запрос вручную, “насильно” выставив настройкуban_users, то обнаружится, что сервера Telegram по какой-то причине игнорируют её. Скорее всего, из-за этого настройка и отсутствует в официальных клиентах, хотя появилась она очень давно – можно посмотреть по истории TL Layer.
Как от этого защищаться? Пока Telegram не предлагает ничего лучше, чем написать собственный скрипт на основе Telegram API, который бы мониторил все удаления подписчиков в канале ботами и банил бы их. К счастью, банить подписчиков боты могут только пачками по 200 (ограничение Telegram на просмотр последних подписчиков канала), поэтому как только какой-то бот забанит первого подписчика, такого бота можно незамедлительно выбрасывать из канала. Это позволит не потерять всех подписчиков за несколько секунд.
Проблема тут только в том, что Telegram API не позволяет одним ботам банить других ботов, из-за чего скрипт мониторинга придется запускать от имени Telegram-пользователя, а не от имени Telegram-бота. С другой стороны, Telegram отправляет уведомления об удалении пользователей из каналов только ботам, а обычным пользователям – не отправляет🤬. Из-за всей этой неразберихи в API рабочая схема защиты будет выглядить так:
Добавляем в канал своего бота, который будет мониторить удаления подписчиков другими ботами
Если было обнаружено удаление, удаляем обнаруженного бота от имени второго аккаунта – пользователя
Код с использованием библиотеки Pyrogram для защиты канала по такой схеме может выглядеть примерно так:
# аккаунт бота
bot = Client(…)
async def banBastard(channelId, botId):
# запускаем аккаунт пользователя для удаления паршивца
user = Client(…)
async with user:
await user.ban_chat_member(channelId, botId)
# callback получения нотификаций об удалении пользователей в каналах, куда добавлен бот
@bot.on_chat_member_updated()
async def onMemberHandler(client, update):
banned = update.new_chat_member.status == enums.ChatMemberStatus.BANNED
byBot = update.new_chat_member.restricted_by.is_bot
if banned and byBot:
await banBastard(update.chat.id, update.new_chat_member.restricted_by.id)
# запускаем бота для прослушивания нотификаций об удалении пользователей
async def main():
async with bot:
while True:
await asyncio.sleep(1)
bot.run(main())
Есть и более простой, но менее надежный способ для администраторов Telegram-каналов. Но для этого придется, как бы сюрреалистично это ни звучало…добавить в канал бота @channel_guardian_bot 🙂 Он будет отслеживать все удаления подписчиков другими ботами и присылать уведомления. Если быстро среагировать, можно будет спасти существенную часть своей аудитории.
По какой причине разработчики Telegram не спешат с реализацией этой очевидно необходимой защиты на стороне сервере, я затрудняюсь ответить. Но пока их changelog будет выглядеть так, словно ничего, кроме сториз делать уже не осталось, администраторы Telegram-каналов спокойно спать не будут.
Методы хэширования паролей. Долгий путь после bcrypt / Хабр | Веб-студия Nat.od.ua
Методы хэширования паролей. Долгий путь после bcrypt / Хабр
Шифровальная машина M-209, на основе которой создана первая в истории функция хэширования crypt в Unix
Прошло 25 лет с момента изобретения алгоритма хэширования bcrypt (1997), но он до сих пор считается одним из самых стойких к брутфорсу хэшей.
Вот уже несколько десятилетий некоторые специалисты прогнозируют, что аутентификация будет производиться ключами/сертификатами. Но этого до сих пор не случилось. Пароли остаются неотъемлемой частью систем информационной безопасности. Вообще, они широко использовались ещё до изобретения компьютеров, так что в таком долгожительстве нет ничего удивительного.
Если посмотреть в историю, то концепция компьютерных паролей возникла на заре многопользовательских вычислительных систем, когда потребовался способ аутентификации и защиты данных. В Массачусетском технологическом институте в 1960-е разработали систему Compatible Time-Sharing System (CTSS) с парольной аутентификацией аккаунтов, одну из первых в мире таких систем. Любопытно, что это произошло несмотря на упорные возражения Ричарда Столлмана, который пытался противостоять введению паролей в MIT в 1970-е. Об этом вспоминал Стивен Леви в документальной книге «Хакеры: герои компьютерной революции».
Однако истинные истоки современной парольной защиты можно отнести к разработке Unix и её нативной функции хэширования crypt. Первоначальная версия crypt в Unix (6th Edition) была реализована Робертом Моррисом и базировалась на шифровальной машине Хагелина (модель M-209).
Конвертер M-209B Бориса Хагелина
О легендарном изобретателе шифровальных машин Борисе Хагелине рассказывали на Хабре. Родившийся в Российской империи, этот мальчик отучился в Баку, а отправился на дальнейшую учёбу за границу, где и стал знаменитым благодаря созданию уникальных шифровальных машин и основанию швейцарской компании Crypto AG в 1952-м, в течение десятилетий мирового лидера на рынке криптографических устройств.
Возвращаясь к Unix, специалисты ещё в 70-е годы осознавали проблему слишком быстрого выполнения функции crypt. В Unix (7-я редакция) функция была усовершенствована путём введения 12-битной соли и итерации шифра Data Encryption Standard (DES) для хэширования пароля. В результате использования соли получилось семейство из 2¹² различных хэш-функций, и каждый пользователь случайным образом выбирал из этого семейства свой пароль. Цель использования соли заключалась не только в том, чтобы обеспечить уникальность хэшей даже для одинаковых паролей, но и в том, чтобы существенно затруднить атаки с предварительным вычислением хэша. Хэшированный пароль с солью хранился в файле паролей, что позволяло системе аутентифицировать пользователей, не храня пароли в открытом виде.
Для своего времени crypt считался безопасным, однако развитие вычислительных мощностей и экспортные ограничения на криптографию в США открыли дорогу новым алгоритмам хеширования паролей, таким как MD5crypt (1994).
Запрещённый к экспорту из США код RSA распечатан на футболке в знак протеста против ограничения свободы слова. Одетый таким образом гражданин имел право выехать за границу и показать футболку иностранным гражданам
Опасения по поводу безопасности новых алгоритмов привели к разработке bcrypt в 1997 году. В нём впервые реализовали концепцию адаптивного хеширования, благодаря которой атаки методом брутфорса и по словарю стали вычислительно более сложными (алгоритм защищён от будущего роста производительности оборудования). С момента своего появления в июне 1997 года в составе OpenBSD 2.1 и публикации в USENIX в 1999 году bcrypt оказал глубокое влияние на индустрию безопасности.
Оригинальная научная статья с описанием bcrypt (1999)
В целом четверть века развития функций хэширования и индустрии брутфорса можно изобразить в такой таблице:
Сравнение функций хэширования и их безопасности. Адаптируемый коэффициент (work factor) означает, что нагрузку на CPU можно увеличить. Вычисления с расходом памяти (memory-hardness) означает, что кроме CPU алгоритм хеширования масштабируется и по памятиПроизводительность брутфорса
За последние 30 лет технологии взлома паролей и аппаратное обеспечение значительно эволюционировали. Мощность брутфорса сильно увеличилась. Стало очевидно, что нужно адаптировать алгоритмы хеширования паролей по стоимости работы. То есть сам алгоритм должен быть спроектирован таким образом, чтобы сделать нерентабельным брутфорс на современном оборудовании, а ещё лучше — с запасом прочности на годы вперёд.
Чтобы продемонстрировать этот прогресс, вот примерные оценки скорости брутфорса на компьютерах разных лет, а также в разных программах (Hashcat и John the Ripper). Следует иметь в виду, что эти цифры просто демонстрируют общий тренд, их нельзя напрямую сопоставлять из-за различий в оборудовании и ПО. Для наглядности цифры публикуются со всеми разрядами, без сокращения до «млн» и «млрд».
Можно заметить, что с годами растёт не только сложность алгоритмов, но и производительность железа, а также эффективность специализированных программ.
Например, за 34 года скорость перебора хэшей des-crypt выросла с 45 штук до 6,3 млрд в секунду.
В то же время старый bcrypt остаётся одним из самых сложных для взлома хэшей, особенно с максимальным коэффициентом сложности (work factor). Хотя формально он считается устаревшим, но на практике теоретически вполне пригоден к использованию, наряду с более современными, стойкими к брутфорсу алгоритмами scrypt и Argon2.
Пароли навсегда
Что будет дальше?
Современные алгоритмы хеширования очень сильно снижают эффективность брутфорса. Но утечки хэшей по-прежнему представляют собой постоянную угрозу. С другой стороны, появление многофакторной аутентификации (MFA) сместило акцент на защиту учётных записей пользователей с помощью дополнительных уровней проверки, в результате чего пароли стали менее важны для безопасности.
В современном мире всё большее распространение получают облачные сервисы, где большинство важных данных хранится удалённо. Простой брутфорс малоэффективен для проникновения в такие системы, поэтому злоумышленники, как правило, используют уязвимости или социальную инженерию.
Спустя четверть века люди до сих пор полагаются на пароли как основной метод защиты компьютерной информации. С каждым годом растёт их сложность (энтропия), вводятся более сложные методы хэширования, но сами текстовые пароли/фразы остаются.
Геймификация в охране труда: кому, зачем и как? | Веб-студия Nat.od.ua
Геймификация в охране труда: кому, зачем и как?
Часто бывает так, что обучение, проводимое работодателем, сводится просто к формальности. Сотруднику дают несколько страниц текста или несколько часов видео и потом проверяют его знания с помощью теста, где нужно просто отметить правильный ответ. Однако опыт специалистов в области охраны труда показывает, что такие методы неэффективны и не способствуют достижению основных целей этой области – сохранению здоровья и жизни сотрудников.
Использование геймификации может быть полезным для бизнеса, а игры могут помочь сотрудникам эффективнее учиться и снижать количество травм внутри компании.
Читать далее
Как добавить несколько товаров в Shopify корзину одним кликом? / Хабр | Веб-студия Nat.od.ua
Как добавить несколько товаров в Shopify корзину одним кликом? / Хабр
Недавно я писал конфигуратор в Shopify и решил поделиться тем, как добавить несколько товаров в Шопифай корзину. Я находил не так много материалов по этому вопросу, тем более на русском языке.
Прикрепляю скринкаст того, что можно сделать при помощи этого. Но применений довольно много, не только конфигуратор. В скринкасте я добавил 6 товаров по одному клику на “Add to cart” кнопку. Но до лимита в количестве добавляемых товаров я не дошёл, может их и нет.
Cart API
Чтобы добавить в корзину несколько товаров, вам необходимо отправить в Cart API объект items с идентификатором(id) продукта и количеством(quantities) товара. На скриншоте ниже я добавляю один товар по клику.
Подготовка items объекта для API
Но обязательно отправляйте идентификатор продукта вместо идентификатора варианта, если у вашего продукта есть варианты, иначе будет ошибка.
Так должен выглядеть отправляемый объект:
items:
Пример того, как можно сделать fetch запрос. Это не самая сложная версия такого запроса, но и не самая простая.
document.querySelectorAll(“form.configurator-form”).forEach((form) => {
form.addEventListener(“submit”, async (e) => {
e.preventDefault();
// Показываем спиннер загрузки
const loadingOverlays = document.querySelectorAll(“.loading-overlay”);
loadingOverlays.forEach((overlay) => overlay.classList.remove(“hidden”));
// Собираем данные товаров
const productData = selectedProducts.map((product) => ({
id: product.id,
quantity: 1,
variantId:
product.variantId && product.variantId !== product.id
? parseInt(product.variantId)
: undefined,
}));
const requestBody = {
items: productData,
};
// Добавляем товары в корзину
await fetch(`${window.Shopify.routes.root}cart/add.js`, {
method: “POST”,
headers: {
“Content-Type”: “application/json”,
},
body: JSON.stringify(requestBody),
});
// Обновляем корзину
const res = await fetch(“/cart.json”);
const cart = await res.json();
// Обновляем число на корзине
document.querySelectorAll(“.cart-count-bubble”).forEach((el) => {
el.textContent = cart.item_count;
});
// Перенаправляем пользователя на страницу корзины
window.location.href = “https://habr.com/cart”;
});
});Заключение
Будьте внимательны когда перед вами встанет эта задача, там довольно много подводных камней. Например, если у товара нет вариантов, то ID в value нужно передавать вот так:
{{ product.selected_or_first_available_variant.id }}
Полный код передаваемого инпута будет выглядеть так:
Но если варианты есть, то уже так:
{{ product.id }}
Полный код похож на предыдущий input, просто value другое:
Вот такой небольшой трюк, который вы теперь знаете. И ещё теперь вы умеете добавлять в корзину несколько товаров. Хорошей разработки!
Прогресс WebAssembly и будущее веба. Быстрые интерфейсы, пример Figma / Хабр | Веб-студия Nat.od.ua
Прогресс WebAssembly и будущее веба. Быстрые интерфейсы, пример Figma / Хабр
WebAssembly (Wasm) — это бинарный формат для безопасного и эффективного выполнения портативных программ в стековой виртуальной машине (в браузере или на сервере). Как и ASM.js, представляет собой низкоуровневый код. Есть ещё WAT — WebAssembly Text, человекочитаемая версия бинарного кода.
WebAssembly — не столько язык программирования, сколько цель компиляции, новый вид ассемблера, который работает близко к железу, принимая программы на C, C++, Rust и других привычных языках. При этом Wasm гораздо быстрее ASM.js и выполняет код в браузере почти как нативные программы под любой ОС.
Анатомия модуля WebAssembly. Программы называются модулями, потому что здесь нет разницы между программой и библиотекой, источник
Первая версия набора функций WebAssembly 1.0 одобрена консорциумом W3С, а некоторые стандартные фичи уже поставлены во все ведущие браузеры. Даже есть случаи масштабного рефакторинга на Wasm, после которого производительность сайта по некоторым параметрам возрастает в несколько раз.
Формат Wasm разработан для того, чтобы браузер мог как можно быстрее его разобрать. Например, вот время загрузки модулей Figma до и после оптимизации:
И код Wasm очень компактен, так что сетевая задержка тоже минимизируется до предела. Сравнение размера до и после оптимизации:
Такая разница в размере неудивительна, потому что синтаксис JavaScript был разработан для людей и содержит много избыточности и дополнительных правил, которые необходимо проверить перед выполнением.
До появления WebAssembly код C++ можно было выполнять в браузере путём кросс-компиляции на Asm.js. Это подмножество JavaScript, в котором можно использовать только числа (никаких строк, объектов и т. д.). Для C++ ничего больше не нужно, поскольку здесь всё является либо числом, либо указателем на число (а указатели — это тоже числа). Адресное пространство C++ — это просто гигантский массив чисел JavaScript, а указатели — просто индексы в этом массиве.
WebAssembly работает иначе, и поэтому здесь перед выполнением не нужно проверять код на ограничения JavaScript/Asm.js. В итоге бинарный код WebAssembly декодируется и выполняется иногда в 23 раза быстрее, чем соответствующий код asm.js.
Другие преимущества Wasm:
- Код C++ сильно оптимизируется компиляторами LLVM ещё до перевода в WebAssembly. Это значит, что браузер может напрямую транслировать его в нативный код, без всяких оптимизаций. В отличие от Wasm, обычный JS для быстродействия нужно оптимизировать на многих уровнях.
- Для браузеров не составляет труда кэшировать трансляцию модуля Wasm в нативный код. То есть при второй загрузке страница с этим модулем запускается практически мгновенно. Этого нельзя сказать об Asm.js, который смешивается с обычным JavaScript и требует сложной проверки, что он действительно соответствует требованиям.
- WebAssembly нативно поддерживает 64-битные целые. В JavaScript поддерживаются 64-битные флоаты (с плавающей запятой) и только 53-битные целые. 64-битные приходится эмулировать, что гораздо медленнее.
▍ Высокая производительность
Можно найти великолепные примеры высокой производительности веб-приложений. Например,
форумный движок AsmBB
, написанный полностью на WebAssembly, с интерфейсом FastCGI и базой SQLite для хранения зашифрованных данных. Целью разработки было создание максимально быстрого и лёгкого движка, при этом с современным UI. Насколько это получилось, можно оценить на
asmbb.org
.
Проект собран компилятором Flat Assembler (FASM). Размер движка около 65 КБ. За счёт минимального размера он всегда в самом быстром серверном кэше. Это уменьшает задержку, создавая ощущение высокой скорости. Разница заметна в том случае, если сеть и БД не являются узкими местами при обращении к серверу. В противном случае, конечно, всё равно, на чём написан сам движок. Тут происходит оптимизация конкретно CPU на сервере, ведь форумы с высокой посещаемостью на самом деле неслабо нагружают процессор. AsmBB запускается абсолютно на любом сервере x86, даже стареньком домашнем ПК. Возможно, это самый быстрый в мире форумный движок (такие бенчмарки ещё не попадались).
Инструкция по установке:
Или взять графический веб-редактор
Figma
, который в 2018 году осуществил
масштабный рефакторинг
, переписав ключевые части движка на Webasm. Это позволило
в несколько раз ускорить ключевые операции
. Например, загрузка документов ускорилась в три раза:
Эту оптимизацию пришлось проводить после того, как редактор Figma начали использовать корпоративные менеджеры для создания сверхсложных приложений. Например, дизайнеры из группы Fluent Design Team в Microsoft создали единый документ Figma со
всеми элементами управления Windows
во всех возможных состояниях и перестановках. По отдельности это несложные вычисления, но время загрузки такого документа оказалось существенным. Оптимизация на Webasm позволила сократить его с 29 до 8 с.
Чтобы понимать сложность обработки в редакторе, некоторые файлы Figma с сотнями тысяч слоёв с трудом умещаются в браузерный лимит оперативной памяти 2 ГБ для кучи. Из браузеров лимит 4 ГБ поддерживает только Chrome, да и то с багами.
На WebAssembly переписали все части, где происходит взаимодействие приложения с пользователями, включая десктопные версии, Chrome, Firefox и Safari на macOS и Windows.
Масштабирование тоже стало втрое быстрее:
Перетаскивание мышкой до и после оптимизации WebAssembly:
Если эти операции выполняются без лагов (фреймы максимальной длины в сотни миллисекунд), то в анимациях UI выпадает меньше кадров. Figma ориентируется на комфортный для пользователя фреймрейт 60 fps без лагов. К этому показателю приложение напрямую приблизилось после оптимизации WebAssembly:
Быстрый интерфейс — неотъемлемая часть удобного UX.
Для людей, которые устали от тормозных интерфейсов ожиревших сайтов и неповоротливых приложений, примеры использования WebAssembly с отзывчивым UI — словно глоток свежего воздуха в атмосфере современного веба.
Figma стала одним из пионеров по внедрению Wasm, потому что сооснователь и технический директор (ведущий программист) Figma Эван Уоллес был большим фанатом WebAssembly и опенсорса. Он выкладывал свои разработки на Github и многое сделал для продвижения этого революционного веб-стандарта (уволился в 2021-м).
Figma до сих пор остаётся примером не только коммерческого успеха, но и технического совершенства как программное приложение. Хотя сейчас появилось уже много последователей, веб-редакторов для быстрого прототипирования интерфейсов, таких как Penpot.
Penpot▍ Изучение WebAsm на практике
Для интенсивного изучения
WAT
с глубоким погружением можно рекомендовать
WATlings
— это специальный курс обучения путём исправления маленьких программ. Опыт показывает, что новые навыки усваиваются максимально быстро, если сразу дать практические задания, то есть создать «препятствия», которые ученик будет
самостоятельно
преодолевать. Это самая эффективная методика.
Многое о языке можно узнать только из его синтаксиса. Возникающие пробелы в знаниях восполняются знакомством с синтаксисом в различных контекстах. То есть многие вещи усваиваются без всякого предварительного объяснения, а просто на практике.
Здесь ещё один наглядный пример того, что излишние объяснения не только затрудняют, но и замедляют понимание предмета. Бывает, что годичный курс теории вполне заменяется трёхмесячной практикой. Об этом методе подготовки много хороших отзывов, так что его стоит попробовать.
Похожий подход обучения программированию с помощью задач использует Exercism, а курс по WebAssemly включает 21 упражнение.
Exercism
Но там учиться сложнее. Придётся читать много теоретического материала, который даётся параллельно.
Другие примеры кода на WAT для изучения см. здесь.
▍ Будущее — за WebAssemly
Подводя итог, WebAssemly позволяет создавать в веб-приложения, которые по производительности не уступают нативным программам для настольных компьютеров. Это новая универсальная вычислительная платформа. Она уже доказала свои преимущества для C, C++, Rust и других языков, а теперь сообщество WebAsm
готово к покорению мира
. Игра началась.
P. S. Как мы уже говорили, многие функции WebAssembly 1.0 приняты и поддерживаются браузерами. В ближайшие месяцы ожидается внедрение в браузеры ключевой поддержки GC, после чего Wasm сможет ссылаться и обращаться к JavaScript, DOM и общим объектам, определяемым WebIDL. Также идёт разработка новых функций, входящих в набор следующего поколения WebAssembly 2.0.
Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх 🕹️
Знакомство с рунами / Хабр | Веб-студия Nat.od.ua
Знакомство с рунами / Хабр
Эта статья — перевод оригинальной статьи “Introducing runes”.
Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.
Вступление
В 2019 году Svelte 3 превратил JavaScript в реактивный язык. Svelte – это фреймворк для создания веб-интерфейса, который использует компилятор для превращения декларативного кода компонентов в такой…
…в жестко оптимизированный JavaScript, который обновляет документ при изменении состояния, например, count. Поскольку компилятор “видит”, где ссылаются на count, генерируемый код очень эффективен, а поскольку мы используем такие синтаксисы, как let и =, а не громоздкие API, вы можете писать меньше кода.
Чаще всего мы получаем такие отзывы: “Хотел бы я писать весь свой JavaScript именно так”. Когда вы привыкли к тому, что вещи внутри компонентов волшебным образом обновляются, возврат к старому скучному процедурному коду кажется вам переходом от цветного к черно-белому.
В Svelte 5 все это изменилось благодаря рунам, которые открывают универсальную, тонкую реактивность.
Прежде чем начать
Несмотря на то, что мы меняем принцип работы под капотом, Svelte 5 должен стать полноценной заменой практически для всех. Новые возможности являются опциональными – существующие компоненты будут продолжать работать.
Дата выхода Svelte 5 пока не определена. То, что мы показываем здесь, – это наработки, которые, могут измениться.
Что такое руны?
Руны – это символы, влияющие на работу компилятора Svelte. Если сегодня в Svelte для обозначения конкретных вещей используются let, =, ключевое слово export и метка $:, то руны используют синтаксис функций для достижения того же и даже большего.
Например, чтобы объявить часть реактивного состояния, мы можем использовать руну $state:
На первый взгляд, это может показаться шагом назад – возможно, даже не по-свельтовски. Не лучше ли, если let count будет реактивным по умолчанию?
Нет. Реальность такова, что по мере роста сложности приложений выяснение того, какие значения являются реактивными, а какие нет, может стать сложной задачей. К тому же эвристика работает только для объявлений let на верхнем уровне компонента, что может привести к путанице. Если в файлах .svelte код ведет себя одним образом, а в .js – другим, это может затруднить рефакторинг кода, например, если вам нужно превратить что-то в хранилище, чтобы использовать его в нескольких местах.
За пределами компонентов
С помощью рун реактивность выходит за пределы файлов .svelte. Предположим, мы хотим инкапсулировать логику счетчика таким образом, чтобы ее можно было повторно использовать в разных компонентах. Сегодня для этого используется кастомное хранилище в файле .js или .ts:
import { writable } from ‘svelte/store’;
export function createCounter() {
const { subscribe, update } = writable(0);
return {
subscribe,
increment: () => update((n) => n + 1)
};
}
Поскольку в данном случае реализуется контракт с хранилищем – возвращаемое значение имеет метод subscribe, – мы можем ссылаться на значение магазина, добавляя к его имени префикс $:
//
Это работает, но довольно странно! Мы обнаружили, что API хранилища может стать довольно громоздким, когда вы начинаете делать более сложные вещи.
С рунами все гораздо проще:
// import { writable } from ‘svelte/store’;
export function createCounter() {
// const { subscribe, update } = writable(0);
let count = $state(0);
return {
// subscribe,
// increment: () => update((n) => n + 1)
get count() { return count },
increment: () => count += 1
};
}
// clicks: {$counter}
clicks: {counter.count}
Обратите внимание, что мы используем свойство get в возвращаемом объекте, поэтому counter.count всегда ссылается на текущее значение, а не на значение в момент вызова функции.
Реактивность во время выполнения
Сегодня Svelte использует реактивность во время компиляции. Это означает, что если у вас есть код, использующий метку $: для автоматического перезапуска при изменении зависимостей, то эти зависимости будут определены при компиляции компонента в Svelte:
Это работает хорошо… до того момента пока не перестанет. Предположим, что мы рефакторим приведенный выше код:
const multiplyByHeight = (width) => width * height;
$: area = multiplyByHeight(width);
Поскольку объявление $: area = … может “видеть” только width, оно не будет пересчитываться при изменении height. В результате код трудно рефакторить, а понимание тонкостей того, когда Svelte решает обновить те или иные значения, может стать довольно сложным после определенного уровня сложности.
В Svelte 5 появились руны $derived и $effect, которые вместо этого определяют зависимости своих выражений при их вычислении:
Как и $state, $derived и $effect также могут быть использованы в файлах .js и .ts.
Усиление сигнала
Как и любой другой фреймворк, мы пришли к пониманию того, что Knockout всегда был прав.
Реактивность Svelte 5 обеспечивается сигналами, которые, по сути, являются тем, чем занимался Knockout в 2010 году. Совсем недавно сигналы были популяризированы Solid и приняты множеством других фреймворков.
Однако у нас все немного по-другому. В Svelte 5 сигналы – это детали реализации, а не то, с чем вы взаимодействуете напрямую. Таким образом, мы не имеем тех же ограничений на дизайн API и можем максимально повысить эффективность и эргономичность. Например, мы избегаем проблем с сужением типов, возникающих при обращении к значениям через вызов функции, а при компиляции в режиме рендеринга на стороне сервера мы можем вообще отказаться от сигналов, поскольку на сервере они – не более чем накладные расходы.
Сигналы позволяют реализовать мелкозернистую реактивность, то есть, например, изменение значения в большом списке не обязательно должно приводить к аннулированию всех остальных членов списка. Таким образом, Svelte 5 работает невероятно быстро.
Впереди более простые времена
Руны – это добавочное свойство, но они делают устаревшими целую кучу существующих концепций:
разница между let на верхнем уровне компонента и в остальных местах
export let
$:, со всеми вытекающими отсюда странностями
разное поведение между
TypeScript и все что тебе нужно в разработке / Хабр | Веб-студия Nat.od.ua
TypeScript и все что тебе нужно в разработке / Хабр
Автор: Маслов Андрей, Front-end разработчик.
О статье
Эта статья создана для облегчения процесса изучения TypeScript с помощью практичных примеров. Более подробную информацию можно найти в документации или в дополнительных материалах.
Статья предназначена как для начинающих разработчиков, которые только начинают знакомиться с TypeScript, так и для опытных разработчиков, желающих углубить свои знания в этом языке. Здесь вы найдете краткое и информативное изложение ключевых аспектов TypeScript, которые могут быть полезными в повседневной разработке. Для вашего удобства, оглавление статьи содержит ссылки на конкретные темы TypeScript, так что вы можете быстро перейти к интересующей вас части материала.
НавигаторIntersection Types и Union TypesIntersection Types
В TS вы можете пересекать типы. Вы можете получить тип C способом пересечения типов А и В. Смотрите пример ниже:
type A = {
id: number
firstName: string
lastName: string
}
type B = {
id: number
height: number
weight: number
}
type C = A & B
//Итог пересечения типов A и B
type C = {
id: number
firstName: string
lastName: string
height: number
weight: number
}Union Types
Аналогично пересечению, вы можете выполнить и объединение типов, т.е создать аннотации несколько типов в текущей переменной. Смотрите пример ниже:
type A = number
type B = string
type C = A | B
//Итог объединения A и B
type C = number или string
const parseAmount = (val: C) => {
if (typeof val === ‘number’) {
return val
}
if (typeof val === ‘string’) {
return val.resplace(‘,’, ‘.’)
}
}Generic Types
Дженерики значительно расширяют возможности TypeScript в повседневном программировании, позволяя нам эффективно переиспользовать типы, избегая создания множества аналогичных “клонов”. Давайте рассмотрим это на практическом примере: создание типа, способного корректно обрабатывать ответы методов.
type FetchResponse
data: T
errorMessage: string
errorCode: number
}
type AuthDataRs = {
accessToken: string
refreshToken: string
}
const login = async (lg: string, ps: string): FetchResponse
const response = await fetch(…)
return response
}
//FetchResponse
//переиспользовать FetchResponse для различных запросов.
При необходимости можно расширять свой тип несколькими дженериками:
type FetchResponse
data: T
error: P
}
Так же вы можете назначать тип по умолчанию дженерику:
type FetchResponse
data: T
error: P
}
Если дженерику не назначен явный тип по умолчанию, то вам необходимо обязательно указывать тип при его использовании. В случае, если у дженерика есть дефолтное значение, передача типа может быть опциональной или даже вовсе не требоваться.
Utility Types
Это утилиты, которые предназначены для удобной работы, а именно генерации новых типов на основе других.
Awaited
Awaited
Утилита предназначена для ожидания в асинхронных операциях, например:
type A = Awaited
//type A -> numberPartial
Partial
Утилита предназначена для создания нового типа, где каждое свойство станет опциональным. Напомню, для того чтобы сделать свойство объекта опциональным, необходимо использовать знак “?”:
type A = {
id: number
name?: string //Опциональное свойство (необязательное)
}
Как работает Partial ?
type A = {
id: number
name: string
}
//Output
type B = {
id?: number //Опциональное свойство (необязательное)
name?: number //Опциональное свойство (необязательное)
}Required
Required
Утилита работает в точности наоборот как Partial. Свойства текущего типа делает строго обязательными.
type A = {
id?: number
name?: string
}
//Output
type B = {
id: number //Обязательное свойство
name: number //Обязательное свойство
}Readonly
Readonly
Утилиты преобразует все свойства типа, делает их недоступными для переназначения с использованием нового значения.
type A = {
id: number
name: string
}
const firstObj: A = { id: 0, name: ‘first’}
const secondObj: B = { id: 1, name: ‘second’}
firstObj.name=”first_1″ // it’s correct
secondObj.name=”second_2″ //Cannot assign to ‘name’ because it is a read-only property.
Если у вас есть необходимость сделать поле readonly только для определенного свойства объекта, то необходимо написать ключевое слово перед именем св-ва:
type A = {
readonly id: number
name: string
}Record
Record
Утилита предназначена для создания типа объекта, Record
enum CarNames {
AUDI = ‘audi’,
BMW = ‘bmw’
}
type CarInfo = {
color: string
price: number
}
type Cars = Record
//Output
type Cars = {
audi: CarInfo;
bmw: CarInfo;
}Pick
Pick
Утилита предназначена для создания нового типа из выбранных свойств объекта.
type A = {
id: number
name: string
}
//Output 1
type B = {
name: string
}
//Output 2
type B = {
id: number
name: string
}Omit
Omit
Утилита предназначена для создания типа из оставшихся (не исключенных) свойств объекта.
type A = {
id: number
name: string
}
//Output 1
type B = {
name: string
}
//Output 2
type B2 = {}Exclude
Exclude
Утилита создает тип, исключая свойства, которые уже присутствуют в двух разных типах. Он исключает из T все поля, которые можно назначить U.
type A = {
id: number
name: string
length: number
}
type B = {
id: number
color: string
depth: string
}
type C = Exclude
//Output
type C = {
name: string
length: number
}Extract
Extract
Создает тип, извлекая из T все члены объединения, которые можно назначить U.
type A = {
id: number
name: string
length: number
}
type B = {
id: number
name: string
color: string
depth: string
}
type C = Extract
//Output
type C = {
id: number
name: string
}ReturnType
ReturnType
Создает тип, состоящий из типа, возвращаемого функцией T.
type A = () => string
//Output
type B = string
Это одни из основных Utility Types, в материалах к статье я оставлю ссылку на документацию, где при желании вы сможете разобрать остальные утилиты для продвинутой работы с TS.
Conditional Types
В TypeScript есть возможность создавать типы в зависимости от передаваемого дженерика.
type ObjProps = {
id: number
name: string
}
type ExtendsObj
const obj1: ObjProps = {
id: 0,
name: ‘zero’
}
const obj2 = {
id: 1
}
type A = ExtendsObj
type B = ExtendsObj
Сопоставленные типы позволяют вам взять существующую модель и преобразовать каждое из ее свойств в новый тип.
type MapToNumber
: number
}
const obj = {id: 0, depth: ‘1005’}
type A = MapToNumber
//Output
type A = {
id: number
depth: number
}Type Guards
Если тип не определен или неизвестен, то на помощь разработчику приходит “защита типов”.
typeof
Самый простой способ обезопасить себя от ошибки, напрямую проверить тип при помощи оператора typeof (ранее в примерах вы могли видеть использование этого оператора, который возвращает тип переменной).
const fn = (val: number | string) => {
if (typeof val === ‘number’) {
return …
}
throw new Error(`Тип ${typeof val} не может быть обработан`)
}in
Еще один из способов защитить тип, использовать in, этот оператор проверяет присутствие свойства в объекте.
const obj = {
id: 1,
name: ‘first’
}
const bool1 = ‘name’ in obj //true
const bool2 = ‘foo’ in obj //falseinstanceof
Оператор экземпляра проверяет, появляется ли свойство прототипа конструктора где-нибудь в цепочке прототипов объекта
function C() {}
function D() {}
const o = new C();
o instanceof C //true
o instanceof D //falseis
Этот оператор указывает TypeScript какой тип присвоить переменной, если функция возвращает true. В примере ниже оператор is сужает тип у переменной foo (string | number) до string. Это определенная пользователем защита типа. Благодаря защите компилятор приводит тип до определенного внутри блока if.
interface FirstName {
firstName: string
}
interface FullName extends FirstName {
lastName: string
}
const isFirstName = (obj: any): obj is FirstName => {
return obj && typeof obj.firstName === “string”
}
const isFullName = (obj: any): obj is FullName => {
return isFirstName(obj) && typeof (obj as any).lastName === “string”;
}
const testFn = (objInfo: FirstName | FullName | number) => {
if (isFullName(objInfo)) {
console.log(‘Тип FullName’)
} else if (isFirstName(objInfo)) {
console.log(‘Тип FirstName’)
} else {
console.log(‘Тип не принадлежит FullName или FirstName’)
}
}
testFn({ firstName: ‘Andrey’ }) //Тип FirstName
testFn({ firstName: ‘Andrey’, lastName: ‘Maslov’ }) //Тип FullName
testFn(1) //Тип не принадлежит FullName или FirstNameЗаключение
Как видите, TypeScript – это мощный инструмент для разработки, который позволяет улучшить качество вашего кода, сделать его более надежным и легко поддерживаемым. В этом туториале мы рассмотрели приемы работы с TypeScript, над такими продвинутыми темами, например, как дженерики и type guards.
Не забывайте, что изучение TypeScript – это постоянный процесс, и чем больше вы практикуетесь, тем более уверенно будете использовать его в своих проектах.
Если у вас возникнут вопросы или потребуется дополнительная помощь, обращайтесь к официальной документации TypeScript или дополнительным материалам.
Материалы для изучения
Основы
Utility Types
Шпаргалка по TS в картинках