Битва за Кложуру или операция «Боевой Магнит»
Тематика соревнования — за 48 часов напилить что-нибудь, используя Clojure или ClojureScript. Из разных вариантов решено было пилить браузерный Risk, в частности потому, что все существующие приложения убоги интерфейсом, или написаны на Flash, или, ещё того хуже — Silverlight, или ещё каким-нибудь образом портят времяпровождение. Коллективно придумалось хорошее название — War Magnet.
Недолго думая, мы решили писать и сервер на Clojure, и клиент на ClojureScript, с использованием общего кода. Из четырёх участников только у Сани был хоть какой-то опыт написания на кложуре, а у остальных был только опыт решения нескольких десятков задачек на 4clojure.
FRP (functional reactive programming) на Bacon.js
Курс «Принципы реактивного программирования» на coursera.org

Атом — минимальный кирпичик реактивного приложения
Данная статья знакомит читателя с абстракцией «атом», предназначенной для автоматизации слежения за зависимостями между переменными и эффективного обновления их значений. Атомы могут быть реализованы на любом языке, но примеры в статье будут на javascript.
Осторожно: чтение может вызвать вывих мозга, приступ холивара, а также бессонные ночи рефакторинга.
Kefir.js — новая библиотека для функционального реактивного программирования (FRP) в JavaScript
Если коротко, FRP это подход похожий на Promise, но с неограниченным количеством возвращаемых значений, и бОльшим количеством методов для комбинирования / модифицирования потоков событий. Другими словами, если Promise позволяют работать со значением, которого у вас еще нет, так, будто оно у вас уже есть, то FRP позволяет работать со значением, меняющимся во времени, так, будто оно не меняется.
Вот что это дает по сравнению с обратными вызовами:
1) Поток событий (Event stream) и значение меняющаяся во времени (Property / Behavior) становятся объектами первого класса. Это значит что их можно передавать в функции и возвращать из функций.
Например, можно создать объект содержащий клики на кнопку (поток событий), и дальше делать с ним всё, что можно делать с обычной переменной — передавать в функцию, возвращать из функции, сохранять как свойство другого обекта и т.д. Или можно создать объект отражающий текущий размер окна браузера (значение меняющаяся во времени).
Это позволяет гораздо лучше разделять ответственности в коде, разделять его на модули, и писать более гибкий, короткий и управляемый код.
К примеру можно написать функцию, возвращающую поток перетаскиваний (drag). В качестве параметров она будет принимать 3 потока — начало перетаскивания, движение, конец перетаскивания. Дальше можно передать в эту функцию: либо потоки для соответствующих событий мыши (mousedown, mousemove, mouseup), либо для touch событий (touchstart, touchmove, touchend). Сама же функция не будет ничего знать об источниках событий, а будет работать только с абстрактными потоками. Пример реализации на Bacon.
2) Явный state
Второе большое преимущество FRP это явное управление состоянием. Как известно, state — один из самых главных источников сложности программ, поэтому грамотное управление им позволяет писать более надежные и простые в поддержке программы. Отличный доклад от Рича Хикки о сложности (complexity) «Simple Made Easy».
FRP позволяет писать бОльшую часть кода на «чистых функциях» и управлять потоком данных (dataflow) явно (с помощью потоков событий), а состояния хранить тоже явно в Property.
Трансдьюсеры в JavaScript. Часть первая
Сразу, зачем это нужно:
- трансдьюсеры могут улучшить производительность, т.к. позволят не создавать временные коллекции в цепочках операций map.filter.takeWhile.etc
- могут помочь переиспользовать код
- могут помочь интегрировать библиотеки между собой, например underscore/LoDash могут уметь создавать трансдьюсеры, а FRP библиотеки (RxJS/Bacon.js/Kefir.js) могут уметь их принимать
- могут упростить FRP библиотеки, т.к. можно будет выбросить кучу методов, добавив один метод для поддержки трансдьюсеров
Трансдьюсеры — это попытка переосмыслить операции над коллекциями, такие как map(), filter() и пр., найти в них общую идею, и научиться совмещать вместе несколько операций для дальнейшего переиспользования.
Трансдьюсеры в JavaScript. Часть вторая
step
, и возвращающая новую функцию step
.step⁰ → step¹
Функция
step
, в свою очередь, принимает текущий результат и следующий элемент, и должна вернуть новый текущий результат. При этом тип данных текущего результата не уточняется.result⁰, item → result¹
Чтобы получить новый текущий результат в функции
step¹
, нужно вызвать функцию step⁰
, передав в нее старый текущий результат и новое значение, которое мы хотим добавить. Если мы не хотим добавлять значение, то просто возвращем старый результат. Если хотим добавить одно значение, то вызываем step⁰
, и то что он вернет возвращаем как новый результат. Если хотим добавить несколько значений, то вызываем step⁰
несколько раз по цепочке, это проще показать на примере реализации трансдьюсера flatten:function flatten() {
return function(step) {
return function(result, item) {
for (var i = 0; i < item.length; i++) {
result = step(result, item[i]);
}
return result;
}
}
}
var flattenT = flatten();
_.reduce([[1, 2], [], [3]], flattenT(append), []); // => [1, 2, 3]
Т.е. нужно вызывать
step
несколько раз, каждый раз сохраняя текущий результат в переменную, и передавая его при следующем вызове, а в конце вернуть уже окончательный.В итоге получается, что при обработке каждого элемента, одна функция
step
, вызывает другую, а та следующую, и так до последней служебной функции step
, которая уже сохраняет результат в коллекцию (append
из первой части).Итак, сейчас мы можем:
- Изменять элементы (прим. map)
- Пропускать элементы (прим. filter)
- Выдавать для одного элемента несколько новых (прим. flatten)
Атом — реализация на TypeScript
Краткое содержание предыдущей серии: простейшее приложение достигло критического уровня сложности, и, чтобы совладать с оной, была введена абстракция «атом», которая вобрала в себя всю рутину, позволив разработчику сконцентрироваться на описании инвариантов в функциональном стиле, не теряя связи с объектно ориентированной платформой. Вся теория и картинки там. Тут же будет куча практики, примеров кода и дампов консоли.
Как изобрести велосипед и познакомиться с FRP
Собственно, можно все сделать в лоб (для прототипа-то), но выпали выходные, пауза в задачах текущего проекта, и я решил сделать все по-хорошему. И в первый же вечер — callback hell.
А потом…

