усы2

Стой под стрелой

Поступки и мысли, о которых могу вспомнить не краснея

Веб послезавтра
усы2
tonsky
Новый пост в англоязычном блоге про то, как должен выглядеть мировой паутин (спойлер: не так, как получилось) и как его таким сделать. Без React-а:

http://tonsky.me/blog/the-web-after-tomorrow/

БД на диване
усы2
tonsky
Я тут слушаю по субботам подкаст, пока в квартире убираюсь, DevZen. У нас с ними своеобразный симбиоз: они мои посты иногда обсуждают, а я из их высказываний иногда черпаю темы для новых постов. В этот раз был совершенно некрасивый наезд на дашборд CouchBase, мол, зачем оно такое нужно, если правильные админы первым делом метрики в graphite сливают.

Я согласен, что дружить с внешним миром надо уметь, но Валера (в основном) совершенно не понял прикола, что это за дашборд. Между тем это очень концептуально важная штука: CouchBase это программа, хардкорная, серверная, все дела, для серьезных продакшнов, которая сразу работает. То есть ее установка это apt-get install и после этого пара кликов мышкой в веб-интерфейсе. Даже настройка кластера в эти пару кликов укладывается. То есть это примерно как скачать программу из аппстора, сравнимый уровень головняка. Я понимаю, что это непривычно, и что так почти никто не делает. Но так можно, и это революционно.



И кайф не только в установке. Сам CouchBase это предельно простой продукт, распределенный кэш ключ-значение. Я подозреваю что там функционального кода раза в 3 меньше чем навернутой вокруг него админки. В нормальном продукте так и должно быть. Это программа, которая сама знает о своей эксплуатации, мониторит ее, репортит, дает UI для управления. У них там графики нагрузки (десятки метрик, возможность zoom in к чему-то конкретному и zoom out к общей картине), мониторинг хост-системы, схема кластера, UI для переконфигурации. Все это живое и web 2.0. По сути это базовый алгоритм и навернутый вокруг него сложный пульт, покрывающий все эксплутационные потребности от начала до конца. Законченная программа, от и до, под ключ.



В данный момент, до сих пор, индустриальный стандарт такой, что все это выносится за скобки, и установка себе, скажем, memcached — это прикручивание к черепахе шасси и фонариков, чтобы хоть как-то с ней жить. Это просто считается ненормальным, если взял с полки и ничего делать не надо. Есть еще SaaS модель, но это примерно то же самое, только прикручиванием занимаются другие люди на зарплате.

И не надо мне говорить, что сливание в одно место, унификация, единый стандарт решают. Не решают. Метрики можно слить, а вот состояние кластера уже вряд ли. Топ 20 горячих ключей тоже непонятно куда пристроить. UI для перебалансировки точно ни с чем не унифицируется. Ну и так далее.

В аварийной ситуации, когда собственно и нужна максимальная прозрачность происходящего, ничего лучше не покажет оперативную обстановку в кластере CouchBase, чем специально сконструированный ровно для этого интерфейс, со всеми датчиками, в реальном времени, и всеми ручками контроля сразу под рукой. Я в Эхо занимался в том числе эксплуатацией CouchBase кластера, и это было прекрасно.

Да, можно повторить только read-only часть, экспортнув метрики в Graphite, но это во-первых надо работать (вы уверены, что настроите свой мониторинг заранее, авансом, с первого раза правильно и полно?), а во-вторых непонятно зачем графики нужны без возможности сразу на ситуацию повлиять. Плюс мне не очень понятен постулат, что ваш локальный админ, у которого стопятьсот дел помимо CouchBase, вдруг настроит мониторинг и репортинг для кластера сразу полнее и надежнее, чем это сделали авторы самого CouchBase, которые свою карьеру строят на том, что только о нем и думают.

без темы
усы2
tonsky
JFYI история с МТС закончилась положительно после того, как я написал им в Твиттере. Сила социальных медиа, понимаешь. Это еще предстоит осмыслить. Почему-то саппорт по телефону даже не предлагал вариант «создать заявку».


Clean не нужен
усы2
tonsky
Когда-нибудь задумывались, зачем в билд-системах команда clean? То есть, понятно, почему она в них была, но почему она до сих пор есть? Почему иногда билд собирается только с чистого листа?

Это все от бедности. Сравнение файлов по дате модификации. Переписывание билд-артефактов. Инкрементальный билд это кэш, а инвалидация кэша — одна из самых сложных задач в CS. Естественно, она всегда будет решаться с ошибками.

Единственная вещь, которая идеально кэшируется это неизменяемые данные. get_cached(file_name) будет ломаться, get_cached(digest(file_content)) нет. Естественно, туда можно (нужно) еще всего напихать, типа окружения, версии компилятора, флагов, цели. Но смысл в том, что кэш по контенту работает сам, успевай только мусор подбирать. Главное — корректность.

