Как стать автором
Обновить
0
ManyChat
Будущее мессенджер-маркетинга

Программирование в массы

Время на прочтение7 мин
Количество просмотров4.9K
Понимание даже основ программирования может упростить деятельность человека. Помимо очевидных вещей, таких как развитие абстрактного мышления или способность разделять задачу на меньшие части, я предлагаю пойти ещё дальше и воспользоваться основными подходами к разработке. На примере создания классической логической игры, проводя аналогию между визуальным и традиционным программированиями, я и хочу показать, как навыки разработки могут помочь в решении прикладной задачи. Желающих подискутировать на тему или поиграть в «Быков и коров» и выиграть приз — зову под кат.



Меня зовут Женя и я backend разработчик в компании ManyChat. Некоторое время назад ко мне обратилась команда HR с просьбой реализовать знакомую многим с детства игру «Быки и коровы» на базе нашего продукта. Позвольте добавить немного контекста. ManyChat — это инструмент для автоматизации взаимодействия между бизнесами и их клиентами, позволяющий ответить на общие вопросы через Facebook, а с недавнего времени SMS и Email. «Быки и коровы» — это логическая игра, в ходе которой за несколько попыток необходимо отгадать загаданное число. Многие могут знать её по игре Fallout, где необходимо взломать компьютерный терминал. Более подробно с правилами можно ознакомиться в конце статьи.

Визуализация


Что мы делаем перед тем как писать код сложной задачи? Идём к доске с маркером или берём в руки карандаш и бумагу и рисуем блок-схему или UML диаграмму, ведь визуализация — это наиболее естественный способ представления и восприятия информации для человека. Flow Builder — сердце нашей системы, базируется на различных объектах, графических элементах и правилах, по которым они взаимодействуют друг с другом. Я сказал бы, что это логическое продолжение объектно-ориентированного программирования. Так что я отбросил привычные инструменты и сразу перешёл к конструированию логики общения бота с игроком.

Flow игры «Быки и коровы»

Это очень удобно, поскольку UML диаграмма и Flow Builder практически тождественны. На этом шаге уже сочетаются проектирование с программированием. За несколько итераций я накидал flow и обозначил места взаимодействия с пользователем и с API. Полученный результат несколько отличался от исходного представления в моей голове — визуализация предоставила возможность посмотреть на задачу с другой стороны. Это хорошо, так как изменения в диаграмму вносить проще и дешевле, чем в код. Как мне кажется, смысл этого подхода уходит корнями к поговорке «семь раз отмерь, один — отрежь». Инженерам он должен быть особенно знаком и понятен.

Разграничение ответственности


Что должно быть реализовано на стороне ManyChat, а что на стороне кода? Ответ на этот вопрос поначалу мне не казался очевидным. Для взаимодействия на нашей платформе есть два инструмента: Dynamic Block и External Request. Они практически идентичны за исключением того, что первый выполняет запрос на удалённый сервер и идёт дальше к следующей инструкции, а второй позволяет прежде сопоставить данные ответа с переменными бота. В одной из первых версий я воспользовался Dynamic блоком и реализовал отправку турнирной таблицы из метода API прямиком в Facebook. Казалась бы, в этом подходе нет ничего плохого. Но если посмотреть немного дальше и предположить, что игрок захочет играть с помощью SMS — коду придётся узнать о канале коммуникации конкретного игрока. Это не кажется необходимым. В следующей версии я перевёл flow на работу с External Request, добавил запись ответа в пользовательские переменные и удалил любое упоминание о канале из кода. Теперь код игры можно использовать в другом приложении и реализовать любой желаемый интерфейс взаимодействия: от консоли до мобильного приложения. Было это отделение представления от управляющей логики согласно шаблону MVC или выделение ограниченных контекстов согласно подходу DDD — решайте сами. Главное здесь то, что не смотря на отсутствие требования, на подсознательном уровне я определил потенциально узкое место системы, которое в будущем могло бы создать проблемы.

Именование переменных


Именование переменных — одна из двух главных проблем программирования. Помимо переменных не менее важным является именование блоков. Многие пользователи не придают этому значения, не успевают оглянуться как flow превращается в набор Copy 1, Copy 2 и так далее. Это кратно усложняет понимание. Всё как с плохим классом — невозможно разобраться что он делает, не зайдя внутрь. Более подробно эту мысль раскрыл мой коллега. Если заинтересовались, предлагаю ознакомиться с его постом.

