Pull to refresh

Функциональная спецификация интерфейса: что это, зачем нужна, как её писать

Reading time15 min
Views18K

Функциональная спецификация вместе с прототипом рассказывает, из каких элементов состоит и как работает интерфейс системы. Она описывает то, что трудозатратно, невозможно или бессмысленно показывать в прототипе.

С её помощью можно улучшить предлагаемые решения, ответить на вопросы разработчиков и других участников проекта, зафиксировать договорённости на бумаге.

В этой статье я рассказал, как она помогает сделать продукт лучше, что можно включить в спецификацию, как её структурировать, что писать об отдельных элементах интерфейса и что уже выходит за рамки подобного документа.

Надеюсь, это поможет вам в написании спецификаций для своих интерфейсов.

Оглавление

1. Что такое функциональная спецификация

2. Зачем нужна

3. Как писать

3.1. Когда к ней приступать

3.2. Состав

3.3. Структура

3.4. Описание элементов

3.5. Описание страниц

4. Примечания и ссылка на видео

Что такое функциональная спецификация

Функциональная спецификация интерфейса — один из артефактов, который полезно создавать при проектировании интерфейсов. Я её делаю после прототипа, чтобы уточнить показанные в нём решения и ответить на будущие вопросы разработчиков.

Итоговый документ работает в паре с прототипом и рассказывает, из каких элементов состоит и как работает интерфейс системы. В нём можно описать то, что трудозатратно или невозможно визуализировать в прототипе, и то, что на картинках человек скорее всего не заметит.

Например:

1. Приложение сигнализации, список пользователей
1. Приложение сигнализации, список пользователей

Разработчики спросят, как упорядочен список пользователей? На картинке ответа нет. Я решил, что упорядочены они по дате и времени подключения, поэтому в спецификации надо написать:

  1. Пользователи упорядочены по дате и времени регистрации на объекте в прямом хронологическом порядке.

  2. Доверенные лица упорядочены по дате и времени добавления в прямом хронологическом порядке.

2. Приложение сигнализации, настройка тегов местоположения
2. Приложение сигнализации, настройка тегов местоположения

На картинке со списком тегов — реалистичные данные. Из них следует, что список упорядочен в прямом алфавитном порядке. Но разработчики могут не обратить на это внимания. И вообще не факт, что подобную информацию они станут искать в прототипе. Значит, в спецификации стоит написать:

  1. Теги упорядочены в прямом алфавитном порядке.

Функциональная спецификация интерфейса — не техническое задание на создание продукта. Она описывает только логику работы отдельных элементов интерфейса и их совокупностей (страниц, экранов). Техническое задание может содержать важные характеристики продукта: производительность, на каких устройствах и операционных системах он должен работать без нареканий, требования к вёрстке и так далее.

3. Приложение сигнализации, установка пинкода на вход
3. Приложение сигнализации, установка пинкода на вход

В приложении можно управлять сигнализацией, поэтому вход в него полезно защитить пинкодом. Это обязательно, если пользовательский телефон сам пинкодом не защищён (раньше такое часто встречалось). А если защищён, отображается кнопка «Не устанавливать код на вход», и шаг установки пинкода не обязателен. Эта логика может быть описана в спецификации:

  1. Установка пинкода на вход в приложение происходит после регистрации пользователя на объекте, если пользователь приложения не пропустил этот шаг или не установил пинкод ранее.

  2. Если телефон не защищён пинкодом, пользователь не может пропустить этот шаг, кнопка «Не устанавливать код на вход» не отображается.

4. Приложение сигнализации, меню со списком объектов
4. Приложение сигнализации, меню со списком объектов

Пользователь может зарегистрироваться на нескольких объектах, тогда в приложении появится список, чтобы переключаться между ними. От названий объектов в списке отображаются только первые буквы: «Квартира» → «К», «Дача» → «Д», «Гараж» → «Г». А от названий, начинающихся одинаково, — буквы с порядковыми номерами: «К1», «К2» и «К3».

