Сообщение об ошибке, от которого не горит

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

Сижу, значит, программирую, внезапно консоль заливает красным, и вылезает вот это:

Uncaught Error: Bad dependency path or symbol.
  // стектрейс из скомпилированного (!) кода...
  // стектрейс из внутренних библиотечных функций...
  //
  // скомпилированного... напомню, это dev-режим.

Да, это сообщение об ошибке.
Да, это всё сообщение.
И да, это плохое сообщение.

Дальше — простыня, почему оно плохое.

Как надо

Хорошее сообщение об ошибке следует двум главным принципам:

  1. Оно опирается на факт, что всё горит, и починить ошибку надо немедленно.
  2. Заботится о разработчике, а не обвиняет его в глупости.

Из этих принципов я бы вывел 4 правила, что хорошее сообщение:

  1. Говорит, что именно сломалось — какой модуль, функция и т. д.
  2. Где именно сломалось — как ошибку найти.
  3. Почему оно сломалось — как ошибку воспроизвести, что не сходится.
  4. Как это починить — что на что заменить, чтобы заработало.

Говорит, что именно сломалось

— Ваше приложение не работает.
— Да, но почему?
— Потому что оно сломалось
¯\_(ツ)_/¯

То, что приложение не работает, я уже знаю — оно, блин, не работает. Мне как бы нужно понять из‑за чего.

В ошибке выше, вроде, даже написано, что сломалось, вот — Bad dependency path or symbol. Но что именно‑то: bad dependency path или bad symbol? Если символ, то какой? Если путь до зависимости, то до какой?

Почему бы, например, не сделать так?

Bad dependency path.
  Cannot find module "superModule".

Указывает, где сломалось

Чтобы что‑то починить, надо исправить код. Чтобы в коде что‑то исправить, надо найти, что
— Ваш Кэп

В эпоху до сборки фронтенда (помните, IE7, FTP, jQuery, эх!..) всё было просто. Стектрейс сам говорил, на какой строке беда. Сейчас браузерный стектрейс может не помочь.

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

Bad dependency path at line 42, character 88 in "entryPoint.js".
  Cannot find module "superModule".

Объясняет, почему оно сломалось

С любовью, вечно ваш «undefined is not a function»

Да, если произошла низкоуровневая ошибка, синтаксическая например, надо об этом написать. Но undefined is not whatever как бы так сказать, is not enough. Ткните, пожалуйста, носом в то место, которое не работает: в поле объекта, название функции, метода.

Если произошла высокоуровневая ошибка, объясните, что именно пошло не так: почему здесь нужен другой аргумент, зачем указывать абсолютный путь и т. д. Дайте ссылку на документацию, это полезно. Даже если документация скудная. Даже если API в ней не нуждается.

Bad dependency path at line 42, character 88 in "entryPoint.js".
  Cannot find module "superModule".
  Expected one of extensions: "js", "jsx", "ts", "tsx", "mjs", but tried to import "".

Инструктирует, как починить

— Хм, а как это починить?
— Ну вы держитесь здесь, вам всего доброго, хорошего настроения и здоровья

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

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

Ещё один хороший способ — показать примеры работы функции, что она вернёт при каких аргументах. Так делает Lodash в jsdoc и многие модули Python в docstring.

Да, это запарно. Но разработчики скажут спасибо.

Bad dependency at line 42, character 88 in "entryPoint.js".
  Cannot find module "superModule".
  Expected one of extensions: "js", "jsx", "ts", "tsx", "mjs", but tried to import "".
  Check your import extension and make sure file exists.
  Note that this lib supports only imports with direct link to a file with its extension.

Опирается на факт, что всё горит

Тут всё как у Ситника в докладе о продвижении проектов.

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

Заботится о разработчике

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

Разработчики не тупые. Им может не хватать контекста, знаний, опыта. А ещё бывает, что другой third‑party код конфликтует с вашим, или браузер лагает, или интерпретатор, или сеть, или железо… ну вы поняли.

Ну и вообще…

Это всё — просто эффективная коммуникация и желание помочь. Ильяхов в Правилах деловой переписки писал подобное. А сообщение об ошибке — чем не переписка?

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

