Прогресс с My Bar Web

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

  • Создание коктейлей. Люди давно спрашивали, есть ли десктоп-версия, а то создавать свои коктейли на телефоне очень неудобно,
  • Дать возможность делиться коктейлями или коктейльной картой с другими пользователями.

 Помимо практических задач у меня был чисто программерский зуд, хотелось погрузиться в современную веб разработку, Flutter и Dart, и это была самая приятная часть всего начинания!

 На сайте в одном из элементов FAQ я написал, что работаю над веб версией и просил писать на емэйл тем, кто хотел бы быть в числе первых бета-тестеров. К концу года мне написали больше ста человек! Собрав их всех в mailing list на moosend.com (который вдруг перестал быть бесплатным), я отправил всем письмо примерно следующего содержания:

  • Не успел сделать полноценную версию, но то, что есть, можно попробовать на mybar.app/app
  • Дизайн оставляет желать лучшего, с этим разберёмся потом
  • Работает только базовый функционал - можно залогиниться, посмотреть свою "барную полку", добавлять-удалять оттуда ингредиенты, смотреть "мои коктейли", "любимые" и шопинг лист ингредиентов
  • Работает шеринг по ссылке. Этой фичи нет даже в мобильном приложениии!
  • Пока нельзя создавать коктейли, нет поиска, интернационализации, фильтров

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

 Шеринг выглядит вот так:

 И отдельно радует, что на фронтенд-часть этой фичи ушло буквально пару часов. Просто вызывается Firebase Cloud function, которая возвращает ссылку.

Разработка

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

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

 Я пошел на Upwork, поискал фрилансеров по кодовому слову Flutter и написал одному русскому человеку с хорошей историей, хорошим рейтингом. Мы хорошо пообщались, но он очень быстро сказал что "тут всю систему надо менять". Рассказал мне, что есть парадигма BLoC, а у меня в коде какая-то мешанина, тестов нет, и что на рефакторинг надо будет потратить 20-50 часов при рейте 40 долларов в час. Я немного удивился, задумался, взял таймаут и пошел разбираться, что там вообще происходит в разработке на Flutter в народе.

 Не могу сказать, что я прямо в восторге от BLoC, а точнее, реализующих его библиотек, но это большой шаг вперед по сравнению с тем, что я раньше читал в официальной документации о Stateful Widget. Концепция появилась, похоже, в начале 2018-го - по крайней мере, тогда появилось вот это видео с конференции, на котором очень красиво в реальном времени нам показали, как разделить логику и представление. Базовая идея BLoC, грубо говоря, состоит в следующем:

  • Весь функционал приложения разделяется на "блоки" (BLoCs)
  • Каждый BLoC представляет из себя кусочек бизнес-логики приложения, который принимает события приложения (events) и производит состояния (states), при этом эти блоки ничего не знают про UI.
  • UI компоненты "слушают" изменения состояний и производят события, которые идут в соответствующие BLoC-и.

 Есть даже специальная библиотека bloc, созданная сторонним человеком, которая позволяет удобно реализовывать, создавать, получать и уничтожать эти самые "блоки", когда потребуется. Библиотека небольшая и простая.

 Здесь хочется пару слов сказать о Dependency Injection во Flutter. Идеология такая, что Виджеты (Widget) образуют иерархию, и каждый виджет может предоставлять (provide) какой-то компонент (блок) для всех наследников (в иерархии), либо потреблять его (consume). То есть, допустим, у меня на уровне всего приложения есть Authentication Bloc, и он доступен всем виджетам, в нем функционал аутентификации пользователя и текущее состояние (например, email залогиненного пользователя).

 Вообще в State Manangement Flutter-a много подходов. Один фрилансер говорил, что MobX это вещь и надо использовать его. Есть даже специальная страница документации, которая перечисляет все подходы, в том числе и BLoC. Их там штук 10 разных! Я глубоко в них не копался, и как мне показалось, радикальных различий между ними нет. Переводя BLoC на хорошо известные дизайны проектирования, блоки занимают место ViewModel (в MVVM) или Controller (в MVC). Блоки в свою очередь используют отдельно стоящие "сервисы", "провайдеры" и тому подобное, что по сути просто библиотеки сами по себе и к пользовательскому интерфейсу отношения не имеют.

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

