Заметки Андрея Романова
1.31K subscribers
40 photos
100 links
Разработка интерфейсов, дизайн, программирование и всё остальное. Вопросы, пожелания, комментарии — @andrew_r

http://andrew-r.ru
Download Telegram
​​Синдром text neck

Прочитал недавно статью о вреде наклона головы при пользовании телефоном. Прикреплённая картинка говорит сама за себя.

Ирония в том, что я вспомнил об этой статье от дискомфорта в шее, сидя за ноутбуком с такой же наклонённой головой. В очередной раз напоминаю себе и вам, что экран должен располагаться на высоте глаз: нужен внешний монитор или подставка для ноутбука. Раньше дома я использовал подставку Roost, сейчас пользуюсь ей на работе вместе с внешним монитором, рекомендую. Ну и не рекомендую ставить ноутбук под внешний монитор и посматривать в экран ноутбука, очевидно, это не избавит вас от проблем.
​​Блокировка рекламы на уровне DNS

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

Я знаю два решения, реализующих этот подход: Pi-hole и NextDNS. Pi-hole — опенсорсное решение, требующее самостоятельной нетривиальной настройки, но полностью контролируемое вами и никем другим. NextDNS — по сути Pi-hole as a Service, требует минимальной настройки, но и не даёт гарантий того, что логи ваших DNS-запросов никуда не сливаются.

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

Мне кажется, на слова доступность и скринридер в нашем сообществе уже распространился феномен баннерной слепоты. Попробовал сформулировать причину проблемы: https://andrew-r.ru/notes/a11y-ux-usability/
​​Пока, 2019: фиксирую значимые для меня события за прошедший год и немного рефлексирую — https://andrew-r.ru/notes/bye-2019/
​​Портировал любимую цветовую схему Alabaster от Никиты Прокопова на Highlight.js, используемый для подсветки кода в моём блоге (и куче других сайтов!).

Если устали от фейерверка в примерах кода на вашем сайте, подключайте: https://github.com/andrew--r/hljs-alabaster
Глобальный .gitignore

В .gitignore проекта часто добавляют файлы, относящиеся не к проекту, а к окружению и инструментам разработчика. Пример:

.idea
node_modules
dist
.DS_Store
.vscode


Из пяти строк только две касаются непосредственно специфики проекта — node_modules и dist. Чем больше разработчиков работают над проектом, тем больше шума будет в .gitignore.

Хорошее на мой взгляд решение — вместо добавления нерелевантных данных в .gitignore проекта завести персональный глобальный .gitignore и добавить в него всё, что касается вашего окружения, будь то настройки IDE или генерируемые операционной системой файлы:

git config --global core.excludesfile ~/.gitignore_global

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

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

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

Объясню на примере. Представьте, что человеку нужно сделать сайт, а он в этом ничего не понимает. Он нанимает специалиста и в какой-то момент интересуется, как продвигается работа. Ему отвечают:

> У меня возникли проблемы с модулем кеширования страниц в WordPress, почитал StackOverflow, там рекомендуют обновиться до PHP 7, тем более в нём появились декларации типов, которые очень полезны в разработке. Я обновил PHP, но из-за этого пришлось решать проблемы с новым механизмом обработки ошибок. К счастью, как раз сегодня закончил с этим разбираться и доделал главную страницу, двигаюсь дальше!

Что из этого понятно заказчику:

> доделал главную страницу, двигаюсь дальше!

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

Чтобы не совершать этих ошибок, можно пользоваться двумя приёмами:

1. Отвечать на вопросы максимально коротко, не погружаясь в детали. Собеседник при необходимости переспросит или уточнит важные ему детали.
2. В разговоре ставить себя на место собеседника и стараться оценить, будете ли вы ему понятны.

Это сильно упростит жизнь вам и всем, с кем вы будете разговаривать.
👍1
Один удалённо — все удалённо

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

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

Рефакторинг, доступность, быстродействие, тесты: эти вещи объединяет фраза «бизнес не выделит на это время».

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

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

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

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

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

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

Проблему слежки решает разделение кеша (cache partitioning): каждый сайт должен иметь собственный кеш для подключаемых на нём ресурсов. Если facebook.com и vk.com подключают с cdnjs.cloudflare.com jQuery одинаковой версии, пользователь при заходе на них скачает jQuery дважды.

Оказывается, в Safari кеш разделён аж с 2013 года. В Chrome с 77 версии тоже ведётся работа по разделению кеша. Инженеры Mozilla активно помогают в стандартизации этого поведения.
О личной эффективности

Марина Сафонова в 2016 году рассказала о своих принципах личной эффективности, а через два года очень хорошо над ними порефлексировала:

Спустя два года перечитываю тот пост и вижу между строк идею «как бы мне еще себя помучить».

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

На дворе 2020 год, а все сервисы для прослушивания музыки, которые я пробовал (Яндекс.Музыка, Spotify, Deezer, Google Play Music, Apple Music), работают отвратительно.

Мой субъективный гигиенический минимум для таких сервисов:
1. Кроссплатформенность и синхронизация фонотеки между девайсами. Здесь нечего добавить.
2. Простой и понятный интерфейс, который в первую очередь показывает твою фонотеку (исполнители, альбомы, треки, жанры), а не рекомендации и подкасты.
3. Стабильность фонотеки. Привет Яндекс.Музыке, в которой я постоянно обнаруживаю то дубли альбомов, то отсутствие добавленных ранее песен.
4. Переключение треков без задержек. Отсутствие этого особенно бесит, когда слушаешь что-то вроде Pink Floyd, где на протяжении всего альбома один трек плавно переходит в другой.
5. Возможность скачивания музыки на девайс. Как целыми альбомами, так и отдельными треками (привет, Spotify, в котором отдельный трек нельзя скачать без диких ухищрений вроде его добавления в специально созданный плейлист для скачивания).
6. Предсказуемая и стабильная работа в офлайне (например, в самолётах). Снова привет Яндекс.Музыке, у которой в офлайне половина песен пропадает, остальные перемешиваются (в прямом смысле, в альбом заходишь, а там песни в неправильном порядке), а у большинства песен не отображаются обложки альбомов.

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