Сложно с помощью одних лишь картинок передать это решение и ответить на вопрос: что будет с порядковыми номерами, когда пользователь отключится от объекта, обозначенного «К1»? Возможно, обозначения «К2» и «К3» стоит сохранить за оставшимися объектами, так как человек мог к ним привыкнуть. В спецификации это можно описать:

  1. Если у пользователя приложения несколько объектов с названиями на одну и ту же букву, отображаются буквы и порядковые номера. Номера присваиваются по мере регистрации пользователя на этих объектах. Например, «К1», «К2» и «К3» — это объекты, названия которых начинаются с буквы «К». Сначала пользователь зарегистрировался на «К1».

  2. Если пользователь отключается от «К1», обновлять порядковые номера не надо, чтобы за оставшимися объектами сохранились привычные пользователю обозначения «К2» и «К3».

Кстати, на этом примере можно проиллюстрировать два полезных приёма: 1) дополнять тезисы примерами, чтобы было понятнее, 2) кратко объяснять не самые очевидные решения. Об этом стоило написать в разделе «Как писать функциональную спецификацию», но здесь уж очень удобный пример подвернулся.

К оглавлению

Зачем нужна функциональная спецификация

1. Донести решения, которые не видны в прототипе.

2. Стать источником ответов на возможные вопросы разработчиков, тестировщиков, менеджеров и других людей, которые будут работать с прототипом. Без такого источника они будут спрашивать дизайнера и откладывать задачи, пока ответов нет. Или придумывать свои ответы и делать как-нибудь (и потом, в лучшем случае, переделывать). Дизайнер может уйти из компании, а в заказной разработке — сдать свой этап работ и забыть детали проекта или просто перестать отвечать на вопросы.

Спецификация нужна при разработке любых более-менее сложных интерфейсов. Полезной она будет даже для лендинга, если на нём есть калькулятор, конфигуратор или форма заказа.

3. Стать частью договора. В отличие от интерактивного прототипа спецификацию легко распечатать и подписать. Фиксировать договорённости полезно не только с внешними контрагентами, но и с собственными коллегами. Внутри команды без такого договора тоже иногда бывает тяжко. Особенно удобно, если можно видеть, кто прочитал документ и задал вопросы.

4. Проверить свои решения ещё раз. Разные артефакты проектирования можно сравнить с разным размером ячеек в сите, с помощью которого просеиваются проектные решения. Прототип — крупная ячейка, выявляющая большие недочёты в логике работы проектируемой системы. Спецификация — мелкая ячейка, помогающая найти недочёты небольшие.

Примеры доработки решений, показанных в прототипе:

5. Приложение сигнализации, вход
5. Приложение сигнализации, вход

Чтобы войти в приложение, некоторым пользователям приходится вводить пинкод. При описании кнопки «Войти» я отвечаю на вопросы: надо ли её блокировать по умолчанию; как отреагирует система на нажатие, если пинкод не введён? При этом может появиться мысль: зачем нужна кнопка, если пускать в приложение можно сразу после ввода корректного пинкода? Стоит убрать кнопку и описать это поведение в спецификации.

6. Приложение сигнализации, подтверждение номера телефона
6. Приложение сигнализации, подтверждение номера телефона

Пользователь подтверждает номер телефона, который он указал на предыдущем шаге. Описывая абзац с номером телефона, я вспоминаю, зачем вообще решил его показывать? Чтобы можно было проверить, нет ли ошибки в номере, если смс долго не приходит. Может возникнуть вопрос: а если номер неправильный, как это исправить? Нужна возможность изменить номер или вернуться на предыдущий шаг.

7. Приложение сигнализации, пустой список пользователей и доверенных лиц
7. Приложение сигнализации, пустой список пользователей и доверенных лиц

Я показал состояние с пустым списком пользователей на конкретном объекте. Пересматривая юзерфлоу (user flow) первоначальной настройки сигнализации, я понимаю, что главный пользователь появляется ещё до завершения настройки нового объекта. Значит, он уже должен быть в этом списке. Надо исправить.

8. Приложение сигнализации, настройка уведомлений
8. Приложение сигнализации, настройка уведомлений

Пользователь указывает, как хотел бы узнавать о сработавшей сигнализации: с помощью пуша, смс, имейла или всеми возможными способами. Прорабатывая уведомления по электронной почте, разработчики спросят, на какой адрес отправлять письмо? При регистрации пользователь вводит только номер телефона, значит, при выборе этого способа оповещения должно появляться поле для ввода адреса почты. Плюс, адрес надо ещё подтвердить, а до этого уведомление по электронной почте работать не будет (надо показать ещё одно состояние).