Это подтверждает успех гуглового Bazel: ненадежные билды на makefiles вдруг стали железно надежными, стоило им перейти на такую схему. Это может быть и было дорого на 386-х, но сейчас один фильм на диске весит столько, сколько ваши разработчики не нагенерируют артефактов за все время жизни проекта.

Я очень жалею, что в ClojureScript не используется подобная схема, хотя казалось бы, кому, из всех людей. (Clojure здесь ловко выкрутилась — грузит файлы из исходников на лету). Билды портятся, приходится стирать и начинать все заново. Я не хочу ничего знать об этом, компьютер вычислительная машина, он должен работать надежно и предсказуемо. Билд это не гадание на нейронных сетях, вход, выход, алгоритм, все детерменировано. Избавьте меня.

Следующий логичный шаг — положить артефакты в сеть. Идеально закешированный, гарантированно работающий артефакт нет смысла каждому разработчику собирать заново. Я не нашел никакой информации о том, делает ли это Гугл, но было бы логично. Ну а дальше граф разматывается с конца: сначала проверяем, закэширован ли самый высокоуровневый артефакт, если нет, смотрим, от чего он зависит, ищем кэши зависимостей, и т.д.

Ладно мы, динамщики, у нас билды недолгие, единственно противно что ломаются при рассинхроне. Но все вот эти ребята, которые на C++ игры пишут и у которых ночной «чистый» билд по шесть часов, они как до сих пор к этой схеме не пришли? Это же классическое «лучше день потерять». Причем даже терять много не придется, система простая как тряпка. Зато окупаемость, о, мне сложно представить ее масштабы.

В идеале, конечно, понятия билда вообще не должно существовать. Билды не имеют отношения к работе программиста, это просто формальный, неудачный шаг. Зато их отсутствие целый пласт проблем снимает. JS, Python, Clojure все делают правильно. Но если уж делать билд, непонятно, почему не сделать его надежным и правильным. Таким, чтобы не было отдельного понятия «инкрементальный билд», чтобы любой билд был инкрементальным, быстрым, с распределенным кэшем. И чтобы я больше ничего о команде clean не слышал.

Перенос номера сотового на практике
усы2
tonsky
В один прекрасный день я купился на безлимитный, безроуминговый интернет и лимитный, но тоже безроуминговый (по России) телефон от Йоты. До этого я лет десять, наверное, был абонентом МТС и даже переезжая в Ульяновск и обратно сумел сохранить новосибирскую симку. Оставим в стороне факт, что если я хочу переехать в другой город, но остаться у того же оператора, мне нужна новая симка. Глупо, но глупости полно кругом, одной больше, одной меньше.

Решил перенести номер. Заявление можно написать сразу в Йоте, они утрясают все детали с отключением от МТС-а сами. Предупредили: проверьте, что баланс положительный, иначе беда. Положил денег с запасом. Жду. Номер переносится 10 дней. Жду. Пробую вставить Йотовскую симку. У Йоты нет личного кабинета, есть только приложение для Айфона и Андроида. Плебеи с Виндоус Телефоном пишут в чат техподдержки, чтобы выбрать тариф.



Балуюсь, пробую включить перенаправление вызовов с МТС-овского номера. Перенаправление у МТС не работает. Пролетает 10 дней. Приходит последняя жалобная смска от МТС: может, все-таки передумали?



Не передумал. Проверяю баланс МТС. Около 50 рублей. В полночь старая симка умирает, личный кабинет блокируется, номер переносится, ура, я счастливый обладатель Йоты.

Почти два месяца безмятежно пользуюсь новым оператором. Интернет денег не просит, 4G ловит, правда, хуже, чем у МТС. Езжу в Москву, звоню, сижу в интернете.

И вот приходит смс от Йоты: чувак, у тебя долг перед МТС, давай разберись, а то нехорошо выходит.



Интересно. Ищу, куда позвонить. У МТС на сайте ни на главной, ни в «о компании», нет вообще ни одного телефонного номера. Гуглю, звоню. Оказывается, через три недели после отключения у меня списали 150 рублей за услугу БИТ. Такая вот услуга, списывается раз в месяц. Окей, выясняю долг (97 рублей 59,96 копеек). Убеждаюсь, что гудок не подключен и дальше никаких списаний не будет (ну и что, что у меня даже симки уже нет, мало ли). Сообщают, что платить надо строго по номеру лицевого счета и строго в салонах МТС. Присылают номер счета смской.



Иду в первый салон. Сообщают, что у них не работает касса, но оплатить можно в терминале, который прямо у них там же и стоит. Объясняю ситуацию. Показывают, как платить по номеру ЛС. Плачу, забираю чек, иду домой.



Проходит 4 дня. Приходит смс от МТС. Уважаемый, вы у нас конечно не обслуживаетесь, но денег должны.



