Стой под стрелой – Telegram
Стой под стрелой
11.5K subscribers
1 photo
17 links
Ведет @nikitonsky. Рекламы нет
Download Telegram
Одна из вещей, про которые я железно уверен, что они работают (а таких ОЧЕНЬ немного) — код-ревью.

Когда-то я работал в компании Эхо, где мы изобретали встраиваемые виджеты комментариев, еще до Дискуса (да, я такой старый).

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

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

Завалилось наше начинание очень скоро и очень живописно. Коммитили мы конечно быстро, но такая фигня получалась. По итогам все согласились (абсолютно добровольно и единогласно!) что не хватает именно код ревью. Нагляднее и доходчивее я мало что ощущал в жизни.

Почему? Гипотеза у меня очень простая: коммуникация. Ревью это простой и понятный формат проговорить важные вещи, сверить часы, поделиться информацией о реализации, согласовать что-то, поднять какой-то вопрос.

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

Другие форматы? Гораздо хуже. Дизайн-митинги, стендапы, пост-мортемы слишком редко проходят, на них слишком много людей и повестка обычно слишком расплывчата. Ревью же максимально конкретны, максимально узкой компанией, с макмимально ясной целью, да еще и щадят расписание участников из-за своей асинхронной природы.

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

Так что вот, рекомендую попробовать.
👍4
Продолжая про код ревью, я научился тогда одной важной вещи, плоды которой пожинаю до сих пор. Называется «не доебываться по мелочам».

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

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

Но самое главное — помалкивать, если не можешь сформулировать проблему, или если формулировка звучит неубедительно. А мои любимые «Этот код говно», «так писать нельзя», «тут все плохо» — не аргументы, а роспись в собственном неумении формулировать мысли. Думать вслух в принципе окей, и не знать всех ответов тоже окей, но ревью не место для этого. Думай в свободное время, но на обсуждение выноси конкретику.
4😁1
Когда обращаешь внимание, что какая-то программа долго запускается, часто можно услышать возражение: «первый запуск медленный, зато инкрементальный быстрый». Типа, пострадай один раз, а потом станет легко и приятно.

Не станет. Инкрементальность — это всегда а) компромисс (запускать каждый раз долго, надо было что-то придумывать), поэтому б) решение задним числом (спохватились, когда уже все написали и поняли, что тормозит) и в) просто очень сложно. Ну не силен человеческий мозг в комбинаторике, не может держать в уме все возможные n² переходов.

Как результат, все инкрементальные тулзы без исключения, которые я видел, работали ненадежно и требовали постоянного перезапуска. Clojure, ClojureScript Compiler, Gradle, Kotlin Compiler, вся IDEA целиком. Причем не в единичных случаях, а на постоянной основе — либо изменений оказывалось так много, что какая-то ошибка обязательно да вылезала, либо просто юзкейс не предусмотрели.

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

Инкрементальность лучше, чем ничего, но это компромисс. Инкрементальность всегда добавляют от плохой жизни, а не от хорошей. Лучше (и проще) — писать сразу быструю программу, которой не нужна инкрементальность.
Короче, писать скрипты на Баше не нужно. Bash на удивление удобный язык, да. Но он так же и очень плохой.

- Bash просто отвратительный язык программирования. Аргументы функций, возвращаемые значения, глобальные переменные, типов нет, списков нет, регэкспы ужасные короче ужас. Даже простые вещи приходится постоянно гуглить, а написать прилично выглядящую и читающуюся, пусть даже слегка нетривиальную программу, практически невозможно. Если подумать, бредовая же идея — интерфейс интерактивного набора коротких однострочных команд засунуть в batch-файл и сделать основой автоматизации всего проекта. Бред! И ровно то, что происходит.

- Куча артефактов древних, про которые ничего не понятно, кроме того факта, что рано или поздно они выстрелят в ногу. В чем разница между $(...) и бэктиками? Между [] и [[]]? И еще там какой-то пробел где-то рядом с этими скобками очень важно поставить, кажется. Каждый раз, когда читаю про то, как правильно дважды эскейпить символы в scp, иду в итоге и напиваюсь.