К оглавлению

Как писать функциональную спецификацию

Когда к ней приступать

Я начинаю писать спецификацию после появления финальной версии прототипа. На этапе прототипирования видение продукта может сильно меняться. И если в прототипе поменять всё относительно просто, то переписывать текст уже не так легко. Части экранов вообще может не оказаться в новой итерации прототипа — есть опасность стереть строк больше, чем выдал. В заказной разработке даже оценивать стоимость написания спецификации лучше после создания прототипа.

Стоит учитывать, что после прототипа появятся дизайн-макеты, которые конкретизируют дизайн. Например, количество превьюшек в галерее. Прототип покажет их количество приблизительно, так как оно зависит от системы отступов, конкретных размеров картинок и самой галереи, которые будут определены уже в макетах.

Если основная задача спецификации — ещё раз проверить и улучшить свои решения, можно написать что-то вроде «Кнопки для прокрутки списка превью отображаются, если изображений в галерее больше N (количество определяется на этапе дизайна)». Если главное — договориться и подготовить проект к разработке, спецификацию придётся обновить после создания дизайн-макетов. Или можно отложить её написание до появления финальных макетов.

С другой стороны, одновременно с прототипированием в спецификации можно фиксировать отдельные решения (чтобы не вспоминать потом) и записывать открытые вопросы.

К оглавлению

Состав

Базовый состав спецификации:

  • Титульный лист.

  • Оглавление.

  • Описания типовых элементов интерфейса:

    • Для продукта в целом.

    • Для его разделов или модулей.

  • Описания отдельных страниц (экранов, блоков на длинных страницах). Для каждой страницы:

    • Её работа в целом.

    • Состав и поведение её элементов.

    • Модальные окна, сообщения об ошибках, особые случаи.

Выделение типовых элементов позволяет не дублировать описания одних и тех же элементов на разных страницах. Типовыми для продукта в целом бывают: шапка, главное меню, подвал, поле поиска, форма подписки на рассылку, лайтбокс просмотра галереи, капча, подсказка и так далее. Для отдельного модуля вроде новостного раздела: меню раздела, блок «Самые популярные новости».

Можно добавить:

  • Введение и общее описание продукта.

  • Описания основных сущностей продукта и определения терминов из предметной области. Например, для конфигуратора одежды, который появится в примерах ниже: нанесение, область нанесения.

  • Определения технических терминов из спецификации. Например: контрол, лайтбокс, алерт, внешняя часть системы.

  • Структуры конкретных разделов или модулей продукта.

  • При описании отдельной страницы:

    • Зачем она вообще нужна, какую задачу решает. Даже краткое описание в 1–2 предложения может оказаться очень полезным.

    • Изображение её основного состояния.

    • Изображения всех её состояний.

Межэкранную логику в спецификации лучше не описывать. Для этого больше подходят сценарии и, если логика разветвлённая, диаграммы юзерфлоу.

Что добавлять в спецификацию, зависит от того, кто и как будет ей пользоваться, и готов ли дизайнер такое содержимое подготовить. Документ с изображениями лучше решает задачу «Стать частью договора» и позволяет ознакомиться с проектом, не открывая прототипа. Описание продукта в целом, его основных сущностей и смысла отдельных страниц упрощает подключение новых людей к работе над продуктом. Словарь терминов помогает всем говорить на одном языке.

Идеально, если все состояния прототипа показаны в спецификации картинками. Можно не перелинковывать её с прототипом, и читателям не придётся изучать два артефакта параллельно. Но это трудоёмко, и без интерактивного прототипа всё равно не обойтись — сложнее оценивать удобство интерфейса.

Можно писать спецификацию в прототипе (в Акшуре или Фигме), но работать с текстом в подобных средах сложнее, чем в текстовом редакторе. И нельзя просто так взять и распечатать её.

Если спецификация работает в паре с прототипом, важно не забыть сослаться на него во введении или на титульном листе.

Также на титульном листе можно разместить:

  • Название проекта.

  • Информацию об авторах.

  • Версию документа и дату последней редакции.

  • Список предыдущих версий с кратким описанием изменений.

К оглавлению

Структура

9. Конфигуратор одежды, структура спецификации
9. Конфигуратор одежды, структура спецификации