Интересно. Черт с ней, с пунктуацией. Гуглю номер МТС, звоню. Долг никуда не делся. Сообщаю, что платил. Рекомендуют позвонить по номеру с чека. Весь день названиваю по номеру с чека. Не берут трубку. Платежная система ТелеПэй. Названиваю по 8800 номеру ТелеПэй. Не берут трубку (целый день, Карл!). Я, в принципе, догадывался, что платежные терминалы это такие ящики для засовывания денег, без каких-либо гарантий. Убедился.

Окей, черт с ними со ста рублями. Иду в офис МТС (другой, на всякий случай). Объясняю ситуацию. В терминале платить отказываюсь, стою в очереди, рекламирую соседям тарифы от Йоты. Меня быстренько берутся обслуживать, достаю 100 рублей. Проблемы со связью. Жду 20 минут. Прихожу еще раз. Еще раз объясняю ситуацию. Выясняется, что проблемы не со связью, а с лицевым счетом. При попытке положить на него деньги возникает ошибка. Жалуюсь, что у меня из-за этих их ошибок отключат Йотовский номер. «Да ну, ерунда какая, не может такого быть», — заверяет меня девушка.

Возвращаюсь домой, гуглю номер МТС, звоню. Меня сразу предупреждают: не погасите задолженность — вас отключит Йота. Объясняю ситуацию. Меня заверяют, что никаких причин не принимать у меня деньги у МТС нет. Более того, МТС очень хочет моих денег.

Иду в третий офис и звоню оттуда в техподдержку, даю трубку сотруднику. Обе стороны понимают, что бессильны. Понимающе молчат. Платеж не проходит. Проверяют другой номер. На другом все работает. Совать деньги в терминал отказываюсь.

Прихожу домой. Ситуация патовая. Моих денег хотят, но не могут взять. Злиться не на кого. Надо извлечь из этого какой-то урок, но непонятно, какой.

Завтра отключат симку.


Новый доклад «ФП в браузере: Redux»
усы2
tonsky
Текст и слайды: http://tonsky.me/talks/2015-frontendconf/


без темы
усы2
tonsky
Вслед http://ermouth.livejournal.com/641180.html

На меня вот эта книга очень сильно повлияла в детстве:



Программировать она не учит, практически совсем. Листинги есть в каждом совете, но их как-то особо не разбирают даже. Там истории интереснее, чем собственно программы — как и должно быть, по идее. То Мцыри печатают, то ищут стратегию для тройственной дуэли из «Хороший, плохой, злой», иногда просто байки травят. Интересно не само программирование, а то, вокруг чего оно используется.

После этого читать «конструктор это метод который...» понятно что нужно, но скууууучно. Короче, такая книжка у каждого программиста должна быть в детстве, чтобы не вырасти неадекватным гиком. Да и вообще, разве может быть плохой книжка, в которой авторы то и дело дают взаимоисключающие советы, а оглавление напечатали на корешке только ради того, чтобы получилось 256 страниц?

ФП в Киеве есть
усы2
tonsky
Был две недели назад в Киеве, прочитал на митапе в Grammarly доклад, продолжение «ФП в браузере». Доклад про то, как сделать векторный редактор на React.js и Immutable.js.

Коротко:

На JS жить можно, с правильной архитектурой писать вполне терпимо. Я ожидал больше страданий. Запилил мультиметоды и атомы, впрочем.

Immutable.js нормальная штука, не хватает только сериализации/десериализации структур в строку, очень странно что они это упустили. Пришлось писать самому.

Еще смешно: Immutable.js портировали реализацию персистентных структур из ClojureScript, при этом писали на чистом JS и умудрились сделать ее в 2-3 раза медленнее, чем на ClojureScript. Вот вам и про преимущества ручного кода перед компилируемым.

Код: https://github.com/tonsky/vec (650 loc)

Живая версия:



Видеозапись:
http://www.youtube.com/watch?v=lDkrXTDwbJQ (разбор кода)
http://www.youtube.com/watch?v=tUtLe1VlkYc (ответы на вопросы)

В Киеве классно:


Не моноспейсом единым
усы2
tonsky
Как вы знаете, я сторонник точки зрения, что код — это еще и красиво (раз, два, три). А что может быть красивее, чем листинги в пейперах по Хаскелю? Встречайте:



Собственно, что я сделал? Взял шрифт из LaTeX (Latin Modern Roman), выкинул всю подсветку (курсив только натыкал кое-где, случайно почти, каюсь). Стрелочки — это не лигатуры, это настоящие юникодные стрелки из UnicodeSyntax. Единственная свинья — в Хаскеле народу чуждо чувство прекрасного и они отказались заменять (\...) на (λ...).

Это вполне рабочая тема для Atom. Код пишется. Форматируется, естественно, табами. Пока это самая слабая часть, хочется семантического выравнивания.

Круто? Распробую — напишу, в чем подвох.

О пользе чистых начал
усы2
tonsky

Тут в Гугл Плюсе Евгений Охотников сетует, что наработки 80–90-х годов нельзя переиспользовать в вебе:

