Рим, октябрь 2018

Рим оставляет очень двойственное впечатление о себе. С одной стороны это типичная Европа, с другой — будто бы и нет. Сейчас попробую объяснить, что имею в виду.

Взять к примеру архитектуру. В Риме есть что угодно и на любой вкус: неоклассика, ренессанс, готика, барокко.

Витториано, пример неоклассицизма
Санта Мария ди Лорето, пример ренессанса
Фасад собора на пьяца Чиполо
Церковь Чесса дель Сакро Куоре ди Гесо в Прати, пример готики
Дворец правосудия, пример барокко

Но стоит опустить голову вниз — и мы видим кучи мусора. Везде.

Переполненная урна и мусор рядом
Угол дома, забросанный мусором
Припаркованный велосипед рядом с кучей мусора

Или транспорт. Можно прокатиться на такой вот милоте.

Старый трамвай

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

Исписанный щит с расписанием маршрутов
Остановка траснпорта

Да. По меркам Рима это идеальная остановка.

Самый удачный пример остановки: есть крыша, есть расписание

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

Град

Классические достопримечательности типа Римского форума

Римский форум — 1
Римский форум — 2

Колизея

Колизей

Пантеона

Пантеон

Дворца итальянской цивилизации

Квадратный Колизей

Уст истины — конечно интересные, но в них уже давно нет духа старины или античности. Все эти места превратили в аттракционы и машины по выкачиванию денег из туристов.

Уста истины

Одно из действительно красивых и атмосферных мест — это некатолическое кладбище на юге города.

Римское некатолическое кладбище — 1
Римское некатолическое кладбище — 2

С музеями тоже двояко. Есть Macro, в котором кроме одной работы смотреть вообще не на что. И есть MAXXII, в котором действительно интересно. Вот интерьер MAXXII.

Интерьер музея — 1
Интерьер музея — 2

“No posters”

Картина, на которой изображены несколько надписей, одна из них — No Posters

Брызжет реальными чернилами.

Фонтан, который брызжет чёрными чернилами

Das Schloss. Макет локации, по которой можно пройтись в шлеме виртуальной реальности.

Макет локации, по которой можно пройтись в шлеме виртуальной реальности

“This is real, right?”

Часть истории-комикса, где робот спрашивает у читателя “This is real, right?”

Ещё из интересного — бывшая психиатрическая лечебница. Экспозиция короткая, но атмосферная.

Портреты пациентов, которые написал один из работников лечебницы
Копии записей одного из пациентов
Оборудование лечебницы, «вшитое» в стену
Кабинет с препаратами

В отличие от Колизея, который мне показался скучным, Собор Святого Петра в Ватикане оказался наоборот интересным.

Собор Святого Петра, Ватикан

Все конечно прут на купол Собора, я тоже туда сходил.

Панорама вида с купола Собора

Внутри Собора также красиво.

Вид внутри собора с купола
Скульптура святого апостола Андрея
Скульптура святой Вероники

Но впечатление портят вот такие вот чуваки. В Риме вас пытаются наколоть на каждом шагу: пропустите очередь, купите ненужную хрень, сделайте то, сделайте это.

Человек призывает «пропустить очередь» в Собор Святого Петра

Ещё из интересного, квартира Суверенного Мальтийского Ордена на Виа Кондотти, 68.

Гравюра с гербом Ордена
Ворота во двор

А также Вилла Мальта, в замочную скважину которой видно территорию трёх государств: Ордена, Ватикана и Италии.

Вилла Мальта
Орден экстратерриториален в Италии
Скважина, откуда видно территорию 3 государств

Ну и несколько фотографий с претензией на художественность.

Вид с Тибра на Собор Святого Петра
Узкая улица в Риме
Люди переходят улицу на перекрёстке
Пара смотрит меню около ресторана
Уличное искусство: портрет, написанный грубыми штрихами

Бесценный обесцененный опыт

Пришёл домой от терапевта, а значит настало время для ещё одного поста ¯\_(ツ)_/¯
Сегодня расскажу о вреде обесценивания прошлого опыта. Приготовьте там чаю себе, пост длинный.

О чём в этот раз

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

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

Почему это вредно

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

Когда я обесцениваю прошлый опыт, я лишаю себя опоры и перестаю понимать, как относиться к ситуации

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

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

Только разница с чистой флешкой в том, что на ней и страхов тоже нет. Она не боится сделать ошибку, а я в таком состоянии — боюсь.

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

Давай‑ка на примере

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

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

