solovyov.net

Переписал Showkr на ClojureScript

4 min read · clojure, showkr

После того, как я закоцал и восстановил себе сервер, я обнаружил (ну и вспомнил в какой-то степени), что Showkr (описание) перестал нормально собираться. Я там не зафиксировал версии библиотек, что-то себе сломало обратную совместимость, и всë такое. В прошлый раз я просто подпихнул рабочую версию, а в этот попытался разобраться, что там происходит.

Но в конце концов мне не хватило терпения - такое ощущение, что сломалось там всë, и я решил что это отличный повод попробовать quiescent - хотелось сравнить с om. Не так, чтоб это был очень нужный сервис, GA говорит, что туда заходит до 5 человек в день максимум. :) Но я его использую для странички с фотками, и мне оно нравится, так что решил, что надо. ;)

Ну и, за несколько дней я переписал его, и заодно написал библиотеку для шорткатов keybind (по мотивам keymage, хе-хе). Вышло прикольно, при одинаковой функциональности кода в 3 раза меньше - в большой степени это от того, что React избавляет от кучи проблем, конечно.

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

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

Про разделение логики работы с данными и с отображением - я что-то пока до конца не въехал во Flux, и написал, что получилось. В принципе относительно ничего, пользоваться можно. Я не сразу пришëл к идее использовать метаданные, чтоб проверять состояние данных - качаются, скачались, или может старые уже слишком.

Единственное, что мне сейчас не нравится - я по ходу дела не сильно размышлял и фактически реплицировал иерархию данных из старой версии. Что значит, что у меня качается информация про фотосет, а потом внутрь этих скачанных данных складируются комментарии к фотографиям. Это приводит к неприятным казусам: например, фотосеты пользователя складываются в информацию о пользователе - еë нужно скачать заранее, чтоб узнать айди пользователя по его имени, и в какой-то момент загрузка информации о пользователе уничтожала все данные внутри. Я переделал на merge вместо assoc, чтоб список фотосетов обновлялся, не исчезая, но это довольно скользкая дорожка и мне кажется, что грабли меня где-то поджидают. :)

Ну и я не строил никаких особенных нормализаторов данных, а складирую прямо то, что вернул фликр, поэтому добавить поддержку любого другого хостинга фоток - тяжело. У меня есть мысль использовать DataScript, чтоб решить и одну проблему (с хранением вложенных данных), и, возможно, вторую - всë равно придëтся парсить данные из приходящего формата в то, что захочет DataScript, вот и будет место для внедрения разных парсеров апи в данные. Но пока что я не очень хорошо понимаю, как это всë правильно парсить, чтоб потом правильно спрашивать. :)

И, чуть не забыл, это ж заодно был повод использовать lein-figwheel. Это такой плагин к Ляйнингену, который следит за изменяющимися файлами, компилирует их как cljsbuild auto, а потом подменяет код в браузере. Работающий код. Работает просто невероятно клëво, с Реактом и подобными штуками - match made in heaven. :)

Нужно как-то нотифицировать своë приложение, конечно, что пора перерисоваться с новым кодом, но это несложно. Единственный момент - я поначалу делал (swap! data/world identity), и всë работало, но не до конца - код загружался, но перерисовывался только если я обновлял самый верхний неймспейс, в котором находилась функция render. Не знаю, в чëм загвоздка, текущая версия работает без проблем.

И, если хочется, чтоб состояние оставалось нетронутым, надо использовать defonce для атомов вместо def - иначе после изменения файла атом переопределится поверх и зачистит данные.

Тут еще спрятан интересный хак - для dev-версии используются две директории, src и src-dev, а для минифицированной - только src. И в src-dev, получается, лежит то, что нужно только для версии для разработки. :) index.html, впрочем, нужен для них разный, так что пока просто конфига недостаточно.

В общем, хорошего всем дня, код можно читать, он простой и, по-моему, довольно внятный (лучше, чем то, что было раньше), так что он будет нормально служить в качестве несложного примера. Если будут вопросы или критика, я бы послушал, может вообще есть идеи, как можно что-то во внутренностях резко упростить? :)

If you like what you read — subscribe to my Twitter, I always post links to new posts there. Or, in case you're an old school person longing for an ancient technology, put a link to my RSS feed in your feed reader (it's actually Atom feed, but who cares).

Other recent posts

Server-Sent Events, but with POST
ngrok for the wicked, or expose your ports comfortably
PostgreSQL collation
History Snapshotting in TwinSpark
Code streaming: hundred ounces of nuances