Ну вот, допустим, кто-то 20-ть лет назад сделал движок текстового или графического редактора. Не суть важно, на C++, Eiffel, Java или Delphi. Для десктопа, понятное дело, т.к. Web тогда только зарождался. Какое-то время этот движок был актуальным и мог быть портирован под разные платформы путем адаптации GUI-библиотеки (или же путем написания слоя между движком и конкретной GUI-библиотекой).

Но с окончательной победой Web-приложений над здравым смыслом (т.е. где-то лет 10 назад по моим субъективным наблюдениям), у разработчиков такого движка встал бы серьезный вопрос: а как все имеющиеся наработки портировать под Web? В котором на клиенте нормально живет только JS, а технологии обмена информацией между клиентом и сервером где-то на уровне каменного века? :)

Кроме как путем серьезнейшей переделки потрохов не получится, имхо. Что, как мне представляется, хорошо видно на примере MS Office, который вышел в Web относительно недавно. И где потребовалось много времени и сил на то, чтобы переиспользовать старый код в Office 365, дописав к нему новых клиентов (своих для каждой платформы).

Все так, но это скорее хорошо, чем плохо.

Любая система рано или поздно упирается в локальный максимум, из которого уже не может выбраться эволюционным путем. Интерфейсы в 80-х мало кто понимал. Отчаянное время. Но и сейчас мы далеки от конечного равновесия: никто не обещает, что через пять лет все опять кардинально не поменяется. Мы пока просто не знаем, как должны выглядеть интерфейсы, программы, да и вообще компьютеры. Делать ставку на долгую поддержку в такой период глупо — наследственность тянет через себя не только хорошие вещи, но и давно неактуальные, а также откровенно плохие. Если вы знакомы с современным Фотошопом, в этом видео видно, откуда растут уши у его многочисленных странностей: Undo по Cmd+Shift+Z, кнопки Preview в эффектах, дурацкие модальные окошки с No pixels selected. Все они прожили по 25 лет.

Чем дольше существует система, тем сильнее обостряется конфликт между новыми потребностями и грузом прошлого. Кода много, его невыгодно переадаптировать, репутация питается только былыми заслугами, программа переходит в режим доживания. Становится выгодно начать с чистого листа. Так за последние 5 лет появились легкие и современные альтернативы Адоби: Скетч, Пиксельматор. Из ниоткуда. Но их экономика понятна: полное переписывание это всегда улучшение минимум на порядок. Новые программы удобнее и актуальнее.

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

Возникает чисто практический вопрос: разве это не безумная прорва работы, сделать что-то хотя бы минимально ценное для пользователя, тот же графический пакет или текстовый редактор? Да, но это и есть проблема: так не должно быть. Нет никаких предпосылок к тому, чтобы разработка Иллюстратора была десятилетней эпопеей на миллионы человеко-часов. Просто наши инструменты несовершенны: разработчики на C++ борются с проблемами, которые присущи не предметной области, а самому инструменту. Включая размер кода, который очень быстро сам по себе становится проблемой. Фокус не в том, где взять столько усилий, сколько вбухивает Адоби. Фокус в том, чтобы делать то же самое быстрее и проще. Этому не научишься, если постоянно доделывать один монолит, поэтому даже хорошо, что GTK не натягивается на HTML. Каждый следующий виток снимает еще одну головную боль, и постепенно, раз за разом, мы придем к нужному состоянию, когда студент сможет написать базовую версию Фотошопа за летние каникулы.


Критерий разумности
усы2
tonsky
Меня в комментариях к предыдущему посту спрашивают, как определить, когда программа что-то по делу спрашивает, а когда нет. Как не проявить излишнюю инициативу и не вступить в конфликт с интересами пользователя? Не истратим ли мы ему интернет, если будем все время что-то обновлять, подкачивать, держать в курсе. Хорошо ли, что Windows сам устанавливает апдейты и перезагружается?

Сейчас научу. Определить, что хорошо, а что плохо — просто. Представьте, что есть вот я, человек, а компьютера нет, и программистов нет, и интернета нет. И вот я хочу что-то сделать. Пока я это делаю, мне хорошо, потому что я делаю то, что я сам хочу. Я хочу писать рассказ, и пока я его пишу, я счастлив, я занимаюсь собственным делом. Как только я начинаю делать что-то, что мне не нужно — скачиваю браузер, закрываю попап, лажу в настройки ворда, подключаюсь к вайфаю, борюсь со стилями, сохраняю, закрываю и открываю файл — даже когда это файл с моим рассказом — я грущу, потому что мне это не нужно. Это нужно технологии, но это не имеет ничего общего со мной и моим рассказом. Вот и все, весь критерий.