Поиски фрилансера

 Это оказалось гораздо сложнее, чем я думал!

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

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

 Я получил около 20 предложений, кого-то позвал сам, и в итоге списался с 13 кандидатами. Первый быстро ответивший кандидат посмотрел код и сказал "надо всё переписать!", чем несколько усилил мой синдром самозванца. Когда мы созвонились и начали обсуждать эту идею более подробно, он не смог толком объяснить, в чем проблема текущего подхода, кроме того, что "я привык работать с А, а тут Б". На этом распрощались.

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

  • Посмотреть на документ, посмотреть на код, получить общее представление об организации кода
  • Написать небольшой одностраничный (максимум!) документ о том, как реализовать добавление коктейля в "favorites" (какие классы поменять, какие методы добавить итп).

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

 Один кандидат из Пакистана (25$ в час) даже почти справился, написал адекватный документик и даже прислал pull request с готовым кодом (хотя я не просил). Молодец! Правда, он посчитал, что добавлять коктейли в favorites нужно прямо из списка, так что воткнул иконку с сердечком прямо в каждый элемент списка коктейлей, а не как в Андроид приложении, где добавлять в favorites можно только из страницы коктейля. Пока что он единственный, кто сделал хоть что-то приемлемое.

 Еще один спустя 20 дней после первых сообщений предложил созвониться "to discuss the project". Я уже вернулся домой из отпуска и понял, что созваниваться для болтовни у меня уже времени нет, тем более в рабочие дни.

 Другой кандидат ответил сразу же, сказал "let me check it" и пропал на неделю. Потом я понял, что мне на самом деле отвечает другой человек. Я просто покажу скриншот:

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

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

 Один кандидат написал "I have checked the app, I can do next task". Когда я повторил, что жду документа, кандидат пропал.

 Еще один фрилансер посмотрел на документ, сказал что он работает с JSON, а не protobuf, что он может, конечно, разобраться, но мне это будет стоить дороже (а как же!). Ну надо же!

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

 Помимо предложений в Upwork мне стали написывать в WhatsApp! И почему-то это все были люди из Индии. То есть они нашли мое Андроид приложение, там указан телефон. И они просто в обход системы начали мне слать сообщения. Причем некоторые очень нагло писали: "I know you are reading my messages", ха-ха! Конечно, я их сразу блокировал. Кто-то даже написал мне на личный емэйл, видимо узнав о нем через расшаренный Google Doc.  Теперь жалею, что не сделал скриншоты всех этих WhatsApp переписок!

Мысли о будущем веб версии

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

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

  • Веб версия в каком-то виде - это хороший способ для шеринга коктейлей и бара. Дал ссылку и можно смотреть "коктейльную карту".
  • Возможно, с помощью Flutter можно создать приложение для iOS. Мне писали, что там до сих пор ничего хорошего из коктейльных приложений нет. В перспективе, может, приложение на Flutter заменит Android app, но есть большой вопрос, удастся ли сделать его рабочим оффлайн.

 В интернете уже полно хороших коктейльных сайтов, и я не хочу с ними всерьез конкурировать (а может быть, стоит?). Difford's guide и Inshaker - прекрасные ресурсы. На первый постоянно хожу посмотреть рецепты коктейлей, которых нет у меня. Нанять людей, платить им деньги - похоже на дополнительные обязательства. Нужно будет держать связь, больше думать о монетизации, поддерживать еще один "продукт". Сейчас приложение приносит какую-то небольшую денежку, а разработка и поддержка веба пока выглядит только как инвестиции (времени и денег) без перспективы прибыли. С другой стороны, если народ туда по какой-то причине потянется, то всегда можно будет придумать, как вывести его в плюс.

 Пока такие новости. Скоро напишу про новую версию Андроид приложения, обновление коктейлей и общение с IBA (международной ассоциации барменов).

Cheers!