На картинке — структура самой базовой спецификации для конфигуратора одежды, разделённого на 6 этапов. В первом разделе описаны типовые элементы, которых совсем немного. В остальных разделах — этапы и отдельные шаги на этих этапах.

Сейчас я бы убрал описания шагов «Выбор подтипа изделия» и «Сообщение об оформленном заказе» в подразделы, чтобы разделы спецификации совпадали с видимыми в интерфейсе этапами конфигуратора. Объём информации позволяет так сделать.

10. Конфигуратор одежды, список этапов в интерфейсе
10. Конфигуратор одежды, список этапов в интерфейсе

Но я не стал переделывать пример: 1) артефакты редко бывают идеальными, 2) не хотел отступать от изначального содержимого доклада, на котором основывается эта статья, 3) нет какой-то единственно верной структуры спецификации.

Я придерживаюсь принципа: если появляются заголовки пятого уровня, возможно, продукт слишком большой и отдельные его части стоит описывать в отдельных документах. Либо спецификация пытается соответствовать структуре продукта. Даже если осуществимо (дерево может быть очень глубоким), это не даёт особых преимуществ при чтении спецификации.

11. Фрагмент структуры спецификации с описанием части сайта для неавторизованных пользователей
11. Фрагмент структуры спецификации с описанием части сайта для неавторизованных пользователей

Описание типовых элементов интерфейса, которые встречаются только в конкретном модуле (вроде части сайта для неавторизованного пользователя), можно разместить в разделе спецификации, посвящённом этому модулю, — как на картинке. Либо все типовые элементы, встречающиеся по всему продукту и в отдельных модулях, можно описать в одном разделе, посвящённом типовым элементам. Выбор зависит от структуры продукта, количества типовых элементов, их распределения по модулям продукта и личных предпочтений дизайнера (тоже немаловажный фактор).

12. Конфигуратор одежды, описание шага выбора типа изделия
12. Конфигуратор одежды, описание шага выбора типа изделия
13. Конфигуратор одежды, описание типового элемента
13. Конфигуратор одежды, описание типового элемента

Как я писал выше, можно сначала описать типовой элемент, а затем ссылаться на него при описании страниц, на которых он встречается. На конкретной странице часть его свойств можно переопределить или дополнить. Например, можно указать, что на странице с поисковой выдачей поле поиска будет по умолчанию заполнено, или добавить текст конкретной подсказки, никак не касаясь типовой логики её отображения.

Некоторые типовые элементы на странице можно даже не упоминать. Например, в описании списка шагов конфигуратора можно указать, что он есть на всех страницах конфигуратора, если не указано обратное.

Заголовки и все абзацы стоит нумеровать, чтобы можно было сослаться на подраздел (например, на описание компонента в §1.1) или обсудить конкретный тезис (информацию о типе изделия в §2, пункте 2.d).

Дополнение Марины Пустовит: Вигерс приводит классный способ нумерации. Смысл в том, что цифры не очень информативны. В многоуровневом документе номер параграфа 4.6.2.1.7 не помогает читателю понять, где в документе он находится и о чём там речь. Вместо этого можно нумеровать словами, а также комбинировать слова и цифры, например: «Слово.Слово.Слово.1.2».

Сам я так не делал, но раз Вигерс советует, а Марина практикует, идея стоит упоминания.

К оглавлению

Описание элементов

Чтобы описать страницу (экран, блок на длинной странице), для начала можно выписать, какие элементы интерфейса на ней есть, и рассмотреть их по отдельности.

Полезные вопросы для описания любого элемента интерфейса:

  • Когда не отображается?

  • Из чего состоит?

  • Какие составные части могут отсутствовать или быть неактивными и почему?

  • Как пользователь может с ним взаимодействовать. Что при этом происходит?

  • В каких состояниях элемент может находиться?

  • Как при наведении на него меняется курсор?

Например:

В новостной ленте каждая новость состоит из заголовка, текста, даты-времени и картинки. Если редактор не нашёл подходящего изображения, будет отображаться картинка-заглушка или альтернативный дизайн новости (без картинки)?

Изменение стрелки на текстовый курсор ⌶ при наведении на текст подсказывает, что пользователь прямо сейчас может его отредактировать. Иногда ответить на вопрос о поведении курсора довольно непросто, например: «Надо ли превращать курсор в палец над кнопками на сайтах?».

