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

ngrok for the wicked, or expose your ports comfortably
PostgreSQL collation
History snapshotting in TwinSpark.js
Code streaming: hundred ounces of nuances
Useful shell prompt