Elementary Geometric Reduction | Веб-студия Nat.od.ua
Elementary Geometric Reduction
Проблема
Если человек не знает математику на уровне высшей школы, то бывает очень трудно разобраться, что означает то или иное выражение, записанное в математической нотации.
Стандартное решение этой проблемы – изучение математики.
Есть прекрасные курсы, упрощающие эту задачу. Начиная с Khan Academy, и многие другие.
Однако всё равно процесс должен был бы занять годы, чтобы начать ориентироваться в этом уверенно.
Кроме того, даже при творческой подаче материала, базовый подход остается в целом прежним: есть математическая нотация, и, подобно музыкальным нотам, нужно выработать автоматический навык ее чтения.
И хочется посмотреть на проблему out of the box, и подумать, а нет ли возможности реализовать инструмент, который бы упрощал этот процесс и позволял сделать его комфортнее и быстрее.
Читать далее
Путь к Быстрому и Легковесному React / Хабр | Веб-студия Nat.od.ua
Путь к Быстрому и Легковесному React / Хабр
Я работаю фронтенд-разработчицей в IT-компании, и многие из моих проектов на протяжении долгого времени собирались с использованием Webpack. Настройка Webpack иногда бывала сложной, но в целом он справлялся с задачей сборки проектов. Однако в последнее время мои коллеги начали восторгаться новым инструментом – Vite. Они рассказывали о его легковесности, быстрой сборке и преимуществах для разработчиков React-приложений. В этой статье я поделюсь своим опытом миграции с Webpack и react-scripts на Vite. Я расскажу о причинах, по которым решила попробовать Vite, а также о том, с какими сложностями пришлось столкнуться и как они были решены.
Почему Vite? Легковесность и Быстрая Сборка
Одной из главных причин, по которым я решила попробовать Vite, была его легковесность и невероятная скорость сборки проекта. Vite разработан с учетом современных требований для разработки веб-приложений и, в отличие от Webpack, не требует предварительной сборки всех зависимостей перед запуском проекта. Это означает, что разработка проходит намного быстрее, так как Vite собирает только те файлы, которые действительно используются в процессе разработки.
Горячая Замена Модулей
Еще одним значимым преимуществом Vite является горячая замена модулей (HMR), которая позволяет вам видеть изменения в коде сразу же после сохранения файла, без необходимости перезагрузки всего приложения. Это значительно ускоряет процесс разработки и улучшает опыт разработчика.
Простая Настройка
Настройка Vite оказалась гораздо проще, чем Webpack. В большинстве случаев не требуется большое количество конфигурационных файлов и плагинов. Vite предоставляет интуитивно понятный файл vite.config.ts, который позволяет легко настраивать сборку приложения.
Сложности и Их Решение
После того как я решила дать шанс Vite, я столкнулась с рядом сложностей. Одной из первых сложностей, с которыми я столкнулась, было отсутствие отображения моих иконок FontAwesome. После нескольких часов поиска решения в интернете и экспериментов с настройками Vite, мне пришлось признать, что проблему остается нерешенной.
FontAwesome
Нюанс оказался связанным с тем, как Vite обрабатывает шрифты и иконки по умолчанию. Вместо того, чтобы использовать тег , который привычно использовался с FontAwesome, Vite рекомендует использовать компоненты FontAwesome. Вот как я решила эту проблему:
Установка пакета @fortawesome/react-fontawesome: Сначала я установила пакет @fortawesome/react-fontawesome, который предоставляет компоненты для отображения иконок FontAwesome в React-приложениях. Вы можете установить его с помощью npm или yarn:
Использование компонента
Импорт иконок: Для того чтобы использовать иконки FontAwesome внутри компонентов, я импортировала нужные иконки в файле, где они используются:
Продолжение разработки: После выполнения этих шагов, иконки FontAwesome стали отображаться корректно в моем приложении на Vite, и я могла продолжить разработку без дополнительных проблем.
Таким образом, решение проблемы с FontAwesome оказалось несложным, и использование компонентов FontAwesome стало хорошей практикой в моих проектах на Vite.
Загрузка Страницы
Еще одним интересным нюансом, с которой я столкнулась при миграции на Vite, была проблема с открытием фронтенд-страницы. После перехода на Vite, мой проект компилировался без ошибок, но сама страница не загружалась. После нескольких часов изучения конфигураций и поиска в интернете, я нашла решение, которое, казалось бы, простое, но могло быть упущено.
В реактовских проектах, файл index.html обычно располагается в папке public. Однако, при использовании Vite, вам следует поместить файл index.html в корень вашего проекта. Этот файл играет важную роль в настройке корневого пути для вашего приложения, и его расположение в корне необходимо для правильной работы Vite.
После перемещения файла index.html в корень проекта, проблема с загрузкой страницы была успешно решена, и мое приложение начало работать корректно.
Не забудьте проверить, что у вас нет других зависимостей, которые могут ссылаться на файл index.html в старом местоположении в папке public.
Прокси в Vite
В процессе миграции на Vite, я столкнулась с нюансом, связанным с настройкой прокси. В большинстве React-проектов, прокси обычно настраивается в файле package.json с использованием свойства proxy. Однако, при использовании Vite, у меня возникли сложности с этим подходом.
Vite предоставляет собой свой собственный механизм настройки прокси, который следует настраивать в конфигурационном файле vite.config.ts. Это может показаться непривычным для разработчиков, привыкших использовать proxy в package.json, но это важно учитывать при работе с Vite.
Для настройки прокси в Vite, вам нужно будет создать файл vite.config.ts, если его еще нет, и добавить конфигурацию прокси внутри этого файла. Пример конфигурации:
Заключение: Почему Vite – Лучший Выбор для React
Миграция с Webpack и react-scripts на Vite оказалась для меня увлекательным и продуктивным опытом. В итоге, я пришла к выводу, что Vite – это именно тот инструмент, который может значительно улучшить процесс разработки React-приложений.
Быстрота и Эффективность
Самым первым преимуществом Vite, которое меня впечатлило, была его невероятная скорость сборки проекта. Способность Vite компилировать только необходимые модули и обеспечивать горячую замену модулей значительно ускоряет разработку и обновление кода.
Легковесность и Простота
Настройка Vite оказалась намного проще и понятнее, чем Webpack. Отсутствие необходимости в большом количестве конфигурационных файлов и интуитивно понятный vite.config.js делают процесс сборки проекта более простым и доступным для разработчиков.
Экосистема Плагинов
Vite имеет обширную экосистему плагинов, которые могут быть легко интегрированы в проект. Это позволяет разработчикам расширить функциональность Vite в соответствии с их потребностями.
В заключение, переход на Vite оказался удачным шагом для моих проектов. Он не только улучшил производительность и скорость разработки, но и сделал процесс настройки и сборки проекта более простым.
Как типизировать Vuex Store / Хабр | Веб-студия Nat.od.ua
Как типизировать Vuex Store / Хабр
Всем привет!
В этой статье мы поймем, нужно ли вам типизировать Vuex Store или нет, и если вы достаточно отчаянны, поймем, как его типизировать, чтобы не погибнуть.
А нужно ли вам это ?
Можно ненадо
Тут я бы не советовал выбирать именно Vuex по нескольким причинам:
Vuex больше не будет апдейтится – на главной Vuex это написано – тык, теперь дефолтный State Manager – Pinia. По количеству коммитов на скрине ниже, можно сказать, что пациент мертв)))
Pinia is now the new default
The official state management library for Vue has changed to Pinia. Pinia has almost the exact same or enhanced API as Vuex 5, described in Vuex 5 RFC. You could simply consider Pinia as Vuex 5 with a different name. Pinia also works with Vue 2.x as well.
Vuex почти полностью написан на JS, а что написано на TS, больше похоже на AnyScript. Вот сравнение репозиториев Vuex и Pinia, как доказательство(тут видно, что primary language у Pinia – TS, Vuex – JS).
Vuex грустно в его репо никто не коммитит
Если после этого вы все еще хотите типизировать Vuex, то погнали
Начинаем типизацию
Пора
Как пример, мы будем писать модуль для типизации Todo приложения.
Типы для нашего TodoModule
Сделаем алиасы для удобного манипулирования типами внутри файла с типами модуля, далее нам это понадобиться.
type State = TodoState;
type Mutations = TodoMutations;
type Getters = TodoGetters;
type Actions = TodoActions;
Тут все просто, мы просто создаем интерфейс и пишем туда наши свойства:
state.ts
export interface TodoState {
todos: {
name: string;
completed: boolean;
}[];
}
Тут также ничего сложного, мы просто описываем наши Mutations как функции в которые первым параметром передаются State, а вторым опционально передаётся payload:
export interface TodoMutations {
addTodo(state: State, payload: State): void;
deleteTodo(state: State, payload: State): void;
setTodos(state: State, payload: State): void;
}
Actions также типизируются как функции с первым параметром, ActionContext({ dispatch, commit, state, getters, rootState, rootGetters }) и вторым параметром опциональным payload.
Здесь я буду использовать типизацию ActionContext из самого пакета Vuex, выглядит она вот так:
Vuex Action Context
dispatch: Dispatch;
commit: Commit;
state: S;
getters: any;
rootState: R;
rootGetters: any;
}
Если вам вдруг недостаточно этой типизации, например вам нужно типизировать getters или rootGeters, то можно сделать самому интерфейс:
Custom Action Context
dispatch: YourDispatchType;
commit: YourCommitType;
state: YourStateType;
getters: YourGettersType;
rootState: YourRootStateType;
rootGetters: YourRootGettersType;
}
Полученный TodoActions
import { ActionContext } from ‘vuex’;
import { RootState } from ‘./store’;
type MyActionContext = ActionContext
export interface TodoActions {
getTodos({ commit }: MyActionContext): Promise
addTodo({ commit }: MyActionContext, payload: State): Promise
deleteTodo({ commit }: MyActionContext, payload: State): Promise
}
Типизировать Getters чуть сложнее, они типизируются как функции возвращающие какое-то значение, но есть нюансы:
В случае, если у вас в Getters не передается никакой payload, сигнатура выглядит следующим образом
getterName(state: State, getters: Getters, rootState: RootState): ReturnType;
В случае, если в Getters передается payload, сигнатура выглядит вот так
getterName(state: State, getters: Getters, rootState: RootState): (parameters: parametersType) => ReturnType;
Мой полученный TodoGetters
export interface TodoGetters {
getTodosByReadiness(state: State): (isCompleted: boolean) => State;
}
Тут получается очень страшная конструкция, которая обогащает базовый тип модуля Vuex Store, по сути мы просто типизируем Mutations, Actions и Getters с помощью полученных нами типов(самое главное тут это переопределение ключей у commit, dispatch, getters, мы сделали так, чтобы они тоже были типизированы)
import { CommitOptions, DispatchOptions, Store as VuexStore } from ‘vuex’;
export type TodoModule = Omit
‘getters’ | ‘commit’ | ‘dispatch’> & {
commit
key: K,
payload?: P,
options?: CommitOptions,
): ReturnType
} & {
dispatch
key: K,
payload?: Parameters
options?: DispatchOptions,
): ReturnType
} & {
getters: {
: ReturnType
}
}
Итого получаем следующий файл:
types/todo/store.ts
import { RootState } from ‘./store’;
type State = TodoState;
type Mutations = TodoMutations;
type Getters = TodoGetters;
type Actions = TodoActions;
export interface TodoState {
todos: {
name: string;
completed: boolean;
}[];
}
export interface TodoGetters {
getTodosByReadiness(state: State): (isCompleted: boolean) => State;
}
export interface TodoMutations {
addTodo(state: State, payload: State): void;
deleteTodo(state: State, payload: State): void;
setTodos(state: State, payload: State): void;
}
type MyActionContext = ActionContext
export interface TodoActions {
getTodos({ commit }: MyActionContext): Promise
addTodo({ commit }: MyActionContext, payload: State): Promise
deleteTodo({ commit }: MyActionContext, payload: State): Promise
}
export type TodoModule = Omit
‘getters’ | ‘commit’ | ‘dispatch’> & {
commit
key: K,
payload?: P,
options?: CommitOptions,
): ReturnType
} & {
dispatch
key: K,
payload?: Parameters
options?: DispatchOptions,
): ReturnType
} & {
getters: {
: ReturnType
}
}
Приступим к имплементации наших интерфейсовstore/modules/todo.ts
import {
TodoActions as Actions,
TodoGetters as Getters,
TodoMutations as Mutations,
TodoState as State,
} from ‘@/types/todo/store’;
// Типы из самого Vuex для совместимости
import { ActionTree, GetterTree, Module, MutationTree } from ‘vuex’;
import { RootState } from ‘@/types/store’;
// Типизируем State
const state: () => State = () => ({
todos: [],
});
// Типизируем Getter с помощью нашего интерфейса + обертки из Vuex
const getters: GetterTree
getTodosByReadiness(state) => (isCompleted) => state.todos.filter((todo) => todo.completed === isCompleted);
};
// Типизируем Mutations с помощью нашего типа + обертки из Vuex
const mutations: MutationTree
addTodo(state, todo) {
state.todos.unshift(todo);
}
deleteTodo(state, todo) {
state.todos = state.todos.filter((t) => t.name !== todo.name)
}
setTodos(state, todos) {
state.todos = todos;
}
};
// Типизируем Actions с помощью нашего типа + обертки из Vuex
const actions: ActionTree
async getTodos({ commit }) {
const todos = await getTodos();
commit(‘setTodos’, todos);
}
async addTodo({ commit }, todo) {
await addTodo(todo);
commit(‘addTodo’, todo);
}
async deleteTodo({ commit }, todo) {
await deleteTodo(todo);
commit(‘deleteTodo’, todo);
}
};
// Экспортим модуль с типами
const todo: Module
state,
mutations,
getters,
actions,
};
export default todo;
Разбираемся, что выше произошло:
Мы типизировали State как () => State, функция которая возвращает State, все понятно.
Мы типизировали Mutations, Getters, Actions как intersection между нашим типом и типом который предоставляет Vuex из коробки, это делается для того, чтобы мы могли потом прокинуть наши mutations, getters, actions в Module и не получить ошибок.
Экспортировали наш типизированный модуль.
Финальный штрих
Финал близок
Для начала нужно подготовить еще несколько общих типов, для того чтобы все заработало.
types/store.ts
import { TodoState, TodoModule } from ‘@/types/todo/store’;
export interface StateProps {
// Сюда нужно будет прописывать все ваши стейт
state: {
todo: TodoState;
}
}
export type RootState = StateProps;
// Сюда нужно будет добавлять все ваши модули через &
export type StoreType = StateProps & TodoModule;
А теперь объясню, что здесь происходит:
StateProps – Все наши State в одном месте
Из него мы будем брать RootState
Мы будем использовать этот интерфейс для того, чтобы использовать его в нашем типе для Store(он итак должен типизироваться, но у меня по какой-то причине не завелось, поэтому я сделал вот такой костыль)
RootState – Тут понятно
StoreType – Типизация всего нашего стора с State, Mutations, Actions, Getters
Применим это все в нашем Store
Тут мы даем тип инстансу store и хуку useStore, теперь импортируя и используя их, вы получаете типизированный Store.
import { createStore, useStore as VuexStore } from ‘vuex’;
import { todo } from ‘@/store/modules/todo’;
import { StoreType } from ‘@/types/store’;
const store: StoreType = createStore({
modules: {
todo
},
});
export function useStore(): StoreType {
return VuexStore() as StoreType;
}
export default store;
Чеклист одного успешного StoreПроверяй
Написал типы для своего Store
Написал имплементацию этих типов
Добавил в StateProps и StoreType нужны типы
Типизировал сам Store
Используешь Store/useStore не из Vuex, а из файла, где типизировал Store
Кайфанул от типизации
Успешный успех
Если статья показалась вам интересной, то у меня есть Телеграм Канал, где я пишу про новые технологии во фронте, делюсь хорошими книжками и интересными статьями других авторов.
Как коридорное исследование помогло обновить каунтеры тредов в мессенджере | Веб-студия Nat.od.ua
Как коридорное исследование помогло обновить каунтеры тредов в мессенджере
Треды — это комментарии под сообщениями. Они помогают сделать общение структурным: вместо потока идущих подряд сообщений можно создавать тематические ветки обсуждений. Но как пользователю сориентироваться, в каких тредах появились новые комментарии, а в каких нет? Сначала мы использовали иконку-каунтер, которая меняла цвет в зависимости от новых событий, но потом стало понятно, что ее нужно менять.
Привет! Меня зовут Олег Борискин, я продакт-менеджер в команде We.Teams. Мы разрабатываем корпоративный мессенджер внутри Webinar Group. В статье расскажу, как исследование на небольшой группе респондентов помогло переосмыслить отображение счетчика новых комментариев в треде.
Как работал счетчик сообщений в треде раньше
Когда мы начали разработку, то сразу заложили в мессенджер возможность оставлять комментарии под сообщениями. Иконка треда выглядела как счетчик с количеством всех комментариев.
За обновлениями помогал следить раздел «Обсуждения», который агрегировал все комментарии в хронологическом порядке. Такое решение позволяло не просматривать чаты в поисках обновлений, а обращаться к одной вкладке и отвечать оттуда.
We.Teams разрабатывается поэтапно: сначала мы сделали треды, а затем начали прорабатывать реакции. В этот момент поняли, что реакции конфликтуют с тредами: и там, и там была схожая форма компонентов. Нужно было отказаться от прошлой визуализации новых комментариев и придумать новую.
Из-за того что мы решили отказаться от таблетки, нам критически было важно донести до пользователя факт наличия нового комментария. Раньше таблетка подсвечивалась фиолетовым, но если ее убрать, то становилось непонятно, как подсвечивать: точкой, цветом, новой строкой с состоянием?
Это всё стало поводом для обсуждений, и мы накидали вариантов, которые нужно было протестировать. Когда решение не очевидно, а значимых аргументов в пользу единственного варианта ни у кого нет, то самый лучший выход — это провести исследование.
Создаем прототипы и зовем людей на тест
Мы решили устроить коридорный тест: собрать небольшую группу людей из компании и попросить их выбрать наиболее информативный макет. Метод простой, но эффективный для быстрой проверки гипотезы и выбора одного варианта из множества.
Мы пригласили респондентов из разных отделов компании: аккаунта, дизайнера, сейлза, разработчика и лида. Мы специально взяли разных специалистов — так модель поведения разработчика в мессенджере будет сильно отличаться от сейлза: последнего будут заметно чаще тегать. В итоге маленькая выборка позволяет диверсифицировать опыт по каждой группе. Да, для продактов и UX-исследований это, возможно, очевидный поинт, но мне кажется, лишний раз стоило его упомянуть 🙂
Задание для респондентов сформулировали так: посмотрите ленту и определите, где нужен ваш ответ. Ориентируясь только на интерфейс, людям нужно было понять, на каком сообщении сфокусироваться.
Как выглядел макет для тестирования
В конце исследования, кроме вопросов в стиле «всё ли было понятно?», мы ввели еще два: оценки эстетики и удобства. Подобные опросы помогают посмотреть на задачу шире и получить общий фидбэк.
В результате лидером по удобству и восприятию оказался вариант с общим количеством комментариев и счетчиком новых.
Исследование не только помогло понять, как лучше отображать каунтер, но и позволило взглянуть на проблему под другим углом.
Восприятие цвета сильно зависит не только от монитора, но и человека. На каких-то устройствах он был слишком тусклым, а люди по-разному воспринимали оттенок цвета. Поэтому ориентироваться только на цвет при уведомлении о новых сообщениях оказалось недостаточно.
Подсветка перегружает интерфейс. Фоновая цветная подложка помогала выделить каунтер, и многим респондентам показалась заметной, но на практике создавала визуальный шум. Если в ленте чата будет десяток таких сообщений, то они будут выглядеть громоздко.
Коридорное исследование помогло нам сразу понять, какая визуализация будет предпочтительней для пользователей. Естественно, когда мессенджер выйдет в публичный доступ, мы будем собирать обратную связь дальше и смотреть. Но зато на этом этапе нам уже удалось сделать пусть и небольшое, но важное изменение, которое улучшит пользовательский опыт от использования мессенджера.
Как теперь работает новый каунтер
Мы оставили логику работы старого каунтера и добавили к нему новый статус — количество непрочитанных комментариев. Если комментариев нет, то показываем только общее число.
Мы дополнили отображение уголком, который позволяет визуально разделять треды и сообщения. Еще этот элемент показывает, что перед пользователем не просто текст, а иерархический элемент интерфейса, по которому можно кликнуть и открыть тред.
Как я уже рассказывал в посте про логику уведомлений, мы продолжаем следовать курсу показывать только то, что относится к пользователю. Мы подсвечиваем новые комментарии только тогда, когда произошло событие, чтобы не засорять ленту рядами фиолетовых каунтеров. Например, в чате есть сотня новых сообщений — подсвечиваться будут только те, где произошло важное для пользователя событие: его упомянули, написали под его тредом или он ранее сам написал в треде.
Кнопка отключения уведомления поможет отписаться от треда, если человек больше не хочет участвовать в обсуждении. Например, он сообщил, что придет на корпоратив и дальше его не интересует обсуждение деталей 🙂
Также мы изменил каунтер для раздела «Обсуждения»: теперь он показывает не общее количество комментариев, а число обсуждений, где произошли события. Так становится проще следить за обсуждениями: пользователь теперь видит число диалогов, а не сообщений. При переходе открывается список диалогов с обновленными каунтерами под сообщениями, что тоже вносит больше порядка в общение.
Напоследок
Если вы в команде не знаете, как и что реализовать, то вы проводите исследования и слушаете пользователей. Как было у нас: столкнулись с проблемой, родилась гипотеза, а тест помог не только выбрать нужный вариант, но и получит ответ, почему другие макеты были не очень удобными.
Поэтому важно ориентироваться не только на собственную экспертность, но и мнение пользователей. Даже такая небольшая вещь, как каунтер, может быть важным элементом интерфейса: представьте человека, который каждый день следит за десятком тредов, и плохая информативность начинает вызывать у него раздражение. Такие небольшие исследования помогают проработать задачу и получить фидбэк до того, как это попадет в прод.
делать то, что нужно, но лишнего не делать / Хабр | Веб-студия Nat.od.ua
делать то, что нужно, но лишнего не делать / Хабр
Кучу времени можно сэкономить если:
Написать тесты на функциональность, которая суперважна или в будущем будет меняться с большой вероятностью.
Не писать тесты на функциональность, которая меняться никогда не будет и не особо критична при поломке.
Тщательно проработать важные аспекты нового проекта, собрав нужных людей на встречу(и), написав понятно задачи.
Не прорабатывать тщательно то, что допустимо придумать на ходу / не особо важно / можно спросить.
Сделать и сверстать красивый удобный дизайн там, где им пользуются тысячи клиентов.
Сделать на отъ*бись там, где раз в год один сотрудник вашей же компании нажимает пару кнопок.
Написать документацию на критически важные узлы и важное взаимодействие с внешними компонентами.
Не писать документацию там, где всё и так очевидно или неважно или почти умерло вообще.
Выделять слои бизнес-логики в сложных программах.
Не городить 10 слоёв абстракций и супергибкий код в небольшой эффективной программе, которая не будет особо меняться в будущем.
Проверять на код ревью важные вещи.
Не докапываться до стилистических мелочей и вкусовщины, а некоторые очевидные MR(PR) вообще не проводить через код ревью.
Тщательно запланировать работы перед важным дедлайном.
Не тратить (много) времени на планирование, если нет дедлайна или нет взаимодействия с другими командами.
К сожалению, люди часто ударяются во что-то одно, или перфекционизм, или вселенский пофигизм. Или 100% тестирование в пет-проекте или катим работу с деньгами без тестирования прямо в прод. Это какое-то когнитивное искажение, человеку проще выбрать один шаблон, и всё делать по нему, унифицируя всё и вся, все проекты и задачи.
Я призываю всегда думать и взвешивать вероятности. Быть осознанным. Ключевой вопрос “А что будет, если не делать?”. Это точно окупится. Всегда всё зависит от деталей, от ситуации, от проекта. Унифицированный подход “один размер подходит всем” неэффективен (за исключением редких случаев).
Короче, нормально делай — нормально будет
Если хотите больше новостей и полезной информации о разработке, подписывайтесь на мой tg-канал Cross Join
как оформить спецификацию, чтобы не запутаться самому и не выбесить коллег / Хабр | Веб-студия 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) сместило акцент на защиту учётных записей пользователей с помощью дополнительных уровней проверки, в результате чего пароли стали менее важны для безопасности.
В современном мире всё большее распространение получают облачные сервисы, где большинство важных данных хранится удалённо. Простой брутфорс малоэффективен для проникновения в такие системы, поэтому злоумышленники, как правило, используют уязвимости или социальную инженерию.
Спустя четверть века люди до сих пор полагаются на пароли как основной метод защиты компьютерной информации. С каждым годом растёт их сложность (энтропия), вводятся более сложные методы хэширования, но сами текстовые пароли/фразы остаются.