Любое движение в направлении моих желаний, моих потребностей — хорошо, это очередной маленький шажок в мир будущего, все, что нет — плохо. Перезагрузка — плохо, потому что мне не нужно перезагружать компьютер. Перезагрузка во время, когда я не сижу за компьютером — хорошо, потому что это технология обеспечивает свои потребности и не маячит у меня перед глазами. Однако нюансы: Windows, во-первых, не может нормально определить, пользуюсь я сейчас компьютером или нет, то есть может прервать мою работу, и во-вторых, она не может все вернуть ровно в том виде, в каком оно было. Она даже ворд назад с тем же файлом открыть не сможет. Хуже всего, она может _потерять_ то, что я написал, а это самый страшный грех для программ на свете. Когда перезагрузка от этих недостатков избавится, станет хорошо.

В этом смысле очень легко понять, что не так с cabal update: я не хочу ведь обновлять <что она там обновляет>, верно? Я пишу код, мне хочется писать код, а эта штука встает на пути, мешает. У меня ведь нет цели в жизни «запускать cabal update», это каприз технологии, ничего со мной общего не имеющий. Если так-то, по чесноку, даже система сборки мне не очень нужна — мне нужен код, но у меня нет задачи его собирать. Вернее даже, мне нужна работающая программа. Системы программирования будущего уберут всю эту ересь, программа будет запускаться, работать и разрабатываться в одном непрерывном процессе, как скульптор лепит скульптуру.

Конечно, мы, программисты, так привыкли, что вот оно все так работает: обо всем нужно просить, явно вызывать, дергать, соединять, настраивать и устанавливать. Руками надежнее, потому что инструменты все ненадежные и тупые — могут съесть платный трафик, забыть обновиться, стереть что-то. Нам кажется, это так и должно быть — но это все временное. Морской капитан 18 века тоже бы не согласился, что паруса и мачты не нужны. Знание Linux, владение командной строкой, API — это местечковые артефакты, всего этого не будет в светлом будущем. Компьютеры будущего будут несравнимо прямее и проще устроены, даже для программистов, с гораздо меньшим количеством ручного управления — и гораздо надежнее, потому что минус человеческий фактор. И это не в ущерб низкоуровневости, скорее она тоже упростится.

Люди не придут к компьютерам, как нам когда-то казалось. То, как мы стали «компьютерно грамотными» — ни одно поколение такого больше не повторит. Не будет дома по-особому пахнущего уголка с жужжащей черной коробкой, никто не будет обучаться Ворду и Экселю, по крайней мене не в большей степени, чем пишущей машинке. В Фейсбуке отказались от термина «пользователи», теперь это просто люди — действительно, странно называть особым словом человека, пользующегося компьютером. Мы же не называем особым словом смотрящих телевизор, или разговаривающих по смартфону. Компьютеры растворятся и придут со стороны бытовых предметов — в одном ряду с миксером, журнальным столиком и ковриком для ванной. В конечном итоге, смысл существования Windows не в том, чтобы существовал Windows. Сам по себе он никому не нужен. Так получилось, что в переходный период без него было нельзя, но не ошибайтесь, что это что-то значимое происходит.

без темы
усы2
tonsky
[~/work/getting-started/haskell] cabal install
Warning: The package list for 'hackage.haskell.org' does not exist. Run 'cabal update' to download it.
Resolving dependencies...
cabal: Could not resolve dependencies:
trying: aicontest-0.1.0.0 (user goal)
next goal: vector (dependency of aicontest-0.1.0.0)
Dependency tree exhaustively searched.


Я не хочу наехать конкретно на Хаскель, просто пример показательный. Много какой софт так написан: он умеет сам определить, в чем проблема и как ее починить, но заставляет пользователя это делать.

Я даже представляю примерно ход мысли, что ли: у разработчика есть модель, как софтом должны пользоваться, и он учит пользователя такими вот ударами хлыста. Затачивает голову под нужный порядок мышления. Это и к GUI-шным вещам часто относится, и к консольным.

Идея о том, что работу, там где это возможно, нужно с пользователя молча снимать, она достаточно недавно пришла в широкие массы (скажем, приложения без файлов и ручного сохранения iOS 2007, автообновление Chrome 2008, автосохранение OS X Lion 2011, background app update в iOS 7/Mavericks: 2013). И это часто все еще некое дополнительное усилие, «фича», особенно для десктопного софта, нежели режим по-умолчанию.

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

Кодефест-2015
усы2
tonsky
Лучшие слайды в моей жизни. Так меня еще никогда не перло. В соответствии с традицией, слайды сразу с полным текстом доклада. Будет ли видео — 50/50, от организаторов зависит.

Щелкайте:


без темы
усы2
tonsky
Один мальчик выложил на GitHub в open source облачный распределенный BigData IoT SaaS мэшап с TDD, BDD, DDD, ATDD, STDD, DRY, CQRS, SPoF, EAFP, IoC, DI, DVCS, YAGNI, TMTOWTDI, convention over configuration, zero configuration, SEO, Scrum, microservices, Docker, Cassandra, Hadoop, Cucumber, responsive isomorphic Angular, machine learning, data mining, loose coupling, event sourcing, FRP и Kanban. Но без MongoDB. Потом его все равно в ад забрали, конечно.

