Tag Archives: clojure

Интересное-9

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

Чтобы человек совершил какое-то действие – например, купил автомобиль, проверил почту или сделал 20 отжиманий – должны одновременно произойти три вещи. Человек должен этого хотеть, у него должна быть возможность это сделать, и его нужно к этому подтолкнуть. Триггер – намек на совершение действия – будет эффективен, только если человек крайне в этом заинтересован, или если действие совершить очень просто. Если сделать это трудно, люди приходят в замешательство. Если у людей нет мотивации, они раздражаются.

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

Чем внезапнее и интенсивнее будет эмоциональный отклик человека при первом опыте использования, тем выше вероятность того, что этот сервис станет базовым выбором человека. Именно поэтому авиакомпании наливают вам шампанское, когда вы летите в бизнес-классе, и именно поэтому в Apple делают все, чтобы первые минуты использования нового смартфона стали для владельца волшебными.

Но в итоге оно того стоит, не правда ли?

Linux Performance – страница с материалами по Linux performance tuning: observability, static performance tuning, and perf-tools/bcc (Linux observability tools, Linux benchmarking tools, Linux tuning tools, and Linux sar).
Удобно собранная вместе информация для системных разработчиков Linux. Да и для прикладных разработчиков информация будет интересна.

Notes on creating microservices-based applications – как видно из названия, это одностраничный набор-памятка, список заметок по созданию микросервисов. Нужно, полезно.

И, напоследок, Updating diagnostics for Boeing’s 737 MAX, статья из журнала для профессиональных авиационных инженеров. Речь в статье идёт о Base2 Solutions, which has AS9100 certification and is a Silver Supplier to Boeing, created prototype software that makes manufacturing and maintenance checks more efficient.

Меня заинтересовало, что этот непростой проект написан не на Java, а на Clojure(!). Интересны причины подобного выбора:

The most unique element of this project was that we used a functional programming language, Clojure, to write the software and were the first ones to use this language on commercial aircraft. Clojure is a relatively new software language that allowed us to write rules and code capable of handling massive amounts of data under significant hardware limitations. We estimate that if we had used Java to write the OMF, it would have resulted in more than half a million lines of code, which would have been significantly more difficult to test and debug. The OMF was written in just 32,000 lines of Clojure code. It is also the first time Clojure has been used on aircraft software.

Clojure uses LISP syntax that allows for very concise code, typically an order of magnitude less code than Java or C++. This means less code to test and debug and easier to get to more than 90% code coverage with unit tests.

Это доказывает, что на больших и сложных проектах, для создания которых по традиции принято использовать Java, без каких-либо затруднений можно взять Clojure (скорее всего это ещё и дешевле обойдётся, т.к. потребуется значительно меньшая команда разработчиков).

Интересное-5

Статья Как технология овладевает сознанием людей – отличный ликбез по механизмам влияния соцсетей на сознание пользователя. Современные технологии и психология, и – никакой магии. У меня лежит серия книг десятилетней давности от РБК-Пресс по маркетингу и брендингу. Принципы продвижения брендов, как смысловых якорей, и конструирование аддиктивности пользователей, применительно к социальным сетям, схожи между собой. В общем данную статью читать любопытно, как минимум чтобы сравнить, насколько технологии манипуляции сознанием ушли вперёд. Рекомендую.

Clojure – мощный язык для потоковой работы с данными. И вот найден очередной наглядный пример – использование функции juxt и group-by.
Благодаря этим функциям можно делать сложные выборки и группировку a-la SQL/NoSQL с высокой скоростью и на больших объёмах данных. В итоге имеем вполне себе in-memory СУБД без каких-либо внешних зависимостей.

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

И, напоследок, статья под названием Кто ворует пчёл: В США похищают сотни ульев в год на миллионы долларов . Это ни разу не ИТ, и не высокие технологии, однако сюжет по-своему захватывающий. Впечатляют масштабы и оборот финансов в этой сфере. Сфера пчеловодства в США крайне развита, это очевидно, а это значит, что есть место для всевозможной автоматизации и прочих интересных штуковин. Например, по спутниковым снимкам и карте дорог делать расчёт логистики и экономической целесообразности для перевозки ульев на новые места, где можно собрать максимум мёда в итоге (и сюда можно тоже воткнуть такие модные в нынешнем году нейросети, да(!)). Естественно, нужно также проводить анализ полей по спутниковым снимкам для анализа “коэффициента сочности травы”. 🙂

Используем peridot для тестирования REST API

В некоторый момент возникла необходимость делать юнит-тесты для REST API. Взял первое, что подошло – ring-mock. И этот вариант вполне удовлетворял моим требованиям. Но некоторое время назад появилась потребность переносить состояние сессии между несколькими последовательными запросами. Тогда я и нашёл удобную библиотечку, которой и пользуюсь до сих пор – peridot.

В использовании peridot довольно проста. Пример того, как она используется у меня:

Как видно из кода, состояние сессии s1 передаётся в следующий запрос к /api/v1/register, результатом которого будет состояние s2. Далее, s2 передаётся в новый запрос, чтобы получить состояние s3. Всё просто, кратко и эффективно, как и должно быть в Clojure.

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

Итого, если вам требуется тестирование REST API с сохранением состояния сессии между запросами – рекомендую peridot.

Есть, кстати, ещё одна интересная библиотека для тестирования – kerodon. Но она ближе к тому, как пользователь взаимодействует с UI тестируемой страницы, т.е. она имеет несколько более высокий уровень абстракции, нежели peridot, который был задуман для работы только и исключительно с REST API. Тем не менее, kerodon – вполне себе вариант тестирования, имеющий свою область применения.

