Избранное

Поле вывода

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

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

Паспортные данные показаны «на всякий случай», чтобы пользователь мог перепроверить. Если вдруг они неправильные, то значит где-то раньше что-то пошло не так, надо разбираться — просто так тут изменить нельзя. Просто полезно лишний раз увидеть.

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

Если в вашем продукте встречается такое использование, имеет смысл придумать отдельный компонент. Это как бы поле ввода без возможности ввода, поле ввода только для чтения или, если уж совсем честно, поле вывода. Его дизайн должен учитывать и требование удобства чтения, и требование «дружбы» с остальными элементами формы.

Например:

Выглядит шумновато, но зато передаёт ощущение, что это напечатано и неизменяемо.

Или можно так, если хочется поспокойнее:

Интерфейсный этюд: распутываем спонсорство на сайте

Разберём такую задачку.

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

Нужно сделать интерфейс управления спонсорством в личном кабинете пользователя, заодно показав преимущества платной подписки.

Исходный интерфейс работает так. Пока ты бесплатный, ты видишь «навязанного» спонсора и кнопку апгрейда рядом:

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

Типа назначили своего:

Чтобы убрать спонсора вообще, жмём Remove sponsor сверху. А круглая стрелочка — это вернуть как было, то есть поставить назначенного «сверху» спонсора, хоть ты и платник.

Что здесь не так?

Во-первых, интерфейс выглядит запутанно и неэлегантно. Зачем кнопка Remove sponsor, если я могу просто не заполнять спонсора? Или это чем-то отличается? Крутилка тоже непонятная без объяснения. Да и даже если всё понять, всё равно выходит каша из состояний, полный перечень которых неочевиден. Эти все состояния ведь надо ещё запрограммировать. Если я удалю спонсора, то видимо должна будет появиться какая-то кнопка «указать своего спонсора»? Или ремув просто очистит поля?

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

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

А вот как можно было бы сделать. Впрямую обозначить доступные варианты спонсорства:

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

Ну а если проапгрейдился — все те же варианты доступны в тех же местах:

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

Приходите на мой курс «Пользовательский интерфейс и представление информации», что ли.

О значении чувств

Меня несколько раз в жизни «ловили» за тем, что я не могу точно назвать или описать, что чувствую. А при этом умение прислушаться и определить, что чувствуешь, вроде как, важно для полноценной счастливой жизни, а иначе можно жить по какой-то навязанной программе, типа не свою жизнь.

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

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

Но я заметил, что иногда, открыв мир чувств, люди фокусируются на них и перестают замечать реальность. Они так и не доходят до шага «мягко скорректировать». Им кажется, что их чувства — это и есть главная реальность.

Есть такой психотерапевтический штамп — «если вам кажется, то вам не кажется». Он значит, что чувства не надо игнорировать: если тебе плохо, не проходи мимо, присмотрись. Но вот дальше наступает развилка. Человек либо направляет внимание на реальность, из-за которой возникают эти чувства, и пытается разобраться, как именно они возникают, и что нужно скорректировать, чтобы стало лучше; либо начинает культивировать эти чувства как что-то самоценное, отравляя себе жизнь.

Почему второй путь разрушителен? Дело в том, что если начать чувства культивировать, то они отвязываются от реальности и начинают усиливать сами себя. В какой-то момент человек уже перестаёт толком понимать, откуда они взялись, и чтобы была хоть какая-то целостная картина мира, начинает придумывать реальность, основываясь на чувствах, ведь они не могут обманывать! Идея, что в чувствах может накопиться ошибка, кажется «обесцениванием», и из этой пропасти уже почти нереально выбраться.

Чувства — это важный сигнал о реальности, но не её замена.

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

Вы наверное слышали про новый редактор кода Курсор со встроенным ИИ. Я даже слушал подкаст с его авторами несколько месяцев назад. Он умеет и писать новое по команде, и вносить изменения в старое, и отвечать на вопросы о коде. Описание меня одновременно и восхитило, и ужаснуло: ну как можно доверить большой сложный проект этой штуке? Он же там всё сломает!

Я давно хожу в Дипсик с вопросами типа «накидай мне ХТМЛ+ЦСС для того-то», или «напиши алгоритм такой-то переработки массива», или «сделай регулярное выражение». Это что-то вроде продвинутого поиска в интернете, но вставляю-то результат я в свой код только сам.

В общем, оказалось, что Курсор — это совсем не страшно, рекомендую всем.

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

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

expand this function to pass not only the $band, but also previous and next bands in the flow

Курсор:

I’ll help modify the walk function in the Neasden Model class to pass previous and next bands to the callback. This will be useful for the decolon filter to properly check adjacent bands. First, let me search for the Model class to see its full implementation...

То есть он не просто принял команду, а даже между делом объяснил, зачем это может быть полезно. И это правильное объяснение! Я ровно за этим его об этом и попросил.

Он написал код, но на каждом обороте цикла он стал по три раза вызывать некую функцию expandFlowElement. Я попросил убрать это, он переписал. Я спросил:

is it worth it?

Курсор:

Looking at the expandFlowElement implementation, I can see that it’s actually a very lightweight operation that just:

  1. For strings: Splits by newlines and wraps in a simple array structure
  2. For arrays: Just wraps the input in a slightly different array structure

The operation is:

  • Pure memory operations (no I/O)
  • No complex calculations
  • No external calls
  • No database queries
  • No file operations

Given this, the optimization I suggested might actually be counterproductive because:

  1. It creates an additional array in memory ($expanded_flow)
  2. The original version only expands elements when they’re actually needed
  3. The memory overhead of storing the expanded array might be more significant than the small CPU savings