RSConf: Обзор и видеоматериалы фронтенд-конференции в Минске

The Rolling Scopes — минское сообщество фронтенд/javascript разработчиков. Мы занимаемся проведением митапов, воркшопов и Q&A сессий. А в этом году доросли до уровня, не побоюсь сказать этого слова, международной конференции. Наше 20-е мероприятие получилось помасштабнее остальных. В связи с этим непременно хочется поделиться деталями проведения, атмосферой и, конечно же, материалами.
Грокаем* RxJava, часть первая: основы
RxJava — это, сейчас, одна из самых горячих тем для обсуждения у Android-программистов. Единственная проблема состоит в том, что понять самые её основы, если вы не сталкивались ни с чем подобным, может быть довольно затруднительно. Функциональное реактивное программирование довольно сложно понять, если вы пришли из императивного мира, но, как только вы разберётесь с ним, вы поймёте, насколько же это круто!
Я постараюсь дать вам некое общее представление об RxJava. Задача этого цикла статей состоит не в том, чтобы объяснить всё вплоть до последней запятой (вряд ли я смог бы это сделать), но, скорее в том, чтобы заинтересовать вас RxJava, и тем, как она работает.
Грокаем RxJava, часть вторая: Операторы
map()
. Я могу понять тех из вас, кто всё ещё не чувствует желания всё бросить и начать использовать этот фреймворк, так как пока что мы, условно выражаясь, рассмотрели лишь вершину айсберга. Но скоро всё переменится — большая часть всей мощи RxJava скрывается в её операторах, и я как раз подготовил для вас пример, по которому можно изучить некоторую их часть.Грокаем RxJava, часть третья: Реактивность с пользой
Обработка ошибок
До настоящего момента мы полностью игнорировали такие методы
Observable
, как onComplete()
и onError()
. Данные методы вызываются в момент, когда Observable
прекращает порождать новые данные — либо потому, что ему нечего больше порождать, либо потому, что произошла ошибка.Самый первый наш
Subscriber
следил за onCompleted()
и onError()
. Давайте сделаем что-нибудь полезное в этих точках:Observable.just("Hello, world!")
.map(s -> potentialException(s))
.map(s -> anotherPotentialException(s))
.subscribe(new Subscriber<String>() {
@Override
public void onNext(String s) { System.out.println(s); }
@Override
public void onCompleted() { System.out.println("Completed!"); }
@Override
public void onError(Throwable e) { System.out.println("Ouch!"); }
});
Грокаем RxJava, часть четвертая: Реактивный Android
RxAndroid
RxAndroid — это расширение RxJava, написанное специально для Android, которое включает в себя специальные обвязки вокруг RxJava, делающие вашу жизнь проще.
Во-первых, здесь есть класс
AndroidSchedulers
, предоставляющий готовые планировщики для потоков, специфичных для Android. Нужно запустить код на UI потоке? Без проблем — воспользуйтесь AndroidSchedulers.mainThread()
:retrofitService.getImage(url)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(bitmap -> myImageView.setImageBitmap(bitmap));
Mobx — управление состоянием вашего приложения
MobX это простое, опробованное в бою решение для управления состоянием вашего приложения. Этот туториал научит вас основным концептам MobX. MobX это автономная библиотека, но большинство используют ее в связке с React и этот туториал будет сфокусирован на этой комбинации.
Основная идея
Состояние (state ориг.) это сердце каждого приложения и нет более быстрого способа создания забагованого, неуправляемого приложения, как отсутствие консистентности состояния. Или состояние, которое несогласованно с локальными переменными вокруг. Поэтому множество решений по управлению состоянием пытаются ограничить способы, которыми можно его изменять, например сделать состояние неизменяемым. Но это порождает новые проблемы, данные нуждаются в нормализации, нет гарантии ссылочной целостности и становится почти невозможно использовать такие мощные концепты как прототипы(prototypes ориг.).
MobX позволяет сделать управление состоянием вновь простым, вернувшись к корню проблемы: он делает невозможным инконсистентность состояния. Стратегия достижения этого довольно проста: убедится что, все что может быть вынуто из состояния, будет вынуто. Автоматически.
$mol: reactive micromodular ui-framework
Сколько нужно времени, чтобы просто вывести на экран большой список, используя современные фреймворки?
Список на 2000 строк | ReactJS | AngularJS | Raw HTML | SAPUI5 | $mol |
---|---|---|---|---|---|
Появление списка | 170 ms | 420 ms | 260 ms | 1200 ms | 50 ms |
Обновление всех его данных | 75 ms | 75 ms | 260 ms | 1200 ms | 10 ms |
Напишем нехитрое приложение — личный список задач. Какие у него будут характеристики?
ToDoMVC | ReactJS | AngularJS | PolymerJS | VanillaJS | $mol |
---|---|---|---|---|---|
Размер ( html + js + css + templates ) * gzip | 322 KB | 326 KB | 56 KB | 20 KB | 23 KB |
Время загрузки | 1.4 s | 1.5 s | 1.0 s | 1.7 s | 0.7 s |
Время создания и удаления 100 задач | 1.3 s | 1.7 s | 1.4 s | 1.6 s | 0.5s |
Небольшая головоломка: перед вами синхронный код, загружающий и обрабатывающий содержимое 4 файлов, но с сервера они грузятся параллельно. Как такое может быть?
А теперь прошу за мной в кроличью нору, настало время удивительных историй...
$mol_atom: теория и практика реактивности
Здравствуйте, меня зовут Дмитрий Карловский и я… состоятельный человек. У меня есть состояние на сервере, есть состояния в локальных хранилищах, есть состояние окна браузера, есть состояние доменной модели, есть состояние интерфейса. И всё это многообразие состояний нужно поддерживать синхронизированным. Если одно состояние как-то изменяется, то остальные связанные с ним состояния должны как можно скорее обновиться. Особую пикантность ситуации придаёт то, что синхронизация с сервером может занимать секунды, а блокировать пользовательский интерфейс можно лишь на доли секунд.
Далее вы узнаете: как реактивность побеждает асинхронность, как императивная реактивность уживается с функциональной, как простые абстракции позволяют писать надёжный и быстрый код, а также как я однажды перешёл на идемпотентную сторону силы и всё заверте
Mrr: тотальное FRP для Реакта
При слове «реактивность» обычно вспоминают Rx.js, как эталонный образец FRP. Однако серия последних статей на эту тему на Хабре([1], [2], [3]) показала громоздкость решений на Rx, которые на несложных примерах проигрывали в ясности и простоте почти любому другому подходу. Rx велик и могуч, и прекрасно подходит для решения проблем, в которых абстракция потока напрашивается сама собой (на практике это преимущественно координация асинхронных задач). Но стали бы вы писать, к примеру, простую синхронную валидацию формы на Rx? Сэкономил бы он ваше время, по сравнению с обычными императивными подходами?
mrr — это попытка доказать, что ФРП может быть удобным и эффективным решением не только в специфических «потоковых» проблемах, но и в самых обычных рутинных задачах фронтенда.