- Многое bash не делает сам, а делегирует «утилитам». Самое подлое, что эти утилиты разные, но только _слегка_, то есть вроде как бы делают одно и тоже, но вроде как и чуть-чуть по-разному. Такая бомба замедленного действия, ждущая своего исключения. Я написал, может, двести строк на Bash, но даже на таком маленьком объеме успел напороться на два расхождения в xargs и в sed между macos и linux.

- Запустить bash на Windows в принципе можно, но означает притащить с собой половину Линукса, и все равно наесться говна на кросс-платформенности. Нет в mingw какого-нибудь zip и привет. Лично я очень долго уговаривал Windows выбрать правильный виндовый компилятор, но вызывать его из линуксового bash-скрипта.

- В Bash опасные дефолты. Очень легко написать программу, которая работает сейчас у меня, но не сработает в слегка другой ситуации. Пробелы в именах файлов до сих пор не побеждены, да! Я лично жрал это говно послдений раз вот прям в 2020. Не проверили exit-код? Зажуем ошибку. Опечатались в переменной? Подставим пустую строку! Запустили скрипт из другой директории? Посчитаем все пути относительно нее!

- Иногда же наоборот, бесит, что там, где как раз «разумные дефолты» диктуют ошибку проглотить (например, потому что работа уже сделана и ничего делать не надо), оно ломается и ставит раком весь процесс. mkdir поверх уже созданной папки? Ужас какой, остановим всю программу! cp с нулем файлов (ну потому что предыдущий шаг ничего не произвел)? Невозможно, на всякий случай тормози поезд! `rm`-у нечего удалять? Непорядок, начальника!

Да, любой из аргументов выше можно опровергнуть: да ты не разобрался. Ну вот мой hot take: а я и не хочу разбираться! Мне не нужна докторская по скриптингу, скриптинг это по определению то, на что я хочу тратить минимум усилий. Чем безболезненне, тем лучше.

Главная уловка-22 в том, что на баше легко _начинать_. Одно-двухстрочники действительно, ни на чем удобнее не сделать. Но дальше bash не масштабируется, а люди все равно продолжают писать. Чтобы выкинуть bash надо _принять решение_, а чтобы продолжать, не нужно делать ничего, даже просыпаться не нужно.

Какая альтернатива? Питон. Отличный язык, очень лаконичный, минимум церемоний, батарейки все в комплекте: argparse, subprocess, os.path, glob, shutil, urllib.request, zipfile. Везде, ну, почти одинаковый. Кросс-платформенный. На маке/линуксе даже как будто из коробки?

Так что я все понимаю. Сложно. Но надо меняться. Даже если кажется, что все окей, даже если все так делают. Потому что bash — это все-таки затянувшийся несмешной пранк, который почему-то начали воспринимать серьезно. Пора ему туда же, где сейчас Перл — на свалку, ой, простите, полку истории.
Каждый раз, проходя мимо фронтенд-стека, удивляюсь: ребята, у вас уже был идеальный сетап для разработки. Редактируешь файл на диске, хоть HTML, хоть CSS, хоть JS, обновляешь страницу — бам! Все работает. Никаких компиляций, никакой инфраструктуры, никаких приложений, достаточно реально блокнота. TextMate в свое время взлетел как раз на волне того, что для разработки ничего более сложного не было нужно. Компилятор встроен в браузер, оптимизирован под time to interactive, REPL там же офигенный, дебаггер, визуальный отладчик один из лучших.

Как это можно было добровольно испортить? Как можно было отказаться от этих даров богов в пользу медленного и сложного пайплайна? Нажал кнопочку, вебпак запустился, минуту пошуршал, стрелочки в терминале красиво погонял туда-сюда. Минуту!!! ... профит? Потом еще пойди разбери, что он там нагенерил и откуда это пришло (наверняка для этого тоже есть ТеХнОлОгИи, но это тушение пожара огнем какое-то, ей богу).