https://twitter.com/nikitonsky/status/578457029876047872

Будьте здоровы!
усы2
tonsky
Согласно вот этой статье из википедии, примерно 18–35% людей чихают при взгляде на солнце. Безусловный рефлекс, генетическая черта.

Я провел опрос в твиттере, действительно, многие признались, что феномен имеет место быть (~25 человек!)

Самые интересные ответы это: «я думал у всех так» (еще один: был уверен, что у всех так) и «постоянно советуют -- не получается чихнуть, посмотри на слонце. Постоянно смотрю как дурак и не чихаю»

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

AnyBar: OS X menubar status indicator
усы2
tonsky


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



Использую лично я для индикации состояния билда (вот плагин для boot-clj). Билд крутится в терминале, а так как экранчик у ноутбука маленький, то терминал на заднем плане где-то. Если сломалось — сразу видно по статус-бару. Вот видик, показывающий, как это работает, на старой версии.

Исходники и ссылка на скачивание на гитхабе:

https://github.com/tonsky/AnyBar

Вступайте в фан-клуб, в общем.

Ну и похвастаться:


Изоморфные веб-приложения: скорее нет, чем да
усы2
tonsky

С тотальной победой React-а и функционального подхода на клиенте может показаться, что будущее одностраничных веб-приложений светло и безоблачно. Однако, даже если предположить, что у нас есть хорошая клиентская база данных навроде DataScript, и мы грамотно организовали потоки данных в приложении, остается вопрос сервера.

Как бы нам этого ни хотелось, данные лежат не в браузере (иногда они, конечно, лежат, но это скорее исключение, да и там уже все не так просто стало). На горизонте появляются тучи, простая и стройная архитектура обрастает некрасивыми хаками. Разные компоненты хотят разные куски данных, иногда куски повторяются, надо решать проблему N+1 select, обратная синхронизация, разделение на начальный префетчинг и доставку дельт. REST это новый ORM (пока, правда, не дотягивающий даже до JDBC), а ORM это путь в никуда. Короче, обычный конфликт: наивную версию сделать просто, но работать она будет неприемлимо, а оптимизации вступают в конфликт с базовыми принципами хорошей архитектуры. Facebook предложил Relay + GraphQL, но ощущения пока такие, что хорошо работать это будет в основном на фейсбуке или чем-то очень похожем: рамки сильнее бенефитов.

Что нужно: язык описания зависимостей по данным и протокол синхронизации на его основе, оптимизируемый, в меру универсальный, компонуемый. В идеале один и тот же язык описывает поток браузер-сервер и потоки внутри браузера: от компонентов к родителям, от родителей в центральный sync hub. Потоки двухсторонние: компоненты отправляют запросы по данным в sync hub, там запрос группируется (компонуемость), отсылается на сервер, и наоборот: сервер пушит данные в браузер, sync hub раскидывает по компонентам, кто на что подписался. Возможно, аналогичную схему «одуванчик» можно повторить и внутри сервера.

Вторая область, где не все гладко и сладко — рендеринг страниц на сервере. Если посмотреть с очень высокой башни, можно увидеть основание из слоновой кости и то, что рендеринг на сервере это бред. У нас есть какое-то хранилище, база, это нормально. Есть приложение, оно в браузере и на js. А вот зачем между базой и клиентом нужна какая-то тонкая прослойка в виде рендеринга каких-то странных кусочков html-шаблонов, которые потом надо как-то частично подставлять в уже работающую страницу? Типичное размазывание отвественности: если мы хотим веб-интерфейс, пусть он будет в одном месте (браузер), и пусть у него там будет под рукой все что нужно. Если согласиться, что естественно не держать никакой view логики на сервере (включая тупые параметры REST-концов типа sort=name&order=asc, которые относятся только к вьюхам, вьюхам, вьюхам), роль сервера становится сильно непонятной.

В идеальной архитектуре сервер — точно такой же равноправный луч звезды, присосавшийся к центральной базе/логу событий, как и клиент в бразуере. Просто у него задачи другие — batch-работу какую-то считать, за метриками следить, почту рассылать по расписанию. Это ни в коем случае не паразитирующий посредник на соединении клиент-база. У клиента уже есть всё, чтобы себя обеспечить, сервер как помощник скорее мешает, чем помогает. К тому же все, вплоть до умеренно-больших проектов, всегда делают один и тот же бэкенд: код генерируется и обслуживается фреймворком и на 90% состоит из тавтологии: возьми table user и переложи ее в user.json. Смысл придумывать, писать и поддежривать прослойку, занимающуюся перекладыванием из формы в базу, если и формы, и базы в принципе уже сами это могут? Дайте им поговорить напрямую. В качестве иллюстрации посмотрите Hoodie и noBackend. Хипстерятина, конечно, но хипстеры же неспроста не хотят писать бэкенд — в нем действительно нет большого смысла.

