
Чему учит выкладывание бесплатной утилиты в люди
Ты пишешь программу для себя. Она работает. Выкладываешь на GitHub, потому что жалко держать в столе, да и вдруг кому пригодится.
А потом приходит человек. У него другая версия Windows, антивирус, которым ты не пользуешься, путь к папке на кириллице, отсутствие прав администратора и полное отсутствие представления о том, как твоя штука должна себя вести. И пишет: «не работает».
Вот с этого сообщения код перестаёт быть кодом и становится продуктом. Никто не предупреждает, что это две совершенно разные работы, и вторая занимает куда больше времени, чем планировалось.
Дальше про то, чему меня научил этот переход. Без историй успеха: тут не про то, как собрать звёзды на гитхабе, а про то, что реально происходит, когда твою программу запускают чужие люди на чужих машинах.
Кому пригодится: если у вас есть проект в столе и вы думаете его выложить; если уже выложили и утонули в вопросах; или если просто любопытно, из чего состоит работа, которую не видно со стороны.
Содержание
- Момент, когда проект перестаёт быть твоим
- «У меня работает» ничего не значит
- Что ломается у людей и никогда не ломается у тебя
- Антивирус против вас лично
- Багрепорт от человека, который не программист
- Ваши пользователи не заходят на GitHub
- Почему нельзя делать всё, что просят
- Сколько стоит бесплатное
- Что бы я сделал иначе с самого начала
- Частые ошибки
- Короткий итог
Момент, когда проект перестаёт быть твоим
Пока программой пользуетесь вы один, у неё нет ни одной проблемы. Все зависимости на месте, пути правильные, права есть, а главное - вы точно знаете, как ей полагается работать, и подсознательно обходите острые углы, даже не замечая этого.
Первый чужой запуск ломает эту идиллию целиком.
И вот тут выясняется неприятное: написание кода было меньшей частью работы. Дальше идёт установка, обновление, объяснения, диагностика по скриншотам, отказы в фичах, и всё это не заканчивается никогда. Код можно дописать. Продукт дописать нельзя.
Тут пройдемся быстро по примеру. У меня довольно богатая документация, в которой НАПИСАНО АБСОЛЮТНО ВСЁ. Для того, чтобы те, кому всё таки не лень что-либо прочитать и узнать как устроена та или иная функция, то это станет огромным плюсом, это ведь просто прекрасно. Жалко, что реально что-то изучить и потратить на это 5 минут никто не хочет и бывает такие глупости спрашивают
«У меня работает» ничего не значит
Самая бесполезная фраза в разработке, и говорят её все, включая меня.
Дело в том, что ваша машина - наименее показательная машина на свете. На ней стоят все нужные библиотеки, лежат правильные пути, включён режим разработчика, антивирус давно получил исключение для вашей папки, а права администратора вы выдаёте не глядя, потому что привыкли. Плюс вы знаете, куда нажимать.
То есть «у меня работает» описывает ровно одну конфигурацию из всех возможных - ту, которая гарантированно работает. Информации в этом ноль.
Лечится это скучно и однозначно: чистая виртуалка. Не «почти чистая», не «я там только Visual Studio поставил». Свежая система, обычная учётная запись без прав администратора, ничего лишнего. Первый запуск делаете там, и половина будущих вопросов отваливается ещё до релиза новых обновлений и прочего.
Заводится такая машина один раз, а окупается с первого же раза, когда ловите на ней то, что у себя не воспроизвели бы никогда. Всем рекомендую способ проверки!
Что ломается у людей и никогда не ломается у тебя
Список из тех, что собираются годами. Он предсказуемый, и в этом хорошая новость: почти всё можно перекрыть заранее.
Путь с кириллицей и пробелами. C:\Users\ту пица\Загрузки\. Классика, на которой спотыкается всё, что кое-как обращается с путями. У вас папка называется dev, поэтому вы этого не увидите никогда.
Запуск прямо из архива. Человек скачал zip, дважды кликнул по файлу внутри, не распаковывая. Windows раскрывает это во временную папку, программа пишет туда настройки, а при следующем запуске их нет. Пользователь уверен, что программа «сбрасывается сама»/как-то криво работает, хотя это может быть в корне неверно.
Нет прав администратора. Особенно на рабочем компьютере, где их и не будет. Если ваша программа без них не работает - это надо сказать до скачивания, а не в момент запуска.
Нет интернета ровно в тот момент, когда он нужен. Если что-то докачивается при первом старте, то первый старт становится самым хрупким местом всей программы. А ещё этот момент отлично совпадает с корпоративным прокси, который режет всё незнакомое.
Второй монитор с другим масштабом. Окно уезжает за край, элементы налезают друг на друга, кнопка «дальше» оказывается за пределами экрана. Вы этого не увидите, у вас один монитор со стандартным масштабом.
Я всегда такие истории не понимал, когда ещё кто-то ставит себе кастомные разрешения, потом ты сидишь и не понимаешь что не так с интерфейсом, я же тестил и всё было гуд.
Региональные настройки. Разделитель дробной части, формат даты, кодировка в консоли. Мелочь, которая роняет разбор чисел на ровном месте.
Старая сборка системы. Человек не обновлялся три года и не собирается.
Ты можешь хоть 100 раз указать, что приложение работает на win 10/11, а так называемый old сидит на своей 7ой винде и говорит, что это у тебя программиста руки кривые, ничего не работает.
Общее правило, которое я вывел для себя: любое ваше предположение о среде - это будущее сообщение об ошибке. Не «наверное, у всех есть», а «у кого-то точно нет».
Антивирус против вас лично
Отдельный раздел, потому что для маленькой бесплатной программы под Windows это проблема номер один, и она не техническая, а экономическая.
Посмотрите на свою утилиту глазами антивируса. Исполняемый файл без цифровой подписи. Скачан из интернета. Просит права администратора. Лезет в сеть. Возможно, что-то докачивает при первом запуске. Возможно, ставит драйвер.
Каждый пункт по отдельности - подозрительный. Вместе - это описание того, что антивирус создан останавливать. Он не ошибается по глупости, он делает ровно свою работу: программа, которую никто не подписал и которую он видит впервые, ведёт себя как то, от чего он защищает.
Что из этого выходит на практике:
- SmartScreen показывает синее окно «Windows защитила ваш компьютер», и кнопка «всё равно выполнить» спрятана под ссылкой «подробнее». Часть людей до неё просто не доходит.
- Файл тихо исчезает из папки загрузок. Человек уверен, что скачивание не удалось.
- Пользователь пишет публично, что вы распространяете вирус. Он не злодей, он честно передаёт то, что увидел.
Чем это лечится, по возрастанию цены:
Написать об этом заранее и прямо. Самое дешёвое и самое действенное. Раздел в README: файл не подписан, вот почему антивирус ругается, вот хеш файла, вот как проверить. Человек, которого предупредили, реагирует принципиально иначе, чем человек, которого напугали. Это буквально бесплатно и снимает больше половины паники.
Отправлять ложные срабатывания вендорам. У всех крупных есть форма для этого, и она работает. Медленно, по одному вендору, и после каждой новой сборки заново, потому что хеш поменялся.
Купить сертификат для подписи кода. Работает лучше всего и стоит денег каждый год. И вот тут честно: для бесплатного проекта это расход, который часто нечем оправдать. Вы платите живые деньги за то, чтобы люди не боялись программы, которую вы отдаёте даром.
Нормальный исход для маленького проекта - жить без подписи и компенсировать это честным README. Это не поражение, а трезвый расчёт.
Далее пойдет талмуд о том, как я устал. мой проект Zapret2UI напрямую взаимойдействует с трафиком пользователя(интернетом типо). Конечно системе это не нравится и она совершенно спокойно ложит движок/всю программу под карантин, иногда ты даже можешь не успеть добавить в исключение его, т.к решаешь здесь не ты, а система безопасности, которая строилась десятилетиями.
Каждый раз слышать одно и то же о том, что вообще-то мне касперский сказал, что здесь троян, и вообще вы блин такие плохие тут, вирусы распространяете. А что делать если антивирус удалил что-то и теперь ничего не работает. Чего я только не видел, иногда читаешь подобные сообщения и не понимаешь это тебя троллят или всё таки человек реально не понимает что делать.
Багрепорт от человека, который не программист
«Не работает».
Это не грубость и не лень. Это исчерпывающее описание всего, что человек смог наблюдать. Он не знает, что бывают логи. Не знает, что версия имеет значение. Не догадывается, что «не работает» имеет полсотни разных смыслов, и вы не телепат.
Просить его научиться - бессмысленно, он не за этим пришёл. Значит, добывать данные надо так, чтобы от него ничего не требовалось.
Скриншот вместо описания. Всегда. Одна картинка содержит версию в заголовке, текст ошибки, состояние интерфейса и очень часто сам ответ на вопрос. Просить надо именно скриншот: это единственное, что умеют все.
Кнопка «собрать диагностику в файл». Потому что фраза «пришлите лог из папки %APPDATA%» не сработает никогда. Одна кнопка, один файл на рабочем столе, «прикрепите его сюда». Это, пожалуй, самая окупаемая кнопка во всей программе.
Версия в заголовке окна. Мелочь, которая экономит бесконечный круг переписки «а какая у вас версия». Раз она в заголовке, она автоматически попадает на скриншот.
Тексты ошибок вместо кодов. Не «Error 0x80070005», а «нет прав администратора, запустите от имени администратора». Код нужен вам, а человеку нужно, что делать дальше.
И главная мысль всего раздела: каждый вопрос, который вам приходится задавать пользователю, - это ваша недоработка. Спрашиваете версию? Значит, её не видно на экране. Спрашиваете, что было в логе? Значит, лог неудобно достать. Каждый такой вопрос можно один раз убрать в коде вместо того, чтобы задавать его до конца жизни.
"Добрый день, к сожалению кнопка включить обход не активна, можете подсказать где я криворук?" сообщение тг чате проекта, и вот я вообще не понимаю что именно у него не работает и прошу логи скриншотом для того чтобы помочь человеку. Как ни крути пользовательский интерфейс решает о том, кому и как будет удобно пользоваться вашим уже продуктом
Ваши пользователи не заходят на GitHub
Смотрю на собственный репозиторий: 39 звёзд и ноль открытых issue. При этом в телеграм-канале люди пишут регулярно.
Первый вывод напрашивается приятный: багов нет. Вывод неверный.
Issue - инструмент разработчика. Чтобы его завести, надо иметь аккаунт на GitHub, понимать, что такое issue, не бояться формы на английском и вообще считать, что твоё сообщение уместно. Обычный пользователь не проходит ни один из этих барьеров и не должен. Он напишет в чат, где уже сидит. Или в комментарий под видео. Или не напишет вообще и просто удалит программу.
Отсюда три вещи, которые стоит принять сразу:
Количество issue не говорит о количестве проблем. Оно говорит о количестве пользователей, которые умеют заводить issue. Это разные числа, и второе сильно меньше.
Тишина - это не хорошая новость. Большинство столкнувшихся с проблемой не сообщают о ней. Они уходят. Вы никогда не узнаете, сколько человек скачало, запустило, увидело окно антивируса и удалило. Проще просто заменить утилиту на аналог, в случае первых же проблем.
За обратной связью надо идти самому. Туда, где люди уже есть. Для меня это телеграм-канал, и это единственный работающий канал связи с реальными пользователями. GitHub при этом остаётся местом для кода и релизов, но не для разговора.
Issue увидеть было бы неплохо для улучшений, но мало кому это надо, даже из тех кто действительно понимает что это такое и как можно сообщить о проблеме
Почему нельзя делать всё, что просят
Каждая отдельная просьба звучит разумно. Проблема в том, что их много, и вместе они превращают простую программу в панель управления космическим кораблём.
Три вопроса, которые я задаю себе, прежде чем что-то добавить:
Это нужно многим или это нужно одному настойчивому? Громкость просьбы и её распространённость - вообще не связанные вещи. Один человек, написавший пять раз, ощущается как пятеро.
Что я обязуюсь поддерживать навсегда, если сделаю это? Вот главный вопрос. Фича - не разовая работа, а обязательство: её придётся чинить, тестировать при каждом изменении и объяснять в документации. Полчаса работы могут обернуться годами сопровождения.
Что она ломает? Каждая новая настройка удваивает количество сочетаний, которые надо проверять. Пять галочек - это тридцать два состояния, и в каком-то из них программа обязательно ведёт себя странно. Проблем с этим просто невозможно посчитать, слишком много рабочего функционала всегда ведет за собой баги, даже если не сразу, то в будующем они обязательно появятся.
Отказывать тяжело, особенно когда отдаёшь бесплатно и кажется, что не имеешь права. Но отказ - это тоже работа над продуктом, причём более ценная, чем очередная галочка. Простая программа, делающая одно дело, живее сложной, которая умеет всё и путается в собственных настройках.
Помогает заранее написанное «чего эта программа не делает». Не в момент спора, а спокойно, в README. Тогда отказ ссылается на правило, а не выглядит личным.
"Добавить возможность смены DNS для всех адаптеров принудительно, Добавить основные типо dns.malw.link, comss dns, xbox dns, adguard, dns sb и т.д." Реальная просьба в моем чате телеграмма, которая звучит очень круто, получать доступ к нейронкам с помощью смены днс звучит очень круто, но лично я это не поддерживаю(отдавать кому попало свои данные). Для меня это полный бред, лучше пользоваться квн. Реальная просьба, реальный отказ, всё просто. Никогда не ведитесь на поводу аудитории, кстати, всегда плохо заканчивается. Вы уже как бесплатный работник будете спустя некоторое время.
Сколько стоит бесплатное
Разговор, которого обычно избегают, потому что «ну ты же сам захотел».
Деньги. Домен, если он нужен. Сертификат подписи, если решились. Это ещё ладно.
Время. Вот тут настоящая цена. Поддержка не разовая, она постоянная и растёт вместе с числом пользователей. А количество ваших часов не растёт вообще. В какой-то момент график поддержки пересекается с графиком свободного времени, и дальше проект начинает есть то, чего у вас нет.
Нервы. Есть неприятная асимметрия: сотня довольных людей молчит, один недовольный пишет. И запоминается именно он. Плюс отдельный жанр сообщений в духе «почему до сих пор не починили», адресованных человеку, который вообще ничего не должен.
Что с этим делать, по опыту:
- Заранее решить, сколько часов в неделю вы на это тратите, и написать это в README. Границы, объявленные заранее, читаются как правила. Те же границы, объявленные в момент раздражения, читаются как хамство.
- Не обещать сроков. Никогда. Сорванный срок в бесплатном проекте бьёт по вам сильнее, чем отсутствие срока. Тебе обязательно напомнят о том, что вообще-то обещал в N дату релиз.
- Разрешить себе паузу. Проект без обновлений месяц - это нормально. Проект, брошенный из-за выгорания, - уже нет.
Я вообще занимаюсь Zapret2UI в свободное время, когда я сам хочу что-то сделать, решить проблему, которая касается именно меня. Я никогда ничего не обещаю, если даже ещё не начал этого делать, нужно верно оценивать свои силы и время, я лучше месяц не буду открывать vsc, чем пытаться тужится чтобы что-то новое добавить.
Что бы я сделал иначе с самого начала
Короткий список того, что стоило завести в первый день, а не на сотом пользователе.
- Чистая виртуалка до первого релиза, а не после первых жалоб.
- Версия в заголовке окна и в логе. Пять минут работы, экономят сотни сообщений.
- Кнопка сбора диагностики раньше, чем вторая фича. Она важнее любой функциональности, потому что без неё вы чините вслепую.
- README с разделом «известные проблемы» сразу, включая честный абзац про антивирус. Не после того, как об этом спросят двадцать человек.
- Написанные границы проекта: что он делает, чего не делает и делать не будет.
- Один канал для связи, обозначенный явно. Иначе вопросы приходят отовсюду и теряются.
Ничего сложного в этом списке нет. Всё дело в том, что на старте кажется, будто это преждевременно, а на самом деле это ровно то, что определяет, сколько времени проект будет у вас забирать.
Частые ошибки
- Тестировать на своей машине и считать, что этого достаточно. Ваша машина - единственная конфигурация, где всё точно работает.
- Считать, что мало issue значит мало багов. Это значит мало людей, умеющих их заводить.
- Обижаться на «не работает». Человек описал ровно то, что видел. Данные добывать - ваша задача, не его.
- Спрашивать то, что можно было показать. Каждый повторяющийся вопрос лечится один раз в коде.
- Молча игнорировать проблему с антивирусом. Она не рассосётся, а репутационно бьёт сильнее любого бага.
- Соглашаться на все просьбы. Каждая фича - обязательство навсегда, а не разовая работа.
- Обещать сроки. Особенно там, где вы никому ничего не должны.
- Считать своих пользователей похожими на себя. Они не читают README, не знают, что такое лог, и запускают программу из архива.
Короткий итог
- Код и продукт - разные работы. Первая заканчивается, вторая нет. Выкладывая утилиту, вы подписываетесь на вторую.
- «У меня работает» не несёт информации: ваша машина - самая нерепрезентативная из всех. Чистая виртуалка решает больше, чем любая аккуратность в коде.
- Любое предположение о среде пользователя - будущий баг. Кириллица в пути, запуск из архива, отсутствие прав, второй монитор, старая система.
- Неподписанная программа выглядит для антивируса ровно как то, что он останавливает. Сертификат стоит денег, честный README - ничего, и работает почти так же хорошо.
- «Не работает» - это полное описание наблюдаемого, а не грубость. Стройте воронку, которая добывает данные без участия человека: скриншот, кнопка диагностики, версия в заголовке.
- Каждый вопрос пользователю - ваша недоработка, которую можно один раз убрать в коде.
- Тишина не значит, что всё хорошо. Большинство ушедших не пишут ничего.
- Отказ в фиче - тоже работа над продуктом. Каждая галочка удваивает пространство состояний и берётся на пожизненное содержание.
- У бесплатного есть цена, и платите её вы: временем, деньгами на подпись и нервами. Границы надо объявлять заранее, а не в момент, когда достало.
Если из всего этого запомнить один пункт - пусть это будет чистая виртуалка. Она превращает половину будущих сообщений «не работает» в баги, которые вы находите сами, до того как их найдут люди.
Мой проект: Zapret2UI.
Что почитать
- Keep a Changelog - как вести список изменений, чтобы им пользовались
- Semantic Versioning - зачем нужны три числа в версии и что они обещают
- Choose a License - выбор лицензии на пальцах
- Microsoft: подпись кода и репутация в SmartScreen
- Microsoft: отправка файла на анализ ложного срабатывания
Browse the rest of the knowledge base — the neighbouring topics are covered too.