Получается, деградация веб-разработки произошла ровно по одной причине: она выглядела недостаточно серьезно. Как это – файл в блокноте написал и все? Ты точно разработчик? А деньги за что получаешь? Конференции, опять же, вокруг TextMate-based workflow не соберешь, а молодым людям хочется общаться.

Если что-то делается слишком просто и очевидно, некуда прикладывать мозг, а человек у молодого растущего человека не любит, когда мозг ничем не занят. Видимо, есть какой-то естественный уровень сложности, с которым человеку приятно работать. Если сложности меньше, она добавляется искуственно, на ровном месте, чтобы мозг не работал вхолостую.
3
Языки пока еще застряли в парадигме разработчика и его машины, а мир тем временем связал интернет. Глобальные репозитории пакетов и импорт зависимостей с github — хорошо, но это только начало. Нужно идти дальше.

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

Что мешает? Количество церемоний. NPM и node_modules подошли близко, но оверхед на публикацию пакета все еще очень высокий. Вот количество файлов в репозитории is-array, js-функции из одной (!) строчки:


.gitignore
.jepso-ci.json
History.md
Makefile
Readme.md
component.json
index.js
package.json
test/test.html


Можно еще меньше, но все равно это как минимум несколько файлов. Кроме этого, нужно завести репу на github, пакет на npm, опубликовать из одного в другое, потом выбирать версию, импортить это в package.json, нажимать npm install, и наконец можно использовать. Сложна!

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

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

И третья проблема это избыточность. is-array это вырожденный случай с одной функцией, обычно, конечно, функций в библиотеке минимум десятки, а дальше сколько угодно. Тебе могут быть не нужны все их них, но подключать приходится все и сразу. JS-ники изобрели tree-shaking, потому что в браузер отдавать балласт не очень здорово, а на бэкенде так и живут — заимпортил сотню классов, использовал два.

И вот к какому решению я пришел:

- Репозиторий функций, а не пакетов.
- У каждой функции уникальное fully qualified имя, как URL.
- Функции иммутабельны. Хочешь что-то поменять — создавай новую. Неудобно, зато надежно.
- Функции могут зависеть только от других уже опубликованных функций.
- Тривиальный импорт из юзер кода. Прям в любом месте import-remote me.tonsky.collections.group-by as group-by; и все, вперед использовать, как будто она у тебя всегда была в соседнем файле написана. Никаких package.json, лок-файлов и никаких прогресс-баров, как она скачивается. Минимум церемоний.

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

Вторая — tree-shaking. В такой схеме он не нужен, потому что импортится только и точно то, что используется.

Нужен ли для этого какой-то специальный язык или рантайм? Кажется, что нет! На Кложе такое можно сделать макросом, у меня даже был прототип, но до продукта я его не довел, потому что там надо тот самый репозиторий организовывать. Кажется, и на JS можно.

Может кто-то сделает.
👍1
Сегодня четвертый день, как я борюсь с макОС-ом в попытке поставить системный светофор по нужным мне координатам. Дорогой дневничок,

День первый.