Но я отвлекся. Если строить свое приложение без сервера, всё как раз получается стройно и логично. Но некоторые противные Гуглы хотят, чтобы по GET /index.html HTTP/1.1 отдавался контент, а не какое-то там веб-приложение. И если мы захотим сделать веб-магазин, то какими бы передовыми мы ни были, и как бы сильно нам ни хотелось сократить траты на разработку и душевное здоровье, под Гугл придется прогнуться.

И тут мы обнаруживаем себя у разбитого корыта. Сколько бы нам уши не жужжали про объединение браузера и клиента, примеры там обычно на уровне «реализовать факториал один раз». А тут настоящий, честный тест: языка, инфраструктуры вокруг него, абстракций, всего. Даже если ClojureScript и кроссплатформенный (через cljx несложно, даже почти удобно писать код, запускающийся и на сервере, и в браузере), то передовой React уже не так охотно готов запускаться на JVM. Надо сразу придумывать какой-то JS-рантайм (очень сподручно, я вам скажу) — но это ладно, его можно и придумать, и даже условно-эффективно (правда, не на JVM, а скорее на node.js). Гораздо интереснее принципиальные вопросы: как выковырять весь свой динамизм из веб-приложения, всякие onClick и onChange (можете себе представить), как эмулировать подгрузку данных, куда девать пуш-механизм (можно ли без него? а если по нему приходит важная часть контента?) и завязки на DOM (React, кстати, пример очень хорошей абстракции-затычки конкретно в этом месте). Ну и немножко поиграть в искусственный интеллект: представьте, что у вас живое приложение, которое рисуется в несколько проходов: сначала костяк, потом идет запрос на сервер (асинхронный, конечно), потом приходят данные (или обрабатывается ошибка), на основании этих данных делается еще N запросов, и так далее. Плюс стоят всякие фишечки, чтобы улучшить User Experience — прогресс-бар там, фоллбеки какие-то, анимации — исключительно для человека, не для Гуглового бота же. В какой-то момент вам нужно решить, что только что приложение было не готово, а вот сейчас уже в таком состоянии, что его можно отдавать Гуглу, надо делать снэпшот и высылать html. Решаемо, конечно, но опять — чувствуете? — очень сложно и местечково вместо красоты и фиалок.

И это хорошо еще если мы сможем хорошо подгрузку данных замокать (скажем, если у нас есть тот самый воображаемый язык из начала статьи). Но если для полной универсальности сервер-сайд приложение будет само на себя ходить по REST-концам, ну, там, с декодированием JSON-а, аутентификацией, эмуляцией cookie storage — я, пожалуй, в этом месте сразу на пенсию и мемуары переключусь. Программисты всю жизнь делали нестыкуемые между собой платформы (сколько сил вгрохано в проекты из серии «А это тот же X, только для Питона»). Сейчас жизнь прижала, деваться некуда, и мне, если честно, страшно смотреть, что из этого выйдет. Пока выходят ужасы из серии «перепишем git на js» и «запустим js внутри JVM/Монги/nginx».

Короче, различий между живым браузером и статичной версией для Гугла столько, что впору призадуматься: а нужна она вообще, эта изоморфность (не смейтесь, это термин из JS)? То есть нужна, конечно, но похоже что наскоком ее не сделать. Даже, скорее, если ее и делать, то с самого начала, честно, основательно, и придется многим поступиться. Причем границы этого пока туманно очерчены, но может оказаться, что с такими требованиями мы обратно придем к статичным веб-страницам и тонкому клиенту. Потому что сама постановка вопроса, она такая, несовместимая со здравым смыслом.

В общем-то, мы хотели научиться делать сложные интерфейсы в вебе, мы их научились делать. Правда, появилась новая проблема: сделать индексируемую веб-страничку.


Неглубокое погружение
усы2
tonsky
Написал про то, как внутри работает DataScript:

http://tonsky.me/blog/datascript-internals/

Навык привычки
усы2
tonsky

Около месяца назад я решил оптимизировать клавиатурную раскладку. Прикинув, сколько и чего я пишу в последнее время (Clojure, CSS, русский/латинский текст), я сделал следующие оптимизации:

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