Стив Макконнелл в своей книге «Совершенный код» писал, что имя должно полно и точно описывать представляемую сущность. Думаю, с этим спорить сложно. Например, для булевых переменных я предпочитаю использовать префикс is. В таком случае читающему код уже по первым двум буквам становится понятно с чем он имеет дело. Что касается длины — желательно, чтобы она не превышала 20 символов (Gorla, Benander, and Benander, 1990). Чем меньше область видимости переменной, тем короче может быть её имя. Но так как все переменные в ManyChat имеют глобальную область видимости, стоит воспользоваться пространством имён. Для «Быков и коров» я использовал начальный сегмент в виде двух заглавных букв BC, производных от Bulls and Cows. Учитывая вышесказанное, у меня получилось имя переменной BC Is Victory — достаточно уникально и исчерпывающе, на мой взгляд.

DRY, KISS


Игра работает и, казалось бы, можно выдохнуть с чувством выполненного долга. Но мы-то знаем, что дальше идёт этап self-review и рефакторинга. При более детальном разборе можно заметить, как обработка стоп-слов и победа ведут на похожие блоки — призывы игрока к некоторым действиям. При этом проигрыш по непонятной причине живет своей жизнью. Объединение этих мест в одно кажется логичным шагом, позволяющим избежать дублирования, что в свою очередь приводит к повышению консистентности поведения и простоте сопровождения. Теперь, в случае необходимости изменения, нужно внести в единственный блок системы без изменений в других, что свидетельствует о том, что принцип Don’t repeat yourself применяется успешно.


Flow с соблюдением принципа DRY

Однако, не стоит останавливаться на достигнутом. Комплексные решения сложны в сопровождении. При возникновении ошибки локализовать её будет непросто, особенно спустя время, когда выпадешь из контекста. У нового человека уйдёт не мало сил, чтобы разобраться, что к чему. А ознакомиться придётся с каждым узлом, дабы не упустить ничего важного. Поэтому стоит воспользоваться принципом Keep it simple, stupid и разнести все возможные действия по отдельным местам. После декомпозиции у меня получилось 5 довольно простых для понимания flow. В качестве приятного бонуса данный рефакторинг удовлетворил Single responsibility принцип. Каждый flow имеет одну ответственность и эта ответственность полностью инкапсулирована в нём. Обращение происходит а-ля Black box, а по характеру возникшей проблемы её можно локализовать быстрее.


Flow с соблюдением принципа KISS

YAGNI


В одной из первых версий автоматизации были наработки по рассылке напоминаний о заброшенной игре и инструкций по получению подарков победителями. Реализацию первой идеи усложнили ограничения со стороны Facebook — с недавнего времени ужесточились условия отправки сообщений за пределами окна в 24 часа. Вторая же оказалась недостаточно тривиальной для реализации со стороны кода. Оба вопроса решаемы, но количество необходимых усилий не оправдывалось потребностями одноразовой кампании. К тому же, спринтовые задачи наступали на пятки, поэтому было принято решение не реализовывать данный функционал. И тут на помощь пришел You aren't gonna need it принцип, цель которого заключается в воздержании от избыточной функциональности. Это нормальная ситуация, когда условия меняются, и в продукте появляются мертвые, более ненужные части. Удаление соответствующих блоков облегчило понимание назначения flow и в лишний раз напомнило о важности своевременного отказа от добавления новой функциональности, в которой нет непосредственной надобности.

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

Давайте поиграем


Этапы self-review и рефакторинга пройдены, ненужного функционала нет, а смысл всех flow прозрачен для понимания. Это значит, что игра готова и настало время побороться за призы. По условиям конкурса топ-10 игроков, которые наберут наибольшее количество баллов до 22 мая 2020 года, получат призы от команды ManyChat.

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

Загадано число 1234.
Участник делает первое предположение: 4321
Получает ответ: 0 быков и 4 коровы
Участник делает второе предположение: 1678
И получает ответ: 1 бык и 0 коров.

Мы предлагаем 2 уровня сложности: игра на ограниченное и неограниченное число ходов. Победа в сложной принесёт вам 3 балла, в простой — 2. Проигрыш, независимо от уровня, заберёт 1 балл.

Игра была реализована на стандартном стеке технологий: Nginx 1.17, PHP 7.4, PostgreSQL 12.1. При желании вы можете склонировать репозиторий на свой сервер, установить шаблон на свою страницу ManyChat и устроить свой турнир.

Выводы


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

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

Никогда бы не подумал, что в одной статье буду цитировать Стива Джобса и Ленина.

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

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

Вероятно есть то, о чём я и не задумывался. У каждого из нас свой опыт и своё видение. Поэтому призываю вас поделиться в комментариях своими мыслями по этому поводу.
Теги:
Хабы:
+6
Комментарии9

Публикации

Информация

Сайт
manychat.com
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Армения
Представитель
Anna Kryukova (Vlasyuk)

Истории