- PVSM.RU - https://www.pvsm.ru -

А теперь немного усложним задачу. Будем писать код для людей!
Объясню, что я имею в виду: я говорю о коде, с которым смогут взаимодействовать другие люди. В частности, я имею в виду искусство создания удобных фреймворков, библиотек, API, SDK, DSL, встроенных DSL или даже языков программирования.
Писать такой код гораздо сложнее, потому что ты не только говоришь компьютеру, что делать, но и вступаешь в борьбу с ментальной моделью твоего кода в глазах другого пользователя. Это в равной степени computer science и психология . Как сделать так, чтобы этот человек понял твой код?
Ричард Фейнман как-то сказал: «Представьте, насколько сложнее была бы физика, если бы электроны имели чувства». Он говорил это в другом контексте, но мне кажется, это частично описывает и программирование для людей. У человека, интерпретирующего твой код, есть чувства!
Давайте поговорим о том, как упростить ему задачу.
Разумеется, нужно обязательно прислушиваться к своим пользователям и принимать во внимание их отзывы. Как оказалось, основную часть отзывов оставляют опытные пользователи, постоянно работающие с вашим продуктом!
Как это повлияет на распределение получаемых отзывов? Не будет ли оно перекошенным? И как с этим связан рисунок самолёта?

Конечно же, здесь идёт речь об ошибке выжившего [2]. Есть пользователи, которые не применяют ваш инструмент, потому что не смогли освоить его. И их отзывы мы обычно никогда не слышим!
У потребительских продуктов уже давно есть хакеры роста, оптимизирующие каждую часть воронки онбординга. Для инструментов разработчика тоже нужен такой подход. Процесс освоения нельзя придумывать уже после того, как вы создали продукт. Освоение — это и есть продукт!
Вплоть до того, что я рекомендую реструктурировать продукт целиком, чтобы обеспечить быстрый онбординг. Избавьтесь от обязательной конфигурации. Сделайте так, чтобы настройка токенов API была до абсурда простой. Устраните все препятствия. Обеспечьте пользователям возможность работать с продуктом на ноутбуке спустя максимум пару минут.
Вы можете заявить что-то типа: «Да кого волнуют ленивые пользователи». Отвечу вам так: сегодня уже есть примерно семь миллиардов инструментов разработчика. У пользователей нет ни лишней энергии, ни терпения, чтобы разбираться, чем ваш пакет NPM кэша LRU лучше остальных. Так что простите!
Люди замечательно справляются с сопоставлением паттернов, в отличие от компьютеров, следующих булевой логике и строгим командам. Часто документация инструментов разработчика структурирована как компьютерная программа. Она начинается с базовой модели данных, взаимосвязей и атомов, с «базовых концепций», с объяснения того, как конфигурировать и выполнять операции.
А люди учатся иначе.
Сразу после того, как я написал предыдущий параграф, в Twitter (X) обнаружился пост, сформулировавший как раз то, что мне хотелось сказать:
Слишком многие книги и туториалы по программированию устроены так: «давайте построим дом с нуля, кирпич за кирпичом». А мне нужно что-то такое: «вот вам готовый дом, давайте изучим его, поменяв что-нибудь и отметив, что поменялось» — Крис Элбон (@chrisalbon) [3]
Вместо того, чтобы писать хронику «базовых концепций» на пять тысяч слов, я советую придумать с десяток примеров. У такого подхода есть несколько преимуществ:
Печальная часть программирования заключается в том, что по умолчанию приходится исправлять те или иные ошибки. То есть пользователи будут больше всего времени тратить на то, чтобы понять, что не работает в вашем инструменте. Именно поэтому помощь им в достижении успеха — неотъемлемая часть продукта.
Вот краткий список:
Воспринимайте каждую ошибку как возможность направить пользователя по правильному пути. Помещайте фрагменты кода в исключения. Генерируйте полезные уведомления, когда пользователи делают что-то странное. Делайте всё для того, чтобы пользователь достиг успеха.
Каждый новый концептуальный элемент, который нужно понять перед использованием инструмента — это преграда. Если таких элементов два-три, то это нормально. Но никто не захочет заморачиваться изучением восьми новых концепций.

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

Вероятно, к работе можно приступить, не осваивая подавляющее большинство этого. Но когда мне нужно изучать новые концепции, у меня начинает болеть голова. Слишком много концепций!
Есть что-то очень изящное во фреймворке из всего трёх-пяти концепций, которому при этом удаётся быть невероятно мощным. Я помню то чувство, когда впервые попробовал React и спустя один-два часа разобрался со всеми концептуальными преградами. Всего несколько относительно простых кирпичиков, позволяющих построить целый собор. Настоящая магия.
Уточню, что сложность не в том, чтобы снизить количество концепций. Сложность в том, чтобы при этом сохранить количество всего того, что можно создать при помощи продукта. Или, по крайней мере, снизить количество первых сильнее, чем количество вторых. Я говорю об этом, потому что могу представить «спираль смерти тупого упрощения инструментов разработчика»:
Не знаю, происходит ли такое в действительности, но считаю, что существует уровень «плохих» упрощений. В конечном итоге вам нужно изменить баланс между «сложностью» (тем, что нужно знать) и «возможностями» (тем, что можно создать). Самые потрясающие инструменты способны снизить сложность на 90%, сохранив тот же уровень возможностей. Но я бы согласился и на инструмент, снижающий сложность на 90% с уменьшением возможностей на 10%. Вполне нормальный компромисс!
Этот пункт связан с предыдущим. Допустим, вы добавляете в свой фреймворк элемент, получающий какие-то значения и вычисляющий на их основе новые значения. Как его назвать? Вычислительным узлом? Блоком вычислений? Думателем?
Нет! Нужно назвать его функцией!