Если знаете сервис, который удовлетворяет всем критериям — делитесь в чате!
Подход Fail Fast

В разработке есть довольно здравые и широко применимые подходы, о которых почему-то редко рассказывают в учебных курсах или книгах, и ты со временем либо интуитивно приходишь к ним сам (зачастую не в состоянии осознанно их сформулировать), либо узнаешь о них случайно. Для меня одним из таких подходов оказался Fail Fast. Давно о нём где-то поверхностно услышал и отложил в закладки, а сейчас добрался до исходной статьи Джима Шора Fail Fast (PDF, ~120 КБ).

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

Рецепт борьбы с такими багами — подход Fail Fast, предполагающий немедленное сообщение о проблеме при её обнаружении. Джим предлагает покрывать для этого код специальными проверками в неоднозначных местах, где что-то может пойти не так.

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

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

Важно отметить, что этот подход не про полную остановку программы при обнаружении ошибки, а в первую очередь про то, чтобы сделать проблемы заметными. Джим приводит в пример пакетную обработку данных, при которой можно обойтись отправкой сообщения об ошибке разработчику (например, через Sentry) и ненавязчивым сообщением пользователю о том, что часть данных обработать не удалось. Основная идея в том, чтобы разработчик узнал о проблеме как можно раньше и чтобы сообщение о проблеме направило его как можно ближе к причине.
Список сделанных рабочих задач

Рутинная, но крайне полезная практика — ведение списка сделанных рабочих задач. Я веду такой список с февраля 2017 года и могу точно сказать, чем я занимался на работе в любую из недель с той даты.

Каждую неделю я завожу в списке отдельную секцию с временным диапазоном (например, «24–28 мая 2021») в заголовке и в течение недели записываю сделанные задачи.

Основная польза в том, что мне больше не нужно в разных ситуациях мучительно вспоминать, чем я занимался и что сделал. А такие ситуации в моём опыте возникают постоянно:
1. Ежедневные встречи с командой, на которых рассказываешь, чем занимался вчера.
2. Еженедельные отчёты о проделанной командой работе, для которых каждый член команды составляет список сделанных им задач.
3. Ретроспектива: понять, на что ушло время вместо важных запланированных задач.
4. Performance review: выделение основных достижений за последние полгода.
5. Подготовка к поиску работы: список освежает память при составлении резюме и рассказе о прошлом опыте.

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

📏 Размер пулреквестов — 80% успеха

Чем меньше пулреквесты — тем лучше. Большие PR демотивируют ревьюеров и снижают качество ревью, потому что сложно удерживать объём изменений в голове.

Если получается большой пулреквест, возможно вы смешали в нём правки в разных частях системы, требуемые для решения исходной задачи. Такие правки обычно можно разбить на отдельные PR: например, отделить новые UI-компоненты от реализации страницы с их использованием.

Ещё один случай больших PR — рефакторинги. Обычно их можно разделить на две части:
1. Содержательные изменения в какой-то части системы
2. Шаблонное обновление остального кода

Отделите первое от второго, и вы сэкономите время и силы ревьюеров, которым не очень важен бойлерплейт.

В завершение про размер пулреквестов: не поддавайтесь соблазну докинуть новую функциональность в уже открытые PR. Новая функциональность — новый пулреквест. Это опять же про самодостаточные изменения и внимание ревьюеров, которое не бесконечно.

📝 Описание изменений

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

Не ленитесь описать это прямо в PR, не все открывают прилинкованные задачи, и в них может не хватать контекста.

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

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

Не стесняйтесь сопроводить PR собственными комментариями на отдельных участках кода, чтобы:
— указать порядок чтения;
— прояснить мотивацию к конкретным изменениям;
— явно обратить внимание на сложные места;
— явно запросить обратную связь, если сомневаетесь в своём коде.

🕵️ Ревью собственных пулреквестов

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

🔔 Уведомления о ревью

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

🤝 Явное обозначение намерений в комментариях

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

Conventional Comments — хороший пример готовых соглашений для обозначения намерений.
👍38
С наступающим 2025

Давно ничего не писал, собрался с силами и вернулся к давно забытому жанру итогов года: https://andrew-r.ru/notes/bye-2024/
30👍15👎4
Мониторинг падений браузера

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

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

Как выяснилось, существует экспериментальный Reporting API, позволяющий отслеживать как падения, так и другие виды проблем, например, нарушения политик безопасности (вроде Content Security Policy) и использование устаревших фич.

Reporting API предоставляет два основных способа получения отчётов о проблемах:
1. Глобальный класс ReportingObserver, позволяющий подписаться на предупреждения и как-либо их обрабатывать через JavaScript; так как это клиентский API, он не отслеживает падения.
2. HTTP-заголовок Reporting-Endpoints, задающий серверные эндпойнты, на которые бразуер должен отправлять собранные отчёты; этот способ покрывает все виды отчётов, включая падения.

На портале Chrome for Developers есть хороший обзор Reporting API.

API всё ещё не стабилен, спецификация находится в статусе черновика, и пока она реализована не во всех основных браузерах. Несмотря на все эти оговорки, аналогов Reporting API нет, и его уже используют, например, в Figma.
👍254