Чувствуете, как быстро дошло до абсурда?

Только снаружи абсурд видно, а изнутри — нет. Изнутри всё получается как‑то стройно, логично и вообще — начинаю себе верить.

Откуда берётся этот голос

Только не кидайтесь в меня сейчас ничем. Это объяснение человека с высшим образованием в этой области. Я не хочу никого ни в чём убеждать, просто рассказываю, чо там у меня.
(Перед применением проконсультируйтесь со специалистом.)

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

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

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

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

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

Когда какая‑то из моих скрытых субличностей пытается выйти на контакт, ведущая воспринимает это как угрозу и начинает беспокоиться. Но мне нужно осознать, что критика от скрытой субличности — это критика, в ней есть благое зерно. Эти претензии — просьба как‑то поменять обстоятельства, чтобы удовлетворить мои потребности. (Потребности — тоже мои, потому что исходят изнутри.)

Что советует терапевт

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

Проговаривать страхи вслух

Раз абсурд заметно со стороны, надо слушать себя со стороны. Я уже как‑то писал об этом в посте о неправильных выводах.

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

На ней как бы появляется больше слоёв, из‑за чего она становится более конкретной. Это и помогает найти изъяны.

Осознать свою полезность в прошлом

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

Когда начинается телега с обесцениванием — освежать в памяти эти моменты. Важно: они должны быть мощными, чтобы убедить меня, иначе они тоже обесценятся.

Осознать свою полезность в настоящем

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

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

Определить, что пытается донести критик

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

Найти способ коммуникации

Чтобы найти причины недовольства критика, надо найти способ с ним общаться.

В терапии есть приём, когда я как бы смотрю на себя со стороны. Прям вот сижу на диване, смотрю на кресло и стараюсь представить, как сажусь в него. Когда образ появился, надо посмотреть, как он себя ведёт: поза, выражение лица и всё такое. Это поможет понять, какие качества выражает эта субличность.

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

Этот символ будет переключателем, который будет давать скрытой субличности «выйти в свет» и сказать, что хочется. У меня это происходит (опять, лол) через заметки в телефоне.

Звучит как какая‑то дичь

Да я и не отрицаю.

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

Почитать на тему

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

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

Проблема

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ссылки

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

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

Новые правила деловой переписки. М. Ильяхов, Л. Сарычева

Эта книга не о словах и правилах, а об отношениях между людьми.

Да, в ней есть список фраз, которые в 2018 году режут людям слух, но нет рецептов типа «используй вот этот шаблон, и все клиенты твои». Ну ладно, по порядку.

Основная мысль

Если относиться к адресату уважительно, то и в ответ к вам будут относиться так же.

Книга не про слова, а про правильное отношение к людям

Переписка — это инструмент, им надо уметь пользоваться. Люди — не инструмент, ими пользоваться не надо, им надо помогать. Собеседник будет охотнее отвечать вам, если ему будет приятно читать письмо.

У нас есть цель: получить совет, назначить встречу, договориться о сотрудничестве. Добиться этой цели проще, если получателю будет приятно читать письмо

Так что можно сказать, что книга — о том, как сделать письмо приятным для читателя.

Об уважении к чужому времени

Целая глава посвящена письмам о срочных задачах, и том как о них пишут: «АСАП», «срочно», «нужно вчера» и вот это всё. Людям не нравится получать письма с такими пометками. Но дело не в самих словах, а в скрытом в них отношении к чужому времени.

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

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

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

Чем больше работы мы проделаем за адресата, тем легче ему ответить, тем приятнее с нами сотрудничать

Не надо рассчитывать на почту, как на экстренный способ связи.

Всё, что в почте, по умолчанию не «горит». Если что‑то и правда «горит», оно не должно быть в почте

Об эмоциях и агрессии в переписке

Письма на эмоциях писать можно, нельзя — отправлять. Эмоциональное письмо может привести к необоснованному конфликту. Если вы сильно переживаете из‑за какой‑то проблемы, позвоните человеку или напишите в чат.

Как определить, что вы сейчас на эмоциях: если вам хочется показать, что вы спокойны и рассудительны — вы не спокойны и не рассудительны. Отправлять письмо в таком состоянии нельзя

В книге схемы «Когда писать письмо» нет, но её можно найти в лекции на ютубе: Когда писать и когда не писать письмо

В работе редко кто‑то вредит специально. Если кажется, что кто‑то ведет себя нехорошо, скорее всего…

Он не козёл, он просто не знает, как правильно