- Мы хотим вписать светофор в наш собственный заголовок. По красоте, как у всех.
- Если скрыть тайтлбар, светофор пропадает. Логично.
- Его можно добавить обратно, но теперь кнопки не реагируют на перемещение.
- Их родительский view тоже не реагирует на перемещение.
- Нужно создать новый view и перенести кнопки туда. Сами кнопки двигать все еще нельзя. Зато теперь можно двигать родительский view!
- У кнопок остается неубираемый оффсет, типа (7, 6). Собственно, чтобы поставить кнопку на X,Y, надо поставить наш view на (X - 7, Y - 6).
- Этот оффсет разный на разных версиях ОС. На Каталине, например, (7, 3).
- Путем нехитрой тригонометрии подгадываем координаты, чтобы кнопки в конечном счете встали куда нужно.
- Тестируем ховер. Плюсы: ховер работает. Минусы: когда наводишь на пустое место, где кнопки стояли раньше, ховер тоже срабатывает :(

День второй.

- Кажется, дело в старом родителе, у которого забрали кнопки, но который до них дозванивается.
- Удаляем его, ховер начинает работать как нужно.
- Тестируем переход в фуллскрин. Чудом фуллскрин работает как надо сразу. Пронесло.
- Выходим из фуллскрина. Кнопки встают на свои дефолтные места. Ну еб твою мать!
- Ладно. Мыж программисты. Выливаем воду из чайника, зовем нашу функцию еще раз, кнопки встают куда нужно.
- Снова тестируем ховер. Работает. Ходим в фуллскрин и обратно. Позицию починили. А ховер, сука, опять не работает!!!

День третий.

- Перепробовано миллион вариантов, кого куда добавлять, за какие методы подергать и какие маски поставить.
- Изучены исходники Electron, включая историю изменений фичи про светофор, Chromium и Firefox.
- Прошерстен StackOverflow.
- Успех пришел из ответа с одним (!) апвотом. Окно после выхода из фуллскрина надо поресайзить — увеличить на пиксель и вернуть обратно.
- Объяснение — кнопки ходят в своего родителя (!) и дергают у него приватный АПИ (!!).
- Причесываю, коммичу наконец (нормально ли, три дня без эякуляции^W^W коммитов?), ложусь спать.

День четвертый.

- Добрые коллеги не поленились каждый завести по тикету, что на старте появился новый warning.
- Оказывается, рутовый view не ожидал, что в него будут что-то добавлять. Он проверяет по списку знакомых ему вьюх, и если что-то незнакомое, то ругается. Но работает.
- В чем смысл такой логики? Ты либо не работай, либо не ругайся. А так пассивная агрессия какая-то.
- Переставил кнопки в content view. Ворнинг ушел. Дело объявляется закрытым.

Ну то есть как закрытым? Кнопки все еще слетают при смене системной темы (!) и прыгают при выходе из фуллскрина. Но я больше не могу, нужно переключится на какую-то осмысленную деятельность. Кстати, если бы я просто сразу сам нарисовал эти три сраных кружка, я бы управился за полдня со всеми ховерами, альтами и попапом на фулскрин. Да, выглядело бы несистемно на старых или новых версиях. Но полдня!

Больше всего расстраивает, что это вроде как и называется инженерной работой у нас в индустрии. Ходить с бубном вокруг каких-то хреново сделанных артефактов в надежде на дождь. Решить тривиальнейшую задачу средствами, сравнимыми с удалением гланд через задний проход. Какое-то бессмысленное колесо сансары, одни делают говно, другие этим говном вынуждены пользоваться, все несчастны.

Отдельно «порадовало» знакомство с нативной разработкой под Мак. С одной стороны, я понимал, что в проприетарной системе не может быть счастья, но с другой, у Эппла же все такое красивое снаружи, может и внутри как-то неплохо? Конечно же НЕТ. Всю дорогу преследовали флешбеки из веб-разработки, которая ввела меня в депрессию в прошлый раз. Только тут еще хуже — вместо условного MDN и Caniuse, где квирки хоть как-то задокументированы, а буйство фантазии Хрома сдерживается конкуренцией, в Эппл экосистеме о хитрых поведениях и ручках не написано нигде и нужно тупо догадываться.

Но всем, типа, нормально. Так и живем.
👍1
Когда тебе пять лет, ты воспринимаешь мир как данность, не ставишь ничего под сомнение и просто запоминаешь, как что работает. Тебя научили ходить в туалет самостоятельно, но в какой-то момент неизбежно случается страшное: заканчивается туалетная бумага. Ты паникуешь и бежишь к маме/папе, которые спокойно показывают тебе шкафчик в ванной, где лежат запасные рулоны. Ты запоминаешь этот факт, начинаешь пользоваться и живешь спокойно дальше.

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

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

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

Это пост про программирование, кто не понял.
3
В контексте UI фреймворков один занимает особенное место в моем сердце. Это Swing. Мне всегда казалось, что в любой сложной вещи можно разобраться. Может быть долго, неудобно, энтерпрайзно, с багами, со странными дефолтами, но это все познаваемые вещи, неприятно, но познаваемые.

Swing это следующий уровень просветления. Познаваемость для него – non-goal. В нем все работает не так, как ожидаешь. Вещи выравниваются по фрактальным направляющим, вместо рядов и строк загадочные лайауты со сторонами света (!), дети встают процентов на 60-75 от доступного места, контролы слегка кривоваты, ресайзятся через раз, а программисты ходят ушибленные, шепчут «достаточно один раз понять gridbaglayout», затягиваются сигаретой и замолкают на двадцать минут. И это при том, что я пятнадцать лет вебом занимался, то есть по определению видел некоторое дерьмо.

Вот как можно было так напрограммировать, а?
😁1
Основная идея ИДЕ и честного семантического анализа кода (а не быстрого синтаксического) в том, что оно понимает разницу между karas и karas(), что переменные indeks в двух соседних функциях это разные вещи, хоть и называются одинаково, и так далее. Как результат, надежнее работают рефакторинги, переименования, find usages, go to declaration и autocomplete. Собственно, на этом обещании и построена вся бизнес-модель.

В противовес такому сложному анализу появился когда-то анализ максимально простой: предлагать все подходящие слова из того же файла. Идея в том, что если ты пишешь какое-то слово, с высокой вероятностью оно в этом файле уже есть, а слишком уж похожих слов, ну, не так много. Популяризовал TextMate, потом это перешло в Sublime, далее и в Atom с VS Code. Казалось бы, полный колхоз и возврат в каменный век, но практика показала, что а) такой подход работает, и неплохо, гораздо лучше, чем может показаться, и б) иногда он работает лучше, чем семантический и умный.