Ссылки в конце поста

Из моего блога:

Из внешнего интернета:

С кодом:

Грязная архитектура

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

Проблема

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

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

Ну и сроки, да. Они всегда горят. Разработчики стали той собакой, у которой «всё хорошо»:

Появились инструменты для решения проблем с рутиной. Манипуляции с ДОМ, запросы к серверу, обработка состояния, хранение данных — со всем этим нам стали помогать библиотеки и фреймворки.

Инструменты — это суперздорово, потому что они снимают с разработчиков нагрузку и позволяют сосредоточиться на бизнес‑логике приложения. Хорошо же? Да, хорошо, но только это чё‑то не работает, как задумано.

Мы всё ещё не уделяем достаточно внимания бизнес‑логике, а упарываемся по модным библиотекам (привет, Реакт!) и фреймворкам (привет, Ангуляр!). И спорим, что лучше, что хуже, на чём приложения моднее.

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

Инструмент не должен вообще ничего вам диктовать

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

Не должно быть никаких «Реакт‑приложений» или «Редакс‑приложений», потому что это инструменты. Реакт должен рисовать пиксели на экране. Редакс должен работать с состоянием. Всё.

А как надо, умник?

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

Бизнес‑правила — скелет, вокруг которого наворачивается мясо

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

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

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

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

А как же фигак‑фигак и в продакшен?

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

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

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

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

Ну и как тогда начать проект?

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

Но за меня на этот вопрос уже ответил Дэн Абрамов в твитере:

Всё зависит от бизнес‑правил. Проектируйте, опираясь на них

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

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

Ссылки

Конспект «Чистой архитектуры»

Дэн Абрамов в твитере

Урбанистика, доступность и будущее

Да‑да, это статья о доступности. Почти.

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

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

На днях проводил в голове аналогии между урбанистикой и разработкой интерфейсов. Придумал шутку:

Эт я к чему? Мы относимся к ошибкам городских проектировщиков серьёзно и говорим, что так нельзя делать, это вредительство. При этом верстаем кнопки дивами, и нам как бы ок.

А вот ещё шутка, зацените:

И проблема тут не в том, что «нас не учат» или «разработчики ленивые». Мы почему‑то не доросли до этого.

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

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

Программистам сейчас хорошо, нас носят на руках. Но однажды случится ошибка, которая всё изменит. Боб Мартин в своём докладе “The Future of Progamming” сказал:

We are facing a disaster… Civilization depends on us. It doesn’t understand it yet. We don’t understand it yet…

You cannot buy something without interacting with a software system, you cannot sell anything, you cannot get insurance… Anything you do in a modern world — you are interacting with a software system…

There is software that controls the throttle (in a car), there is software that controls the brakes… There is software that can control the steering wheel… How many people have been killed by cars? Dozens! We are killing people…

In one day one of us is going to do something dumb and… the result will be a catastrophe that will bring thousands of people to die… And when this happens, the politicians of the world will rise up and they will point their fingers right at us and they will ask us the question: “How could you have let this happen?”

And they will do the only thing they can do — they will legislate. They will tell us what languages we have to use, what platforms, processors we have to use, what books we have to read, what tests we have to pass, what signatures we have to get. They will regulate us, because we’re dangerous! We kill people

Давайте не будем ждать. Давайте позаботимся о будущем.

О нерадивых собачниках

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

Я сам собачник, у меня есть пёс. Он без привязи ни на метр не отходит, но я не отпускаю его с поводка. Потому что понимаю, что несу за него ответственность. Но многие другие по этому поводу совсем не парятся — отпускают собак, те гуляют сами по себе. Хозяев не волнует, что люди боятся собак, что кому‑то неприятен запах псины, а кто‑то не любит, когда его обнюхивает слюнявая морда.

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

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

Для чего нужны урны?

Для красоты. Для чего ж ещё?

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

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

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

Про загаженные пляжи можно даже не говорить. Неужели так трудно с собой свой мусор забрать? Возьми мешок, сложи мусор туда. Хотя зачем, кто‑нибудь придёт, уберёт. Только никто не придёт и не уберёт.

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

В общем, ненормально это всё, плохо это пахнет.

Раньше ↓