Category: производство

усы2

Clojure impresses

Нашему Clojure-проекту исполнилось полгода, из них последние три месяца его используют заказчики. Пора подводить промежуточные итоги.

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

С одной, это правильный Питон — писать быстро, динамично, код компактный, легкий, лаконичный. Куда более лаконичный, чем питоновский, за счет ФП, макросов и прекрасной стандартной библиотеки.

Удобный перочинный нож на каждый день. Присылают .docx файл с табличкой — копирую его в Sublime, парой регэкспов подчищаю до регулярного формата (в sublime я этому научился-таки, а в vim регэкспы запомнить так и не могу, к вопросу о юзабилити vim-а), потом тремя-пятью трехстрочными функциями паршу и генерю что мне нужно.

Короче, когнитивного оверхеда никакого нет (особенно если repl уже запущен), и мне кажется, вообще всё надо на Кложе писать. Какой-нибудь енвайромент соорудить заместо bash, в котором все будет просто, логично и все главные нужные, но забытые в линуксе вещи будут, какой-нибудь feature-full process/task management framework, желательно network-transparent; и оттуда строить светлое будущее.

С другой стороны, Кложа одновременно и правильная Джава — вся та же Джавовая инфраструктура, доступ к любым библиотекам, maven-репозиториям, генерация Джава-кода, прямой интероп. Тоже минимум оверхеда, всё, что нужно сделать — выучить язык, и уже можно мягко и нежно продолжать достраивать Джава-проект на Кложе, без революций.

Плюс скорость. Тут сразу получается чуть хуже, чем у Скалы (по слухам) и голой Джавы, и иногда для разгона надо приложить усилия — типы кое-где дописать, инты анбокснуть, ленивости убрать или, наоборот, добавить. Написать джава-класс, в конце концов. Я в этом плохого ничего не вижу, потому что мы уже получили два в одном — быстрый прототип можно плавно и инкрементально перевести в производительное промышленное приложение. Такой мостик, которого нет у Питона, Руби (мы же не считаем всерьез мостиком возможность «переписать на C»?), Джавы.

С третьей стороны, и совсем не так давно, Кложа — это еще и правильный Джаваскрипт. Я на 100% оценил идею, что код сервера и клиента должны быть на одном языке, только кто решил, что это должен быть Джаваскрипт?

На бытовом уровне ClojureScript круче js хотя бы потому, что в js ты постоянно вошкаешься в поисках библиотеки, объединяющей строки или еще чего-то банального, но забытого разработчиками Netscape. Ну, по крайней мере, пока ты не профессионал и не написал свой utils.js. В cljs все сразу под рукой в стандартной библиотеке.

На промышленном уровне cljs, как наследник clojure, гораздо адекватнее, практичнее и однозначнее, чем js. На нем можно что-то строить, поддерживать и развивать, а не прыгать по плитам на одной ноге вокруг замаскированных ловушек, и не тратить дни на изобретение тысяча сто дватцать восьмого способа превратить код, сделанный из палок и соломы, во что-то, похожее на инженерное сооружение.

Ну и он, надо сказать, прёт вперед с каждым месяцем. Сейчас source maps прикручивают, скоро никаких аргументов за js не останется.

В-четвертых, изучение Кложи прокачивает внутреннего инженера. Хватаешься всяких полезных вещей — composable abstractions, примеров хорошей декомпозиции, учишься отличать важное от неважного, выделять среди моментов чистого хипстерства вещи, которые влияют на реальные, измеримые эксплутационные характеристики. Понимаешь, как важно, когда абстракции помещаются в голове.

Вот чему я научился бы, свяжи я свою карьеру с Питоном? The Zen of Python (хорошая штука, чего уж там), Джанге, WSGI и PyPy? А если бы с Руби, так вообще нахватался бы плохого. Вот в нашем Кложе-мире много новых взглядов на старые проблемы. Они, хоть и практичный язык, на самом деле на Джаве только бутстрапились, а сейчас потихоньку всё переписывают. Datomic, core.logic, reducers, cljs, enlive, lighttable, в самом языке stm, protocols, подход к стейту, много интересного короче и пищи для размышлений. Не любой код на Кложе — идеал, конечно, но это тоже работает в плюс — смотришь на хорошее, смотришь на плохое, анализируешь, почему так и в чем существенная разница. Да даже просто наблюдение сложности maven на фоне изящного lein подарило мне немало минут медитации об устройстве мира. Правда, как они ТАК всё зафакапили на ровном месте?

Тут секрет еще в чем? Чтобы выучить Кложу, надо посмотреть хотя бы пяток лекций Рича Хики. То есть, можно конечно и по-другому выучить, но тогда я не понимаю в чем смысл. А Рич Хики крутой чувак и все время правильные вещи говорит, универсальные. Если и есть надежда, что кто-то нашу software industry спасет, так это может быть он. Ну не DHH же в конце концов. И, давайте будем реалистичными, не Хаскель. Хаскель больше про объяснения и рефлексию, чем про спасение.