Примеры, когда права ИДЕ, достаточно очевидны и приводить их я не буду. А вот когда побеждает простой текстовый матчинг по текущему файлу? А вот когда:

- Когда программа сломана / недописана / синтаксически некорректна. То есть в процессе написания. То есть ровно тогда, когда тебе эти подсказки больше всего нужны.
- Когда нет поддержки конкретного языка или просто в сплошном тексте.
- Когда имя размазано по программе, а не сконцентрировано в одной сущности. fun switch(style: SwitchStyle, colors: SwitchColors): Switch. Тут четыре упоминания корня switch, но для ИДЕ это просто четыре разные сущности, функция и три разных класса. Инструментов для работы с каждой по отдельности сколько угодно, а вместе — ноль.
- Когда ты пытаешь сослаться на что-то в «неправильном» контексте. Например, объявить функцию с таким же именем, как переменная, или в println вставить ("soloma: " + soloma). Переменная, понятно, найдется, а вот то, что внутри строки, для ИДЕ просто непрозрачный текст.
- Когда что-то сломалось (что не такая уж редкость).

В целом ИДЕ делает ставку на лучший результат, но только когда дела обстоят хорошо. Легковесные редакторы ставят на среднего качества опыт через эвристику, зато работающую всегда и везде.

Так и живем.
👍2
Лет десять назад я очень увлекся юзабилити и интерфейсами. Читал книжки взахлеб, советы Горбунова и Бирмана, презентации Головача, отвечал на UX StackExchange, даже подработал дизайнером интерфейса немного. Очень уж легко и естественно мне заходила эта тема, казалось, что ничего важнее быть не может, я даже подумывал о смене профессии.

И вот на одной конференции выступала Ольга Павлова, основательница компании, продающий как раз UX экспертизу, с каким-то докладом, проилюстрированном исключительно мемами. Кстати, тогда же я понял, что UX это не про красоту, не про оригинальность и не про хороший вкус, а про содержание.

После доклада я задал ей два вопроса: как, по ее мнению, измененился спрос на UI/UX? Ответ: вырос экспоненциально и не продолжает. И второй: как сильно, по ее мнению, влияет UI/UX на успех продукта? Ответ: процентов 10.

Короче, это меня тогда очень впечатлило и, хочется верить, вовремя повернуло мозги в нужную сторону. Потому что легко представить, что ничего важнее UX в продукте нет, и проигнорировать все остальные 90% факторов. Примерно как «клиент всегда прав» не может быть главным принципом для бизнеса.