Если это выглядит как утка, плавает как утка и крякает как утка, то это, вероятно, и есть утка.
Возможно, у этого элемента есть тонкости, немного отличающие его от функции. Например, значения кэшируются. Но он достаточно похож на функцию!
Если назвать его функцией, то можно воспользоваться уже имеющейся у пользователя ментальной моделью того, что умеет функция. А это сэкономит вам 90% времени на объяснение возможностей элемента.
Люди будут делать с вашей кодовой базой безумные вещи. Они будут брать написанное вами и засовывать в цикл for внутри функции, которая находится внутри чего-то ещё. Люди изобретательны!
Поэтому почти всё в вашем фреймворке должно быть «программируемым».
Это целый класс проблем, связанных друг с другом и решаемых схожими способами.
Позвольте вызывать всё напрямую в коде, а не через CLI. Избегайте конфигураций и превратите их в SDK или API. Упростите параметризацию, чтобы можно было создать n вещей, а не только одну.
У такого подхода есть неожиданное преимущество — иногда пользователи самостоятельно могут обнаруживать новые сценарии использования. Воспользуйтесь стремлением людей к «хакингу» поверх вашего фреймворка. Эти пользователи принесут определённое количество проблем, но не мешайте им! Возможно, они на пороге открытия чего-то неожиданного.
Допустим, вы создаёте инструмент, исполняющий Jupyter notebook в облаке, и у вас есть функция run_notebook, получающая список ячеек (с компьютерным кодом) или что-то подобное.
Как пользователь может указать, какой образ контейнера следует использовать? У нас есть несколько вариантов:
image=..., который нужно указывать всегда.image=..., который по умолчанию имеет какое-то базовое значение, используемое большинством библиотек data science; пользователь может его переопределять.Какой вариант использовать? Если вы хотите минимизировать объём усилий пользователей, сохранив при этом поддержку самого широкого множества сценариев использования, то я бы выбрал последний. Но у этих вариантов, за исключением первого, есть некоторые проблемы:
Если стандартные значения не подходят в 97%+ случаев, а магия — в 99% случаев, то будьте аккуратны с их использованием. Разумеется, это не строгие значения, но смысл в том, что надо всё продумывать.
Можно подумать, что цель разработчика инструмента — минимизация количества кода, который придётся писать пользователю. Но кодинг — это не гольф!
Я провожу здесь аналогию с разницей между Perl и Python. Разработчики Perl упорно стремились оптимизировать код, максимально сокращая его, из-за чего каждая программа выглядела, как строка из одних специальных символов. Потом появился Python, и его код был на 50% длиннее. Он никогда не пытался стать самым коротким! Но оказалось, что код на Python очень удобен для чтения, а потому гораздо понятнее. А люди читают в десять раз больше кода, чем пишут.
То же самое относится и к синтаксическому сахару. Есть искушение добавить специальный синтаксис для наиболее распространённых сценариев использования инструмента. Но это часто мешает целостности и снижает очевидность способов кастомизации кода. Поэтому если синтаксический сахар не покрывает 99%+ случаев, то, вероятно, добавлять его не стоит.
Мы добрались до конца статьи, но мне бы хотелось продолжать обсуждать множество других тем:
И, наверно, многое другое. Возможно, я напишу об этом ещё один пост!
В том числе и о том, что я считаю самым удивительным: почему крупные компании обычно неспособны выпускать высококачественные инструменты разработчика.
Я иногда думаю, что сложность проектирования инструмента для никогда не работавшего с ним пользователя похожа на сложность написания популярной песни. Продюсер прослушает песню тысячу раз. Но даже слушая её в 999-й раз, он должен представлять, как она будет звучать для человека, слышащего её впервые, что, как мне кажется, крайне сложно.
Скорее всего, именно поэтому я пишу инструменты разработчика, а не сочиняю попсу.
Автор: ru_vds
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/interfejsy/398378
Ссылки в тексте:
[1] мышления: http://www.braintools.ru
[2] ошибке выжившего: https://en.wikipedia.org/wiki/Survivorship_bias
[3] Крис Элбон (@chrisalbon): https://twitter.com/chrisalbon/status/1831497223076770217?ref_src=twsrc%5Etfw
[4] Источник: https://habr.com/ru/companies/ruvds/articles/847664/?utm_source=habrahabr&utm_medium=rss&utm_campaign=847664
Нажмите здесь для печати.