В прошлом месяце наши собственные Алекс Карл и Рон Нельсон посетили CED Tech Venture Conference, региональное сетевое мероприятие для стартапов и инвесторов из Северной Каролины.
Рон, наш директор по продажам и резидент-вундеркинд Mario Kart, также сделал короткую презентацию о быстром росте Adzerk за последний год.
Хотя я лично не присутствовал на конференции, некоторые программы, которые я написал, присутствовали. Это программное обеспечение, Панель показов, представляет собой одностраничное приложение (или SPA), демонстрирующее нашу технологию и некоторых наших клиентов. Алекс и Рон настроили его для работы на Macbook, подключенном к телевизору на нашем стенде.
Цель Dashboard состояла в том, чтобы представить оперативные данные таким образом, чтобы прохожие могли понять наши технологии и бизнес, а также помочь начать разговор.
Вот как это выглядело на конференции:
Вы также можете запустить клиентскую версию Dashboard, чтобы лучше понять, что она делает. Из соображений удобства панель инструментов была разработана специально для телевизора, на котором она была представлена — она может отображаться неправильно на вашем экране.
В этом посте я поделюсь некоторыми инструментами, сервисами и практиками, лежащими в основе этого небольшого, но успешного приложения.
ИНФОРМАЦИОННОЕ ПРИЛОЖЕНИЕ
В начале прошлого месяца я проработал в Adzerk всего несколько дней, когда Dashboard стал потенциальным первым проектом. Tech Venture была не за горами, и проекты, подобные Dashboard, были успешными на предыдущих конференциях. Нам нужна была Dashboard, и нам нужна была быстро.
В частности, нам нужно было приложение, которое:
- показывал реальные, производственные показатели и постоянно обновлялся
- Алексу и Рону было бы легко настроить
- вернуться к историческим данным во время сбоя Wi-Fi, возобновить работу с данными в реальном времени после восстановления подключения
- было эстетично
- может быть построен и испытан за 3 дня, вершины
В идеале приложение должно было бы легко улучшаться дизайнером и содержать части, которые мы могли бы использовать в будущих конференциях и аналитических панелях без необходимости привлечения программиста.
ДЕНЬ 1: РЕШЕНИЯ, РЕШЕНИЯ…
Единственное, что я знал наверняка в начале первого дня, это место, где живут данные, которые я должен был показать, и это место было Datadog.
Мы счастливые и активные пользователи Datadog. Мы работаем с сотнями инстансов AWS EC2, и метрики — важная часть того, что делает возможным работу в нашем масштабе. Наши сервисы отправляют данные о событиях в Datadog, которые затем мы можем просматривать в режиме, близком к реальному времени, с помощью встроенных в браузер Datadog инструментов запросов и построения диаграмм.
Инструменты, которые Datadog предоставляет через свой веб-интерфейс для построения графиков и информационных панелей, феноменальны и близки к тому, что нам нужно для нашей собственной панели Impressions Dashboard. Тем не менее, нам было интересно показать что-то фирменное и более простое от Adzerk.
К счастью, в дополнение к информационной панели и инструментам запросов, Datadog имеет хороший HTTP API, который мы можем опрашивать с помощью метрического запроса. Затем мы могли бы использовать этот результат запроса в качестве значения для датчиков приборной панели. С нашими собственными сервисами, Datadog и Dashboard картина выглядит примерно так:
БОЛЬШЕ О ХОПЛОНЕ
Начало проекта — самое дорогое время для принятия плохого технологического решения, поэтому, как правило, рекомендуется развлечься и оценить различные инструменты и подходы, прежде чем браться за какой-либо из них.
Тем не менее, если вам нужно добраться до работы вовремя, нет особого смысла тратить время на обсуждение достоинств одной породы лошадей перед другой, когда у вас в руках ключи от Кадиллака.
Cadillac в данном случае — это Hoplon, фреймворк Clojure и ClojureScript для создания SPA, таких как наша Dashboard.
Помимо достоинств функционального программирования, которые дает Clojure, Hoplon также предлагает обработку HTML-разметки — как альтернативный синтаксис ClojureScript — который может помочь удовлетворить нашу амбициозную цель — поддерживать приложение дизайнером.
Объединение программы и разметки — это то, что спасает нас от теневого мира и открывает для нас проверенные временем инструменты абстракций черного ящика в контексте браузера.
Возможно, самым важным преимуществом Hoplon в случае с этим приложением, учитывая жесткие сроки, является возможность использования и модуляризации существующих элементов, таких как подключаемые модули jQuery и сетки, для рендеринга элементов интерфейса, таких как датчики и выполнение жидкостного позиционирования.
В то время как браузеры заявляют о различных уровнях поддержки для множества разработанных комитетом и неудачно-но-поддерживаемых/устаревших API-интерфейсов, только один — которого даже никогда не было в браузере — выдержал испытание временем и надежностью. Этот API — jQuery, и с его помощью и его экосистемой плагинов мы можем сэкономить тонны времени.
О, и Hoplon также рулит, потому что я сделал его (с Micha Niskin) и оттачивал его специально для SPA, подобных этому, в течение последних двух лет. Да, этот пост в блоге сфальсифицирован :-)
ДЕНЬ 2.0: РАЗРАБОТКА МАКЕТНЫХ ДАННЫХ
После установки лесов для проекта Hoplon я приступил к поиску деталей, которые мне понадобятся, чтобы сделать что-то эстетически приятное.
Из-за того, как работает Hoplon, меня совершенно не интересовали детали получения данных от Datadog для целей разработки интерфейса. У меня было довольно хорошее представление о том, что мне нужно, и о том, что Datadog поддержит мои потребности в данных.
Помочь мне не заботиться о Datadog мне помог Javelin, библиотека ClojureScript, принесенная Hoplon, которая четко отделяет презентацию от вычислений, используя модель потока данных, подобную электронной таблице.
Точно так же, как диаграмме в электронной таблице все равно, откуда взяты значения, из которых она получена, компоненты моего пользовательского интерфейса (UI) не будут заботиться о происхождении значений, которые они должны отображать. Процесс подделки данных и их получения по сети изолирован от процесса их отображения благодаря Javelin и модели электронных таблиц.
Как работает большинство фреймворков SPA, вы можете подумать, что это невозможно. Поверьте мне, это так.
Пользовательский интерфейс может отображать только значения, а не процессы. Как появились ценности, мы не знаем и не заботимся.
Первой частью, которую я искал, была структура сетки, чтобы упростить позиционирование элементов. Хотя в прошлом у меня были хорошие результаты с Zurb Foundation, в наши дни я предпочитаю Twitter Bootstrap, хотя бы потому, что в StackOverflow есть огромное присутствие Bootstrap, которое будет чрезвычайно полезно, когда я неизбежно застряну. .
Еще одним преимуществом Bootstrap является то, что он доступен в Hoplon Vendor, банке библиотек JavaScript и jQuery, упакованных для удобного использования проектами Hoplon. Мне нужно было только добавить загрузочный пакет Hoplon Vendor к набору зависимостей Maven моего проекта, и Bootstrap был в наличии, активы и все такое.
Интерактивная разработка с использованием Hoplon осуществляется в основном через «живую перезагрузку» — когда я сохранял файлы ClojureScript, HTML и CSS, приложение в моем браузере автоматически обновлялось.
Поскольку меня заботило только то, как приложение будет выглядеть на конкретном дисплее, который Рон и Алекс привезли на конференцию, я установил телевизор на своем столе, чтобы я мог разрабатывать прямо на нем, перезагружая по ходу дела:
ДЕНЬ 2.5: КОМПОНЕНТЫ
Мое введение в Hoplon завершилось идеей о том, что Hoplon делает доступным и легко модульным множество плагинов и библиотек jQuery и JavaScript, которые уже широко доступны и проверены в боевых условиях.
Как только я создал скелетный проект Hoplon/Bootstrap примерно на 2,5 дня, пришло время снова доказать это самому себе. Я начал искать какой-нибудь плагин «манометр».
Я попробовал gauge.js, jQuery gage и JustGage и остановился на JustGage, потому что мне больше всего понравилось, как он выглядит. JustGage красиво смотрелся на телевидении, потому что он использует SVG и анимацию, и это было явно то, что я не смог бы быстро состряпать самостоятельно. Использование его вместо альтернативы или использование моего собственного датчика не составляло труда, особенно с учетом моего нехватки времени.
API JustGage
Чтобы создать JustGage, сначала нужно написать небольшой HTML-заполнитель:
<div id="gauge" class="200x160px"></div>
Затем немного JavaScript:
var g = new JustGage({
id: "gauge",
value: 67,
min: 0,
max: 100,
title: "Visitors"
});
API JustGage типичен для библиотек элементов пользовательского интерфейса браузера в том смысле, что:
- экземпляры создаются с помощью конструктора, в данном случае
JustGage()
, который принимает объект JavaScript из пар ключ/значение конфигурации. - конструктор принимает идентификатор узла HTML, к которому он должен добавить динамически сгенерированную разметку. Для JustGage в объекте конфигурации указывается ключ
"id"
. Плагины jQuery обычно «привязываются» к объекту jQuery и работают с любыми выбранными элементами, которые он представляет. - методы экземпляра элемента обеспечивают изменение внутреннего состояния во время выполнения. Экземпляры JustGage поддерживают метод
.refresh
, который принимает новое значение для отображения.
Подходит ли вам такой API или нет, это дело вкуса, как и почти все в программировании, помимо математических основ вычислений. Что касается меня, то я не большой поклонник.
Начнем с положительной ноты: приятно, что JustGage()
принимает объект вместо позиционных параметров, учитывая, что в объекте конфигурации может быть дюжина или более возможных ключей.
Что менее приятно, так это то, что обязательным аргументом является id
целевого элемента. Это похоже на жесткое кодирование указателя в качестве аргумента функции. Помимо того факта, что этот id
находится в пространстве имен, отличном от пространства имен нашей программы JavaScript, способ работы DOM также только что установил временную зависимость между нашим экземпляром JustGage и DOM, потому что указанный нами элемент доступен только после того, как DOM загружен.
Итак, нам нужно использовать $(document).ready(...)
jQuery для управления этой временной зависимостью, немедленно добавляя к нашему шаблону.
Наконец, чтобы обновить экземпляр JustGage после загрузки приложения, мы должны сохранить его дескриптор, чтобы мы могли вызывать его метод .refresh
. С необходимостью обратного вызова круг путаницы замыкается. Добавление большего количества экземпляров и других типов элементов пользовательского интерфейса, которые необходимо обновлять аналогичным образом (и в определенных порядках), усложнит оркестрацию и отладку обратных вызовов по мере роста приложения.
Модульность с дефелем
К счастью, с Hoplon у нас есть инструменты, позволяющие абстрагироваться от деталей владения и эксплуатации экземпляров JustGage
. Давайте поиграем с самым важным инструментом, идеей, что HTML можно рассматривать как Lisp, прежде чем мы применим его к JustGage.
HTML как ClojureScript
Hoplon предоставляет платформу, в которой миры JavaScript и HTML объединены. В Hoplon разметка и код выражаются одинаково — как программа. Например, рассмотрим следующий HTML:
<h1>Lisp is awesome!<h1>
Согласно обычной семантике браузера, этот фрагмент существует в статическом файле HTML, интерпретируется средством визуализации HTML браузера и становится доступным в DOM как объект HTMLHeadingElement
после обработки файла HTML.
В Hoplon HTMLHeadingElement
объектов можно создать следующим образом:
(h1 "Lisp is awesome!")
h1
в данном случае является функцией ClojureScript, и соглашения о ее вызовах соответствуют остальному языку ClojureScript. Вот более сложный пример, который также дает HTMLHeadingElement
, но демонстрирует некоторые преимущества, присущие рассмотрению HTML как альтернативы Lisp:
(let [language "Lisp"
adjective "awesome"]
(h1 (str language " is " adjective "!")))
Функциональная HTML-композиция
Поскольку h1
и все другие конструкторы объектов DOM являются обычными функциями, мы можем создавать и компоновать разметку интересными способами. Рассмотрим этот фрагмент HTML:
<ol>
<li>first</li>
<li>second</li>
<li>third</li>
</ol>
В Hoplon мы могли бы выразить это так:
(ol (li "first")
(li "second")
(li "third"))
Хотя синтаксически версия Hoplon немного более лаконична, реальная сила заключается в том, что, поскольку HTML — это язык программирования, мы можем устранить li
дупликацию с помощью средств функционального программирования:
(ol (map li ["first" "second" "third"]))
Обратите внимание на две вещи:
- Функции конструктора DOM, такие как
li
, могут без проблем передаваться функциям более высокого порядка, таким какmap
- Если функции-конструктору DOM, такой как
ol
, передается коллекция, она «склеивает» коллекцию со своими дочерними элементами.
Элементы — это функции
Возможно, мы часто создаем списки ol
с кучей строк. Мы могли бы рассмотреть возможность создания функции:
(defn quicklist [& strs]
(ol (map li strs)))
Теперь мы можем составить такие списки:
(quicklist "first" "second" "third")
Пользовательский элемент! Поскольку элементы являются функциями, и мы можем тривиально создавать именованные функции, мы можем так же тривиально создавать «пользовательские элементы», такие как quicklist
здесь.
Вернуться к JustGage
Итак, что мне действительно нужно, так это «настраиваемый элемент» под названием gauge
, который принимает некоторые параметры и который я мог бы использовать в разметке, как если бы он поставлялся с браузером. Вот как это выглядело, когда я закончил:
(defelem gauge [{:keys [value min max title label]
:or {max 100}
:as attrs}]
(let [div-id (str (gensym))
elem-attrs (dissoc attrs :value :max :title :label)]
(with-let [elem (div (assoc elem-attrs :id div-id))]
(with-init!
(let [params (js-obj "id" div-id, "max" max, "title" title, "label" label)
gauge (js/JustGage. params)]
(cell= (.refresh gauge value)))))))
Это промежуточный ClojureScript, и он также использует некоторые функции и макросы, характерные для Hoplon, поэтому не беспокойтесь, если он не имеет для вас полного смысла. Что следует отметить по этому поводу, включают в себя:
- он использует
defelem
для определения функцииgauge
, которая принимает ряд атрибутов какattrs
, используя деструктурирование карты ClojureScript. - он генерирует
div
со случайным именем, называемым(str (gensym))
, чтобы указать экземпляру JustGage на - он создает экземпляр
JustGage
, передавая объектparams
, созданный с помощьюjs-obj
, функции ClojureScript для создания общих объектов JavaScript. cell=
прикрепляет «ячейку формулы» Javelin к аргументуvalue
.value
здесь — «ячейка ввода», которая представляет собой ссылочный тип, похожий на Atom. Идея ячеек иcell=
заключается в том, что выражения должны запускаться, когда любые зависимые ячейки изменяют значение. Здесьcell=
используется для запуска выражения(.refresh gauge value)
при каждом изменении значенияvalue
.
Датчик запросов
Имея под рукой обычный калибровочный элемент, я смог создать еще один пользовательский элемент, query-gauge
. Идея с query-gauge
заключалась в том, что я мог создавать датчики в разметке и передавать запрос Datadog для визуализации в виде строкового атрибута.
Внутри query-gage
опрашивает наш сервер Clojure, который, в свою очередь, опрашивает API Datadog, который возвращает метрику обратно в датчик для отображения. Поскольку этот пост уже немного содержателен, я приберегу подробности для другого поста.
В итоге в файле index.html.hl
я смог создать такие датчики:
<dash.query-gauge
q="sum:eventserver.events.impression{*}"
max="15000"
title="Impressions"
label="per second">
</dash.query-gauge>
ДЕНЬ 3: ПРОВЕРКА И ТЕСТИРОВАНИЕ
На самом деле я не делал ничего интересного в День 3, потому что День 2 был очень продуктивным! Мое время в основном уходило на настройку CSS и обеспечение работы кода в различных сценариях подключения. Днем я развернул приложение на машине в AWS и показал Алексу, как настроить его в Chrome.
ГРУППОВЫЕ ОБЪЯТИЯ
Этот пост был бесстыдной шумной игрой гоплонов, но я надеюсь, что, по крайней мере, он дал вам понять, насколько я взволнован гоплоном и тем потенциалом, который я вижу в нем. Я рекомендую вам попробовать краткий учебник на hoplon.io, чтобы убедиться в этом самостоятельно.
Если вам больше нравится YouTube, вас может заинтересовать доклад и демонстрация, которые я недавно провел для Clojure Toronto.
Есть вопрос или комментарий? Пишите мне в Твиттере, я @alandipert. Спасибо за чтение!
Эта запись была первоначально опубликована Аланом Дипертом в Техническом блоге Adzerk в октябре 2014 г. Вы можете узнать больше о Adzerk здесь.