О праве на отказ

Да‑да, пошла песня про Кэмпа, но камон. Люди любят делать добрые дела и помогать другим людям. Мы социальны, и ощущение, что я помог кому‑то приносит удовольствие, а…

Когда мы даём человеку право на отказ, у него появляется больше поводов нам помочь

Особенно важно право на отказ в холодных письмах, где читатель ничего не должен. Он может даже не открывать письма. Задача таких писем — наладить контакт и выйти на связь, а не продать что‑то.

Об удобстве читателя

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

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

Про конфликт ваших принципов письма и удобства читателя.

Принципы‑шмынципы. Ответ однозначный: надо делать так, чтобы было приятно и удобно читателю, научному руководителю. Нечего тут рассуждать

О внимательности, границах, переходе на «ты»

О небрежном отношении к имени знаю из опыта — меня постоянно называют Алексеем, не надо так.

Если бы мы могли оставить в этой книге только одно правило, мы бы оставили вот это: внимательно с именем

Переходить на «ты» лучше при личной встрече. Главное, чтобы в переходе не было напряжения, иначе переход не нужен.

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

Гораздо безопаснее писать о том, что мы сами думаем и чувствуем, — а не лезть со своими оценками в душу другому

О манипуляциях и ситуациях «из ряда вон»

Самые неприятные письма — лицемерные и манипулятивные. Люди всегда видят, когда их пытаются обмануть или пытаются ими манипулировать. Им это не нравится. Если ситуация нестандартная, то надо это признать. Свои косяки тоже надо уметь признавать.

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

Лучше прямо сказать: «Я понимаю, что ситуация дурная». И дальше строить аргументацию, исходя из этого

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

Об этике переписки

Не писать ничего, что нельзя переслать. В претензиях не переходить на личности и оценивать не человека, а работу и результат.

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

Все претензии должны быть сделаны без переходов на личности, а оценить можно только работу, а не человека или его профессиональные качества

Об откликах на вакансии

Здесь всё снова упирается в человеческие отношения. Если письмо шаблонное и пытается просто закрыть вакансию, то работодатель скорее всего в нём пользы не увидит и не ответит.

У сопроводительного письма нет обязательной формы. Нет требований по формату и объему; необязательно пересказывать биографию… говорить о своей стрессоустойчивости, коммуникабельности, самообучаемости. Относитесь к этому письму не как к священному ритуалу, а как к общению человека с человеком. У одного проблема, у другого — решение. Они хотят договориться

Об ответах на хамские письма

Тут так же: быть на равных, не переходить на личности, не нарушать границ, проявлять искреннюю заботу.

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

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

Клиент не всегда прав. И если он не прав, надо честно и без стыда это объяснить. Это и есть уважение: не пытаться понравиться всеми силами, а спокойно признать, что нам не по пути

О шаге навстречу

Книга предлагает в любой ситуации делать шаг навстречу человеку, с которым вы переписываетесь. По‑моему, это вообще универсальный принцип.

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

Ссылки

К этой книге:

Мимо пролетало:

«Кликни меня!» на RxJS

На прошлых выходных мне надо было поковырять RxJS, и я попробовал написать игру с кнопкой, которая убегает из‑под курсора. В этом посте расскажу, что и как именно я использовал при написании и разберу по шагам процесс.

Если вы уже работали с этой технологией, скорее всего, ничего нового не узнаете. Пост ориентирован на таких как я — которым из RxJS знаком только JS.

Игру будем писать на Тайпскрипте. Отличий от обычного JS будет немного, но всё же стоит глянуть документацию по нему, чтобы знать, как объявляются типы переменных и возвращаемых из функции значений.

Почему Тайпскрипт

Мне давно хотелось его распробовать, а RxJS написан как раз на нём. Я подумал, почему бы не добавить себе ограничений и головной боли, ну и вот ¯\_(ツ)_/¯

Что такое RxJS

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

Если выражаться примитивно, поток — это последовательность чего‑то: событий, данных, преобразований и т. д. Представьте себе чатик, в котором вы с кем‑то переписываетесь. Последовательность сообщений в нём — это и есть поток.

Поток наблюдаемый, если мы можем на него подписаться — объявить функцию, которая будет обрабатывать каждый новый элемент. Чатик — это наблюдаемый поток, если мы сидим и читаем каждое новое сообщение.

Польза потоков в том, что они дают возможность не обрабатывать, например, события по одному, а объединить их и работать сразу с набором событий.

Наблюдатель и наблюдаемый