Общее направление — минимизировать количество нажатий шифта, что должно уменьшить нагрузку на пальцы. Это не универсальный рецепт, многое зависит от того, чем вы занимаетесь — скажем, в CSS и в JS имеет смысл вынести на безшифтовой режим фигурные скобки.

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

    cljs (97) —————————————

    backslash            \      503           81   |
     brackets           []    25786         3142   {}
        colon            ;     5079  <<     7769   :
         dash            -    23239         1606   _
      numbers   1234567890     9598  <<    85609   !@#$%^&*()
         plus            =     1866          490   +
        punct           ,.     8730         1651   <>
       quotes            ‘      827  <<     8544   “
        slash            /     4575         4226   ?
        tilda            `      142           10   ~

    css (7) —————————————

     brackets           []       26  <<      600   {}
        colon            ;      818          866   :
         dash            -      564          184   _
      numbers   1234567890     1757          458   !@#$%^&*()
         plus            =       11            1   +
        punct           ,.      560           51   <>
       quotes            ‘       60           24   “
        slash            /       56            0   ?

    js (2) —————————————

    backslash            \       71  <<     1094   |
     brackets           []     2564  <<     9168   {}
        colon            ;     4736         5409   :
         dash            -     1516  <<     2917   _
      numbers   1234567890     5437  <<    25052   !@#$%^&*()
         plus            =     6720          970   +
        punct           ,.    20530          549   <>
       quotes            ‘     2794  <<     6924   “
        slash            /     5279          517   ?
        tilda            `     1492            2   ~

Две цифровые колонки посередине — это частотность символов из группы. Знак << означает что имеет нехилый смысл поменять кнопку и ее шифтовый эквивалент.

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

(let [[x & xs] @atom]
  (swap! *context* #(assoc % :key "abc")))

Самое интересное здесь — это процесс адаптации. Для меня это не новый опыт — у меня уже есть клавиатура с нестандартной раскладкой, вот такая:

Так вот, у нее прямо в инструкции написано: сразу вы на ней печатать не будете. Вы помучаетесь примерно неделю, будете промахиваться мимо клавиш, печатать со скоростью второклассника, выводящего буквы в прописях, захотите это дело забросить, не раз придете в бешенство. Потерпите. Через неделю вы привыкните, будете печатать как ни в чем не бывало. Трудности даже не вспомните. Главное, что оно того стоит.

И они оказались правы. Примерно так процесс адаптации и происходит. Я прошел его один раз с клавиатурой, и вот недавно второй раз с новой раскладкой.

Забавнее всего, что в процессе обучения подобным механическим навыкам не участвует личность. Мы привыкли говорить — я знаю, я умею, мне нужно научиться. Здесь личность только мешает — учиться неохота, эмоции переполняют, ничего не получается, выигрыш далеко за горизонтом и вообще сомнительный. Проще всего к тренировке подойти отстраннено: как будто ты не себя тренируешь, а собаку. Чужую какую-то собаку. На входе энное количество механических повторений, некая регулярность. На выходе собака умеет печатать. Хочет она, не хочет, даже если она принципиально против — обучение встроено в организм и мозгом не управляется. Если есть тренировка — собака научится. То, что личность собаки в данном случае совпадает с инициатором тренировки — необязательная деталь.

То же самое и со многими другими видами обучения — новый редактор, новый язык программирования, новый курс на Курсере. Полезно смотреть за собой, улавливать структуру поведения, четко разделять цель (научиться чему-то), процесс обучения и собственную эмоциональную реакцию на него. Последнее надо научиться изолировать — эмоции идут и развиваются сами по себе, влиять на процесс они не должны.


Расширяемость
усы2
tonsky

Ковырялся я тут на досуге во внутренностях react.js, и вот что я хочу сказать вам о JavaScript вообще.

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

Реализация кое-где хромала, конечно. Свойство prototype, к примеру — не путать с идеей прототипов — настоящий бред. Если бы его быстренько — ну, в ES3 там, или раньше — зафиксили, народ бы не ныл и не просил классов. Ну или использование объектов как структуры данных-словаря, до сих пор эпичнейшие баги всплывают, типа того что на npm нельзя создать библиотеку с именем constructor. Мне кажется, именно из-за этого JS-программистов и следом вообще всю frontend-разработку не считают за «настоящее» программирование.

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

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

Ведь почему мы так любим Кложу? Потому что в ней принято делать открытые системы (с подачи Рича, конечно). Первое — библиотеки гоняют данные, и на вход, и на выход, и внутри. Данные, понятно, открыты, это не классы, их легко распечатать, легко поменять, сгенерировать в нужном виде — короче, библиотека никак не диктует, что и как вам делать с данными. Второе — протоколы, протоколом прикинуться легко. Третье — открытые неймспейсы, куда можно при необходимости залезть, посмотреть, поменять что-то. Позволяет, например, тестировать даже то, что для тестирования не предназначалось.

Это приводит к тому, что почти всегда библиотеку на Кложе можно понять и можно заставить делать то, что нужно. Очень трудно загнать пользователя в угол, если только специально не прилагать усилий. Это важно, и я рад, что Кложе-сообщество подхватило этот тренд.

Но куда идет общественное мнение? Общественное мнение склоняется к тому, что разработчику библиотеки виднее, что выставлять наружу, а что нет. Приватные свойства, закрытые лексические скоупы, захваченные через замыкание функции и свойства без постоянного имени, проверка конкретного типа вместо протокола или утиной типизации. Все это потихоньку втаскивается в JS как зарекомендовавшие себя практики из «большого» программирования, но это и убивает всю прозрачность JS.

Не надо так.


?

Log in