Структуры данных как идея

Подумалось тут: а ведь то, что у Clojure “всё есть данные”, является очень серьёзным преимуществом над классами в ОО-языках. Ключевая “фишка”, которая мне постоянно бросается в глаза – сериализация “из коробки”. Вообще же, смотрите, что в итоге получается:

  1. не нужны методы-аксессоры для доступа к приватным полям – всё публичное
  2. легко контролируется целостность состояния данных
  3. лёгкость интроспекции – состояние данных у нас уже на блюдечке, и доступно в любой момент
  4. структуру можно подавать на вход любой функции, и шансы, что вылетит exception, будут крайне малы
  5. удобная передача данных между логическими модулями – какие бы ни пришли данные, мы можем их попытаться распарсить без сваливания с исключением

Про гомоиконность (код как данные) и остальное я уже не говорю.

Да, конечно, в ОО-языках можно тоже взять структуры, написать функции для них. Но тогда зачем нужны ОО-языки?

Работа с HMAC в ClojureScript

В рамках одного из моих проектов возникла задача прикрутить HMAC для механизма аутентификации. Backend я пишу на Clojure, frontend же сделан на ClojureScript, т.е. казалось бы – гоняй мессаги из clj в cljs туда-сюда без проблем. И, действительно, проблем здесь не было. Однако возникла трудность во время сравнения HMAC, пришедшего от UI с HMAC, сгенерированном на бэкенде – банально не совпадали значения.

На фронтенде вычисление сигнатуры выглядело так:

На бэкенде кусок, сравнивающий HMAC-сигнатуру, выглядел так:

Первое, что я сделал, так это последовательно упростил генерацию HMAC на фронтенде и бэкенде, вычисляя хеш лишь из одного элемента, составляющего содержимое для генерации HMAC, чтобы убедиться, что это точно не “глаз замылился”. Ан нет, тут всё было в порядке, т.е. проблема осталась.

Ну хорошо. Переключил алгоритм с SHA256 на MD5. Проблема осталась.

Ок, тогда пробую найти, кто из библиотек врёт – buddy на бэкенде или Google Closure Library. Ищу два-три онлайн генератора HMAC, убеждаюсь что они все дают одинаковый результат, делаю тестовую генерацию содержимого, взятого на бэкенде. HMAC совпал с тем, что выдаёт buddy на бэкенде, а вот гугловский goog.crypt.Hmac выдаёт ерунду.

Виновник найден. Разбираюсь, почему получается именно такой результат. Это вряд ли глюк реализации – Google Closure Library обкатана в боевых условиях так, что это практически невозможно. Т.е. я где-то что-то не так делаю.

Возвращаюсь к коду на ClojureScript, и тщательно проверяю параметры при вызове goog.crypt.Hmac.getHmac() и типы, которые я туда передаю. Первый параметр это объект-генератор хешей, второй – пароль в виде массива целых чисел, третий – строковое значение, подлежащее HMAC-обработке. Вроде бы всё верно.

Внимательно перечитал доку по типам данных ClojureScript. Ничего нового. И тут я случайно натыкаюсь в выдаче гугла на какой-то Сheat Sheet по сравнению типов данных JavaScript и ClojureScript, и до меня начинает доходить – а царь-то ненастоящий! а ведь похоже, что vector в ClojureScript  и Array в JavaScript не одно и то же! Погуглил бегло на эту тему и понял, что нужно создавать именно JavaScript-овый тип данных. Слабая динамическая типизация в JavaScript сыграла со мной злую шутку.

Итоговый исправленный вариант на фронтенде выглядел так:

Мораль – внимательно читайте документацию. А потом перечитайте её ещё раз, и – не менее внимательно!

Simplicity matters, again

Наверняка уже практически все кложуристы посмотрели знаменитое Simplicity Matters by Rich Hickey на Rails Conf 2012. Выступление очень чётко объясняет, что есть простота решений в software engineering.

Вчера наткнулся на видео с TED – Toward a science of simplicity by George Whitesides. Разговор шёл о всё той же простоте, но уже безотносительно какой-то конкретной области деятельности. Думаю, это неплохое дополнение к первому выступлению, эдакий переход от частного к общему.

Mac OS X, Java, и грабли с консолью

Один из моих домашних проектов на Clojure – консольный отладчик для Java с псевдографическим интерфейсом. Во время работы над ним наткнулся на неожиданное поведение консоли, пробуя запускать его в Mac OS.

Для работы с консолью я выбрал кроссплатформенную библиотеку Lanterna, написанную на Java. В процессе реализации модуля, обеспечивающего взаимодействие пользователя с консолью отладчика, наткнулся на то, что под Mac OS коды клавиш отличаются от тех же в PC. Причём для некоторых клавиш получить их состояние под Java невозможно (это касается командных клавиш), т.е. сочетания Ctrl+Left и Ctrl+Right читаться через Lanterna не будут. Похоже, что нужно использовать JNI, чтобы задействовать нужные кнопки.

В итоге реализовал для Mac OS работу через Esc+<кнопка> (т.е. Esc+Backspace, вместо Ctrl+Backspace). Получилось что-то эдакое:

В Google Groups находил треды (например, этот), где народ натыкался на те же проблемы, и, используя только Java, решить их так и не удавалось. Под линуксами же Lanterna корректно обрабатывает все необходимые кнопки. Похоже, что у Mac OS своя собственная кроссплатформенность.