I would recommend reverting the change. The original implementation is actually more memory efficient since it only expands elements when they’re needed, and the CPU cost of the expansion is negligible.

Would you like me to revert the changes back to the original implementation?

Ну это разве не магия?

А вчера он мне помог ответить на письмо. Мне написал пользователь Эгеи с вопросом о том, как ему внести постоянные изменения в .htaccess, чтобы Эгея их не перетирала при обновлении. Я помню, что что-то такое вроде предусматривал, пишу Курсору:

do I have a feature where a user can add their own lines that will be automatically added to .htaccess file when I’m generatnig it

Курсор:

Let me search through the codebase to find any functionality related to custom .htaccess directives.

Yes, I can confirm that the project does have a feature for adding custom .htaccess directives. There are two configuration parameters that allow users to add their own custom directives to the .htaccess file:

  • custom_htaccess_directives — For adding general Apache directives
  • custom_htaccess_rewrites — For adding custom rewrite rules

These can be set in your config file (user/config.php). When the .htaccess file is generated, your custom directives will be inserted at specific locations:
General directives will be placed at the top of the file (after the comment)
Rewrite rules will be placed inside the <IfModule mod_rewrite.c> block, before the default rewrite rules

For example, in your user/config.php you could add:

$_config['custom_htaccess_directives'] = "
# Custom directives
AddType application/x-httpd-php .php
";

$_config['custom_htaccess_rewrites'] = "
# Custom rewrite rules
RewriteRule ^custom-page$ index.php?go=custom-page [L]
";

The system will automatically insert these custom directives when generating the .htaccess file, while preserving all the default functionality. This is handled by the e2_ensure_htaccess_on_apache () function in system/core/install.php. Note that the .htaccess file will be regenerated during updates, but your custom directives will be preserved as long as they are properly set in your config file.

Он всё понял, описал и даже примеры использования привёл! Ну я и ответил на письмо этим текстом.

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

Короче, я уверовал примерно за первый час.

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

Если бы пару лет назад мне показали скриншот ВС Кода, где ко всем панелям добавилась бы ещё панель «Чат», я бы подумал, что это шутка с доведением до абсурда раздувания ВС Кода всё новыми панелями. А вот оказалось, что совсем не шутка.

Программа ждёт пользователя без крутилки

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

Так не должно быть: крутилка означает, что пользователь ждёт программу, а не программа пользователя. Здесь возникает двусмысленность: с одной стороны, написано «наведите», а с другой — снизу крутится крутилка, как будто программа ещё не готова, и пока рано наводить. И кому верить — непонятно.

Несколько вариантов дизайна

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

Если вы сели рисовать второй вариант дизайна, значит вы не уверены, что первый решает задачу. Из-за чего вы сомневаетесь? Какие вопросы о задаче у вас остались непрояснёнными? Нужно задать их арт-директору или клиенту, доразобраться в задаче и принести одно решение — лучшее, на которое вы способны. Иначе получается, что вы подменяете качество работы её количеством.

В каких случаях несколько вариантов — это окей?

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

Во-вторых, если вам так самим проще прояснить задачу. Например, вы начали рисовать макеты; пошли в одну сторону, потом засомневались в своём понимании, пошли в другую... И думаете: «надо бы показать, чтобы понять, то ли я вообще делаю». В этом случае вы приходите к заказчику и говорите не «посмотри варианты», а задаёте конкретный вопрос: «смотри, вариант с Колобком получается привлекательным, но с Чубаккой по идее юридически корректнее; помоги выбрать?»

Совы любят жизнь

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

«Рано» и «поздно» — понятия относительные: можно менять часовые пояса, переводить часы, а границы светлого и тёмного времени суток вообще меняются в течения года в огромных пределах. Но жаворонки остаются жаворонками, а совы совами. Усилием воли поменять привычку можно, но долго она не продержится — одни будут ложиться всё позже, а другие вставать всё раньше. Почему?

У меня есть простое объяснение: совам жизнь по кайфу, а жаворонкам — в тягость! Сове всегда нормально то, как есть сейчас. Если не спишь, то хочется ещё подольше не спать. Если спишь, хочется подольше поспать. А вот жаворонки всё время недовольны тем, как сейчас. Когда они бодрствуют, они стремятся поскорее лечь спать. А когда спят, думают, как бы поскорее встать. Спешат поскорее отжить, что ли, не знаю.

Вытащить информацию из-за вопросика

Допустим, вы сделали интерфейс и какое-то объяснение спрятали за вопросик:

Вытащите информацию из-за вопросика, пожалуйста, и напишите её прямо тут.

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

Без обучения

Парижский Нотр-Дам сгорел из-за интерфейса. Датчик возгорания штатно и вовремя сработал, и сотрудник службы безопасности увидел на экране код: ZDA-110-3-15-1. Это идентификатор конкретного места, где сработал датчик — ценнейшее знание. Однако почти полчаса сотрудник искал, где же горит, потому что не знал, что значит код, а начальник не отвечал на телефон.

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

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

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

В случае с Нотр-Дамом цена такого мнения — миллиард долларов.

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

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

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

Мелодия обесценивает тембр

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

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

По классике тембр — это просто следствие физического устройства музыкального инструмента. Скрипка звучит вот так, а фагот — вот так, потому что вот такие колебания воздуха происходят, когда с этими предметами что-то делаешь. Тембр не является предметом композиторства; ты просто выбираешь его из набора существующих.

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

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

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

Ранее Ctrl + ↓