Подтверждение неважности UX я вижу каждый день на каждом шагу. Сотни суперуспешных продуктов имеют отвратительный UX целиком или в деталях, и это совершенно никак не мешает им быть успешными. GTA Online загружается пять-семь минут? На бизнес не влияет. У Apple Music вместо интерфейса запутавшаяся рыболовная сеть, но музыку играет, идет предустановленным на телефоны, что еще надо? Patreon самая известная crowdfunding платформа, и там _ничего_ не сделано нормально, зато деньги надежно капают на счет. Про Амазон вы и сами представляете. Гугл-драйв. Медиум. Биг Сур. Букинг. Линкедин. Это все не просто «можно что-то улучшить», это целиком продукты, делавшиеся или без UX-эксперта, или намеренно во вред пользователю.

Увлекаться UX я не перестал, зато перестал думать, что обладаю самым главным знанием на свете. Скорее это такое гиковское увлечение, клуб по интересам, довольно изолированное от реального мира и никому кроме нердов не интересное. Но пока интересно — почему бы и нет?
5
Давным-давно, в 2012 году, у Студии Артемия Лебедева была традиция публичных вакансий, примерно как домашки у Ильи Бирмана сейчас: делаешь задание, а потом арт-директор публично разбирает все присланные работы.

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

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

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

Примеров вокруг полно. Мы все любим Гугл не потому, что с одним-единственным полем поиска легко найти то что нужно, а потому что не нужно думать о всяких-разных настройках. Даже если с доп. настройками мы искали бы точнее. Или какой-нибудь айфон времен расцвета Эппл (сейчас-то уже все мобильные ОС практически идентичны), который ничего не поддерживал и почти ничего не умел, зато то, что Эппл соизволила реализовать, просто работало. Мало и просто >>> много или удобно.

Другой способ думать об этом: у каждой фичи или настройки есть ее когнитивная стоимость. Если польза от фичи не превышает эту стоимость, добавлять ее не стоит. Итоговая сложность интерфейса должна быть соразмерна решаемой задаче, и да, даже ценой удобства.
4
По интернету гуляет статья «Speed is the killer feature», которая, типа, как раз по мою душу. И там, конечно, все правильно написано, я и сам сто раз про это говорил.

Но фокус там на проблемах, которые вызывает latency, а я хочу поговорить о преимуществах, которые дает скорость. Так вот, в использовании цифровых продуктов (нет, речь не о молоке) есть некоторый порог скорости, после которого происходит качественный скачок в использовании.

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

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

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

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

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

Так что писать быстрые программы нужно не потому, что пользователи не дожидаются и куда-то уходят. Нет, они очень терпеливы. Скорость нужна, чтобы вместо десяти вариантов использования, которые вы предусмотрели, пользователи открыли сто или тысячу, фантазировали, экспериментировали и приспосабливались. Это очень сложно делать в медленной программе, а вот быстрая к такому сама подталкивает.
16👍5
В далеком 2012-м году все сидели на Скайпе. Скайп никому особо не нравился, мне больше всех, поэтому я начал инициативу по переводу компании на Campfire. Ну да, Слака-то не было тогда еще. И Телеграма не было.

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

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

Ладно. Собрали второе совещание. Спрашиваю, мол, а чего все снова в Скайпе-то? Да хз. Что-то не нравится? Нет, все нравится. Может, кто-то передумал? Нет, никто не передумал. А чего все в Скайп пишут? Хз, само так получается.

В общем, я еще побегал, поуговаривал, попредлагал решений, но ничего не сработало. На третью неделю я перегорел, инициатива провалилась, а я на собственной шкуре оценил гравитационную мощь инерции, и насколько против нее не попрешь.