ReactiveX в основе использует шаблон «Наблюдатель». Два основных понятия, которые нам понадобятся — это observer (наблюдатель) и observable (наблюдаемый).

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

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

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

Наблюдаемый поток знает, как сообщить:

  • что появился новый элемент;
  • произошла ошибка;
  • элементы закончились.

На всё это наблюдатель может как‑то реагировать.

Диаграммы

Чтобы понять концепцию потоков лучше, документация к RxJS предлагает так называемые marble diagrams. На них изображены шарики, которые как бы нанизаны на нитку.

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

(Было бы конечно круче это всё показывать анимацией: ну типа элементы один за другим падают вниз, проходят преобразование, падают дальше.)

Применимо к игре

Чтобы написать игру, надо определить, какие события мы собираемся обрабатывать и что мы с ними хотим делать.

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

Если чуть ближе к коду, то у нас будет поток из событий перемещения мыши. Мы их будем чистить и оставлять только координаты {x, y}. Затем будем фильтровать координаты, проверяя находится ли курсор достаточно близко от кнопки:

Начинаем пилить

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

import {from} from 'rxjs'

// выталкивает по одному элементу из массива, пока они не закончатся
const arraySource = from([1, 2, 3, 4, 5])

Источником для нашего потока будет событие движения мыши по экрану. Чтобы создать источник из браузерного события, мы будем использовать fromEvent:

import {fromEvent} from 'rxjs/observable/fromEvent'

const source = fromEvent(document, 'mousemove')

Теперь браузерное событие mousemove будет отслеживаться в пределах document, и на каждое перемещение будет появляться новый элемент в source.

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

Операторы

Операторы — это функции, которыми можно преобразовывать элементы после того, как observable их отправил.

Чтобы применить несколько преобразований по очереди, нам потребуется pipe. Это метод, который занимается композицией операторов, то есть применяет их по порядку.

import {map, filter} from 'rxjs/operators'

// ...

const observable = source.pipe(
  map(...),
  filter(...)
)

Оператор map нам нужен, чтобы применить к каждому элементу какую‑то функцию.

Мы хотим извлечь из данных о каждом событии координаты мыши на экране. Поэтому в map мы передадим функцию, которая будет доставать эти данные и возвращать объект.

map((event: MouseEvent): MouseCoords => ({ x: event.x, y: event.y }))

MouseCoords — это тип данных, который мы создадим для работы с координатами. Он будет представлять из себя объект с полями {x, y}. Создавать новый тип необязательно, но так понятнее, с чем мы работаем.

type MouseCoords = {
  x: number,
  y: number,
}

// ...

map((event: MouseEvent): MouseCoords => ({ x: event.x, y: event.y }))

Оператор filter будет выбирать события, которые нам подходят.

Событие нам подходит, если курсор находится в пределах 15 пикселей от кнопки по обеим осям.

const shouldUpdateApp = ({x, y}: MouseCoords): boolean => {
  const {top, left, widthRange, heightRange} = state.get()
  const padding = 15

  return inRange(x, left - padding, widthRange + padding) 
      && inRange(y, top - padding, heightRange + padding)
}

// ...

filter(shouldUpdateApp)

И тогда код observable будет выглядеть так:

const source = fromEvent(document, 'mousemove')

const observable = source.pipe(
  map((event: MouseEvent): MouseCoords => 
    ({ x: event.x, y: event.y })),
  filter(shouldUpdateApp))

Подписка на события

Каждый элемент в потоке стремится попасть в subscribe, где он будет как‑то обработан.

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

observable.subscribe(
  // onNext, вызывается при появлении новых элементов, el — новый элемент
  (el) => {},

  // onError, вызывается, если произошла ошибка, er — объект ошибки
  (er) => {},

  // onCompleted, вызывается, когда поток завершён
  () => {},
)

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

observable.subscribe(() => updateApp())

const updateApp = () => {
  const {left, top} = getNewPosition()
  state.update({ left, top })

  applyStyle(button, {
    left: `${left}px`,
    top: `${top}px`,
  })
}

Результаты

Я не буду подробно останавливаться на классе, который управляет состоянием приложения, и функциях‑хелперах. Исходный код всего‑всего можно посмотреть на Гитхабе.

Сама игрушка получилась очень простой, хотя для знакомства с RxJS вполне ок.

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

Ссылки

Сделяль

Шаблон «Наблюдатель» и ФРП

Документация RxJS

Операторы

Книги и сервисы

Раньше ↓