14. Конфигуратор одежды, галерея изображений
14. Конфигуратор одежды, галерея изображений

В галерее изображений можно переключать вертикальный список превью. К чему приведёт нажатие на нижнюю иконку шеврона: к отображению одного нового превью или блока из семи новых картинок? А если есть только три новых картинки, на экране будут они и пустое место или три новых и четыре старых картинки? Если новых картинок нет, шеврон станет неактивным, пропадёт или прокрутит список картинок в самое начало? Вот часть спецификации:

  1. Кнопки для прокрутки списка превью отображаются, если изображений в галерее больше N (количество определяется на этапе дизайна).

  2. Нажатие приводит к прокрутке списка и отображению следующих N превью.

  3. Если следующих превью меньше N, отображаются все новые превью и часть старых, из предыдущей группы.

  4. Если следующих превью нет, кнопка не отображается.

Полезные вопросы для описания элементов интерфейса определённого типа:

1. Список и таблица:

  • Из чего состоит элемент списка?

  • Сколько элементов списка отображается на странице?

  • Когда отображается постраничная навигация?

  • Как упорядочен по умолчанию? Например: в прямом алфавитном порядке по названию, в обратном хронологическом по дате публикации.

  • Что будет, если в списке не окажется ни одного элемента?

2. Кнопка:

  • Когда может быть неактивной?

  • Что происходит при нажатии активной и неактивной кнопки?

  • Как ведёт себя, чтобы не допустить двойного нажатия и двойной отправки данных?

  • Какие вызывает сообщения об ошибках заполнения формы?

Если кнопка неактивна, полезно сообщать пользователю, почему так и как её активировать. Например, при наведении на неё курсора.

3. Поле формы:

  • Тип поля?

  • Обязательно ли для заполнения?

  • Есть ли требования к вводимым данным? Например, можно вводить только цифры.

  • Минимальные и максимальные значения?

  • Значение по умолчанию? Например: на странице с поисковой выдачей поле поиска по умолчанию заполнено пользовательским запросом; на странице регистрации флаг в чекбоксе «Подписаться на новости компании» по умолчанию установлен.

  • Наличие или отсутствие плейсхолдера?

  • Текст плейсхолдера, если он не показан в прототипе?

  • Текст сообщений об ошибках?

  • Когда сообщения об ошибках будут отображаться: во время заполнения формы или в момент её отправки? Если во время заполнения, то когда именно? Например, когда поле теряет фокус.

  • Связь с другими полями формы и элементами страницы? Например: если флаг в чекбоксе «Уведомлять по электронной почте» установлен, отображается поле для ввода адреса электронной почты.

4. Поле поиска:

  • Когда отображаются и как работают подсказки?

  • Появляется ли кнопка очистки поля?

  • Реагирует ли на нажатие клавиш? Например, нажатие на Enter приводит к отображению поисковой выдачи.

5. Контент:

  • Откуда появляется?

  • По каким принципам генерируется? Решение с обозначениями «К1» и «К2» в примере в начале статьи, возможно, не самое удачное, но оно записано и его можно обсуждать.

  • Как пользовательские данные влияют на поведение системы?

Примеры влияния пользовательских данных:

В форме заказа пользователь выбирает регион. В одних регионах заказы обслуживает сама компания, в остальных — региональные партнёры. Специалисты компании работают в CRM, а партнёры получают заказы по электронной почте. Во втором случае потребуется шаблон электронного письма.

15. Приложение сигнализации, сообщение о датчике, который сработал при включении сигнализации
15. Приложение сигнализации, сообщение о датчике, который сработал при включении сигнализации

Пользователь может включить сигнализацию, не закрыв окно в детской. Может быть, он просто забыл или специально оставил детскую проветриваться. В этом случае, если сигнализация включена, закрытие окна приведёт к отправке уведомления, а повторное его открытие — к тревоге.

Пользователь видит текст о датчике и логике работы сигнализации и может решить: закрыть окно или спокойно уйти, так как день не ветреный и окно само не захлопнется. Экран с этим сообщением появился уже при написании спецификации, когда я прикидывал, какими могут быть пользовательские данные (показания датчиков) при включении сигнализации.

И в заключение параграфа — пример элемента с нетиповым взаимодействием:

16. Конфигуратор одежды, редактирование нанесения в виде картинки
16. Конфигуратор одежды, редактирование нанесения в виде картинки