Через год уже другой сотрудник поднял тему переезда, я его конечно поддержал, но вписываться, наученный, уже не стал. И да, у него точно так же ничего не вышло. В следующей компании я наблюдал аналогичную попытку съехать с Flowdock, которая провалилась похожим образом. Да что там, у нас в JetBrains есть свой собственный чат в составе Space, и даже собственных сотрудников невозможно убедить им пользоваться. Не потому что плохой — нет, нормальный — но потому что инерция.

В этой истории у меня осталась только одна непонятная деталь: а как получилось у Слака? Что они такого особенного сделали, что смогли эту инерцию переломить? Не то чтобы у них какие-то уникальные функции были, или скорость, или простота (ох уж их система логинов!), или позиция на рынке. Что такого есть у них, что люди _хотят_, сами, добровольно, им пользоваться? И чего нет у их конкурентов? Понятно, что стадный инстинкт (где друзья, там и я), но каким чудом они набрали критическую массу?
👍2
На словах почти все языки понимают важность глобально уникальных имен: у файловой системы может быть, например, Path, и у графической библиотеки может быть Path, но есть один нюанс^W^W^W никаких проблем не возникает: у тебя java.nio.file.Path, а у меня javafx.scene.shape.Path, не перепутаешь.

Почти никто, впрочем, не понимает, что эта уникальность должна сохраняться в пользовательском коде. Иначе начинаются всякие нелокальные эффекты: заимпортишь один пакет, а у тебя код ломается, потому что он уже использовал такой же класс из другого пакета. То, в чем комплятор только что прекрасно разбирался, внезапно становится китайской грамотой, и только из-за _добавления_ кода. Можно еще веселее: создать новый класс в своем пакете и сломать чужой, который import твой.пакет.* делал!

Читать тоже сложно: смотришь в коде, написано: “List”. Думаешь: а какой конкретно List? Чтобы узнать, надо идти наверх и смотреть на импорты. А если в импортах wildcard, то надо в каждый пакет идти и смотреть, не экспортит ли он случайно класс с таким именем. Так, собственно, и возникли IDE: язык так плохо сдизайнен, что без IDE не разберешься.

Решается проблема тривиально: fully qualified name надо писать в месте использования, а не в месте импорта, а импорты вообще запретить. Ну, может, алиасы оставить.

Один только язык подошел к делу правильно: Эрленг. Если я правильно помню, там как раз никаких импортов нет, а функции из другого пакета надо по полному имени вызывать.

Глобально уникальные имена вообще гениальная штука, она такая простая и при этом столько всего решает, что даже удивительно, как люди продолжают ее избегать и героически решать связанные с неоднозначностью проблемы.
Интересно, как Unix когда-то был интерактивной средой, в которой люди буквально жили: хранили списки покупок, писали письма, читали интернет. Язык C в то время был просто подспоркой в обживании этой среды: быстренько заавтоматизировать что-то, упростить себе жизнь. Ну, я так себе это представляю, конечно, я пока не такой старый.

Артефакты тех времен — например, пользователи. Хоум дир, права доступа на каждый файл, группы — когда компьютеры были дорогими, а программисты дешевыми, приходилось общежительствовать.

Или локаль — штука, попавшая в стандарт языка C прямиком из соглашения операционной системы. То, как будут парситься флоаты в языке, зависит от того, как пользователь настроил свое окружение! Сейчас так уже не делают, конечно — языков в изобилии, а операционные системы не каждую декаду появляются. Этот пост вообще вдохновлен багом с локалью: недавно фиксил SVG парсер, который путал . и , на Линуксе, потому что там до сих пор теребят LC_ALL.

Сегодня это все милые штуки, бесконечно устаревшие, конечно, и ничего кроме головной боли уже не вызывают. Скорее бы сделали «серверный» линукс, в котором все это вычищено и оставлена самая суть.
Посмотрел The Outsider по Кингу, с которым у меня очень долгое недопонимание.

Интересно, как человек, настолько подробно понимающий мелкие детали человеческих жизней (а Кинг весь про детали) может, но почему-то не хочет, сколь-нибудь долго про них писать. Каждый раз, начав за здравие, все равно скатывается в свехестественную дичь, растеряв и все свои сильные стороны по пути, и весь интерес к происходящему.