В лекции про муравьев, например, Рич раскрыл практическую сторону Кложи — симуляцию колонии муравьев можно сделать и на Джаве (JVM же общая), но очень сложно. Кложа дает правильные примитивы, в терминах которых можно мыслить — stm, транзакции, стейт, его изменение и синхронизация (например, традиционные actors здесь называются agents, плюс много других concurrent примитивов). Когда этого нет, никто конечно не мешает их написать, но люди, у которых есть жизнь, скорее вляпают глобальный лок на время рендеринга или еще какую-нибудь гадость. Потому что просто и идиоматично для Джавы. И потом будут бодаться с бизнесом — и тормозит, и ненадежно, и исправляется только выбрасыванием. Чтобы сделать правильно, надо было с самого начала правильно идти по довольно тонкой тропке выверенных решений; в условиях реальных проектов кто ж так сумеет? Нужен правильный инструмент.

Пользуясь случаем, хочу сказать, что мыслить в терминах Кложи про стейт и его изменение легко, удобно, и трудно ошибиться. Мне когда-то казалось, что STM это что-то толстое, серьезное и страшное, вроде БД, но нет, удобное и понятное, и пригождается даже в мелочах.

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

Иммутабельность и персистентные структуры совсем не просаживают производительность, по крайней мере мне заметить пока не удалось. Видимо, если хоть как-то вовлечено io, всё нивелируется. Естественно, плюсы от них бесконечны.

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

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

С синтаксисом всё в порядке — управляющих конструкций больше, чем в любом языке, что я видел (любят заточенные под разные случаи частные случаи макросы вроде ->> или condp).

И немного приятных мелочей. Кложа — это действительно очень прикольный язык трансформации данных. Его надо каким-то DSL, мне кажется, оформить и во все остальные языки встраивать, или в базы данных, или в NoSQL вместо js.

(->>
  (str "http://api.twitter.com/1/users/lookup.json?screen_name=" (str/join "," names))
  slurp
  json/read-json
  (map (juxt (comp str/lower-case :screen_name) :id_str))
  (into {}))

(reduce #(min %1 (@emitted %2 0)) limit ins)

(reduce #(%2 %1) (update-in record [:rules] conj name) actions)

(reduce (fn [s [f t r]] (str (subs s 0 f) r (subs s t)))
        (:text tweet)
        (reverse (sort replacements)))

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

Это нормальные-дефисы-в-именах вместо уродливых_подчеркиваний или ВерблюжьегоРегистра, да и вообще много прикольных спецсимволов в именах можно использовать. ->> например вполне валидный идентификатор.

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

(no subject)

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

(no subject)

А теперь к интересному. На собеседовании к нам часть кандидатов решает задачи на C, часть (малая) — на чем-то высокоуровневом (C#, Python). Так вот, на этом контрасте видно — я сейчас говорю о самых лучших кандидатах, вопросов к профессионализму которых нет вообще — как на C вы час решаете с человеком задачу, учли кучу случаев, исписали две страницы кода, а на выходе малозначительная не утилитка даже, а функция, но зато уже (!) с кучей допущений насчет входных данных, неврозом по поводу утекающей памяти1, с допущениями по порядку вызова и прилагающимся сюда неврозом по поводу надежности вызывающей стороны; и неистребимым ощущением неудовлетворенности в целом. А на Python-е за пятнадцать минут у тебя уже готово и чтение файла, и парсинг какой угодно, и все это надежно, и общее ощущение хорошо и правильно выполненной работы. Я первый раз даже не готов оказался — через пятнадцать минут и вот, всё, пожалуйста, что дальше делать? Хотя работы было раза в три больше.

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

Питон же — язык с готовым каким-то решением на любой случай жизни. Практичный в бытовом смысле язык. Задача без раздумий и сомнений ложится на код практически один-к-одному, потому что все нужное уже тут. Когда готово, вдруг думаешь — как это получилось? Подозрительно мало я страдал: над выбором библиотек, над мелкой моторикой работы с ними, над микрооптимизациями. Потом к этому ощущению привыкаешь, понимаешь, что так и задумано. И удивляешься, что у других не так: кто-то занят какими-то моноидами, чистотой, системами типов, а на самом деле мясо, скучные бытовые утилиты — они и в промышленности, и для собственного счастья куда важнее. Когда каждой следующей строчкой ты приближаешься к окончательному решению своей задачи (в терминах вход-результат), а не к очередному уточнению используемой абстракции, это больше смысла несет, это важнее. Даже ощущение правильности решения больше. Но это надо попробовать Питон, чтобы понять.

1 Это мое личное, может, в универе меня напугали, но на меня любая строчка кода на C смотрит как партизан, который нет-нет да и выкинет кунштюк, а мне потом неосвобожденная память две ночи снится. В банальной программе
    int* arr = malloc(10);
    arr[0] += 1;
    free(arr);

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

(no subject)

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



Хотя в консольных редакторах оно так и выглядит, если подумать. Хм. Ну ладно, откровения не получилось. Но в сочетании с урл-баром все равно круто, мне кажется. Этот постмодернизм прям заводит. Да еще и ссылки (в IDE давно есть), и цветовые схемы через цээсэс, ух.