Пользователь добавляет на футболку нанесение в виде текста или изображения. У любого нанесения есть два состояния: просмотр и редактирование. Нанесения не могут пересекаться — это техническое ограничение процесса печати и вышивки на одежде. Чтобы отредактировать нанесение, надо на него нажать.

Описание взаимодействия, включающее реакцию на некоторые клавиши:

  1. Нажатие на нанесение приводит к его выделению и отображению его настроек.

  2. Нажатие на второе нанесение, когда первое выделено, приводит к скрытию настроек первого и отображению настроек второго.

  3. Нанесения не могут пересекаться.

  4. Выделенное нанесение удаляется, если пользователь нажимает клавишу Delete или Backspace. Не работает в режиме редактирования текста в текстовом нанесении.

В режиме редактирования нанесение можно перемещать, масштабировать и поворачивать. Возникают вопросы: с каким шагом в градусах его можно поворачивать; что если пользователь переместит его за пределы области нанесения?

  1. Пользователь поворачивает нанесение, удерживая его за специальный контрол, нанесение поворачивается в заданную пользователем сторону с шагом в 90 градусов.

  2. Пользователь перемещает нанесение, удерживая его за специальный контрол.

  3. Пользователь может переместить его за пределы области нанесения, но не далее рабочей области. При этом:

    1. Часть нанесения, оказавшаяся за пределами области нанесения, не отображается.

    2. Контур нанесения и связанные с ним контролы настройки отображаются и за пределами области нанесения.

Состояние с объектом, оказавшимся за пределами области нанесения (с контуром и частично скрытым текстом или изображением), надо показать в прототипе.

К оглавлению

Описание страниц

Поведение системы не всегда связано с конкретными элементами на странице. В этом случае можно описать поведение страницы в целом.

17. Приложение сигнализации, пользовательское соглашение
17. Приложение сигнализации, пользовательское соглашение

Экран с пользовательским соглашением появляется при первом запуске приложения и при каждом изменении соглашения. Вопрос: когда пользователь увидит его во второй раз, не решит ли он, что это сбой в матрице, ведь он уже соглашался с условиями? Возможно, стоит предусмотреть дополнительное состояние экрана на случай, когда соглашение изменится. Вот описание экрана «Пользовательское соглашение»:

  1. Экран отображается:

    1. При первом запуске приложения до тех пор, пока пользователь не подтвердит согласие с условиями пользовательского соглашения.

    2. При открытии приложения в случае, если текст соглашения был изменён и требует нового согласия пользователя. В этом случае текст соглашения будет начинаться со слов о том, что соглашение было изменено.

В итоге решили обойтись без дополнительного состояния.

Что если пользователь открывает приложение из-за тревоги, а соглашение изменилось? В этот момент неуместно просить ознакомиться с новой версией документа, даже если он написан человеческим, а не юридическим языком. Это тоже стоит добавить в спецификацию.

Тревога и наличие нескольких объектов приводит к появлению межэкранной логики:

  1. Когда у пользователя более одного объекта, после входа он переходит:

    1. Если тревоги нет — на экран со включённой или выключенной сигнализацией последнего выбранного объекта.

    2. Если тревога у одного объекта — на экран тревоги этого объекта.

    3. Если тревога у двух и более объектов — в главное меню.

Эта логика может быть зафиксирована в описании кнопки «Войти», но лучше её вынести в документ со сценариями или юзерфлоу. Особенно, если войти в приложение можно с помощью других кнопок (например, через соцсети).

К оглавлению

Примечания

Это текстовая версия моего доклада о функциональной спецификации интерфейса с конференции БИФ, прошедшей четыре года назад. С тех пор материал не сильно устарел, но эта статья — не просто транскрипт. Я постарался сделать её понятнее доклада: переработал структуру, уточнил формулировки, убрал краткий рассказ об артефактах проектирования и лишние примеры, добавил важные уточнения. Есть запись доклада (41 минута), но статья лучше, и читать её всего 15 минут.

Спасибо Марине Пустовит, Даниилу Скрыльникову и Егору Камелеву за комментарии, которые помогли дополнить статью и упростить её для восприятия.

Подписывайтесь на мой телеграм-канал UX Notes!

Tags:
Hubs:
Total votes 2: ↑2 and ↓0+2
Comments6

Articles