У меня, конечно, есть теория. Что если Кинга в детстве что-то очень сильно, по-настоящему напугало, настолько, что до сих пор не отпускает? И он продолжает писать книжки, чтобы как-то этот страх успокоить, сталкивая в книгах зло с рациональным, будничным, реалистичным, то, что его окружает каждый день, и давая силам добра победить скукой и занудством. Ну, хотя бы в книге.
Одну вещь заметил в интернете — встраивать видео умеет только Ютуб. Все остальные доморощенные плееры и даже нативный тег <video> всегда работают через раз. Кривоватенько, косоватенько, что-нибудь нет-нет да отвалится, качество шакальное включит, буферизация неожиданная выскочит, в фуллскрин не перейдет, перейдет, но не развернется, контролы не покажет, или покажет, но не уберет.

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

Короче, сложная проблема компьютер сайнс.
👍3
Супер-полезная фича, которую я видел только в Эрленге — тотальный порядок на всех значениях, даже разных типов. Можно спокойно сравнивать числа и строки, словари и були, атомы и функции. Физического смысла это не несет, и не очень важно, больше ли true чем 'a' или меньше. Важно, что это как-то решено и глобально согласовано для всех значений.

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

В остальных языках разные типы обычно вообще несравнимы, а одинаковые просто нарушают контракт линейного порядка. NaN < 1 || NaN > 1 || NaN === 1 => false, NaN != NaN — честно, конечно, теоретически чисто, но непрактично. Ну вот кому хорошо от того, что попавший в сет NaN ломает тебе все инварианты? Или отдельная история про то, что ==`/`=== работает отдельно от <`/`>, что только путает карты:


a = function() { return 1; }
b = function() { return 1; }
a > b => false
a < b => false
a <= b => true
a >= b => true
a == b => false


Будь как Эрленг, короче. Сравнивай яблоки с огурцами.
👍2
Сначала антагонисты в кино были плоские и злодействовали просто из-за злодейства. Зритель поумнел, и им придумали мотивацию, потом характеры, потом и положительные черты. Закончилось все это моральным релятивизмом — «мир не делится на черное и белое», «у каждого своя правда», «встань на его место».

Что идея довольно плохая, потому что у некоторых вещей есть вполне четкие границы, которые не надо размывать. Можно, конечно, сколько угодно упражняться в толерантности и safe speech, только их цель не в том, чтобы назвать черное белым. Хотя механика и похожа.

Самый отвратительный пример такой тенденции — фильм «Бог простит» Рёфна, но там, кажется, режиссер просто довыебывался и это просто хуевый фильм.

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

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

Как говорится, под аккомпанемент множественных фейспалмов, занавес. Оверкомпенсировали немножко.
😁1
У Пелевина в «Тайных видах на гору Фудзи» была интересная мысль, что наука не особо что-то там позволяет понять и вообще не вносит никакой окончательной ясности.

С одной стороны вроде бы как же так, что вообще может быть честнее и незыблемее науки? Знание не одежда, которая меняется каждый сезон. А с другой:

<<<<<<<

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

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

>>>>>>>

Оказалось что и в науке вроде бы только-только в чем-то разобрались, как бум, тренд меняется и все по новой.

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

Пока компьютеров не было, никто не понимал, о чем вообще речь, и такое объяснение в голову никому, конечно, не приходило — слов таких не было, мыслительных трафаретов в голове.

Про симуляцию, кстати (из «iPhuck 10»):

<<<<<<<

[Взять хотя бы] ...актера и гей-икону Киану Ривза – особенно того периода, когда он еще не мочил из двух стволов русскую мафию (зигмунд, молчать), а подрабатывал Буддой.

«Пацаны, мы в Матрице!!!»

Кто в молодости не шептал этих слов? Только тот, у кого нет ни ума, ни сердца.

>>>>>>>

Что дальше? Не знаю, просимулируют мозг, наверное, и окажется, что вся вселенная тоже в каком-то смысле мозг и разумна. И думает о котиках.
👍2