<?xml version='1.0' encoding='utf-8' ?>
<!--  If you are running a bot please visit this policy page outlining rules you must respect. https://www.livejournal.com/bots/  -->
<rss version='2.0'  xmlns:lj='http://www.livejournal.org/rss/lj/1.0/' xmlns:media='http://search.yahoo.com/mrss/' xmlns:atom10='http://www.w3.org/2005/Atom'>
<channel>
  <title>Блокнотик Centaur’а</title>
  <link>https://yurikhan.livejournal.com/</link>
  <description>Блокнотик Centaur’а - LiveJournal.com</description>
  <lastBuildDate>Wed, 18 Jan 2017 09:21:24 GMT</lastBuildDate>
  <generator>LiveJournal / LiveJournal.com</generator>
  <lj:journal>yurikhan</lj:journal>
  <lj:journalid>6749321</lj:journalid>
  <lj:journaltype>personal</lj:journaltype>
  <image>
    <url>https://l-userpic.livejournal.com/130329012/6749321</url>
    <title>Блокнотик Centaur’а</title>
    <link>https://yurikhan.livejournal.com/</link>
    <width>100</width>
    <height>100</height>
  </image>

  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/70024.html</guid>
  <pubDate>Wed, 18 Jan 2017 09:21:24 GMT</pubDate>
  <title>Типы данных для идентификаторов</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/70024.html</link>
  <description>&lt;p&gt;В языках программирования категорически не хватает типов &lt;code&gt;id32_t&lt;/code&gt; и &lt;code&gt;id64_t&lt;/code&gt;. Внутреннее представление — целое соответствующей битности, набор операций — только сравнение на равенство и неравенство. Ну, может, ещё линейный порядок, для использования в качестве ключей в упорядоченных контейнерах. Но точно без арифметики.&lt;/p&gt;

&lt;p&gt;Навеяно очередным ворнингом о неявном преобразовании из знакового в беззнаковое или обратно.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/69129.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/69129.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/70024.html?view=comments#comments</comments>
  <category>work</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/69823.html</guid>
  <pubDate>Wed, 28 Dec 2016 06:49:39 GMT</pubDate>
  <title>Новогоднее</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/69823.html</link>
  <description>&lt;p&gt;Dashing through the snow&lt;br /&gt;
In a one horse open sleigh&lt;br /&gt;
I went for a walk&lt;br /&gt;
On a winter day.&lt;br /&gt;
Bells on bob tails ring&lt;br /&gt;
Making spirits bright&lt;br /&gt;
California dreaming&lt;br /&gt;
On such a winter… night? 😮&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/68971.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/68971.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/69823.html?view=comments#comments</comments>
  <category>центон</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/69499.html</guid>
  <pubDate>Fri, 02 Dec 2016 16:48:12 GMT</pubDate>
  <title>Purple Tentacle keyboard</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/69499.html</link>
  <description>&lt;p&gt;Окей, оно готово. За этот отпуск я сделал себе клавиатуру.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;max-width: 100%&quot; src=&quot;https://imgprx.livejournal.net/574fad650af05396bc1ecf62ba1293e051364ad99ff279d9e413b63c3c932166/P2WlxyVijxKvg25v9cdSUkMdsf-ah7h0xluQTrlbjt6d9BHAndSnRkMpT056H0p0pQ0HzGyIMlIURR8HmAE58EcdjzjMN-SR4V9EoV9rOhWuDg:q0eC_sEuG9SdvrtSBlknIg&quot; fetchpriority=&quot;high&quot;&gt;&lt;/p&gt;

&lt;p&gt;Клавиши — Matias Quiet Click. Реально стучат тише, а тактильный фидбек ярче, чем у Cherry MX Brown.&lt;/p&gt;

&lt;p&gt;Корпус конструкции «бутерброд»: дно — нержавеющая сталь 1 мм, стенки — оргстекло 10 мм, монтажная пластина — снова нержавеющая сталь 1 мм, сверху рамка опять из оргстекла.&lt;/p&gt;

&lt;p&gt;Электроника собрана методом бесплатного монтажа (то есть без печатной платы).&lt;/p&gt;

&lt;p&gt;Подставки под ладони — от клавиатуры Matias Ergo Pro. Мягкие, гелевые, прикольные.&lt;/p&gt;

&lt;p&gt;Внутри — микроконтроллер Freaduino Micro (аналог Arduino Micro), на чипе Atmel ATMega32U4. Его пинов ввода-вывода как раз хватает на матрицу из 12 полурядов по 8 клавиш и на три светодиода.&lt;/p&gt;

&lt;p&gt;Прошивка — TMK Keyboard Firmware by Jun «hasu» Wako. Скомпилировалась, прошилась и заработала буквально с полпинка.&lt;/p&gt;

&lt;p&gt;Раскладка по мотивам Truly Ergonomic и Keyboardio. Примерная логическая раскладка &lt;a href=&quot;http://www.keyboard-layout-editor.com/#/gists/7ff511dfa12e47cab36f642bfe9ae19a&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;тут&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Потратил на всё это около 215 долларов США, вместе со всеми пересылками, лазерной резкой прототипа и деталей корпуса. То есть сравнимо со стоимостью массово производимых клавиатур такого класса. И ещё осталось полкоробки клавиш на второй экземпляр.&lt;/p&gt;

&lt;p&gt;Со временем выложу все исходники как open source hardware.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/68819.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/68819.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/69499.html?view=comments#comments</comments>
  <category>purple tentacle</category>
  <category>keyboards</category>
  <lj:security>public</lj:security>
  <lj:reply-count>6</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/69179.html</guid>
  <pubDate>Thu, 17 Nov 2016 18:31:46 GMT</pubDate>
  <title>Тизер</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/69179.html</link>
  <description>&lt;p&gt;Тестируем ранний прототип.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://imgprx.livejournal.net/f4a9f0720de054c0496fec42f325643df05244dc67b2a9044f1143158f334a96/P2WlxyVijxKvg25v9cdSUkMdsf-ah7h0xluQTrlbjt6d9BHAndSnRkMpT056H0p0pQ0HzGyIMlIURR8HmAE58EcdjzieaaSH6FZZqhQsPhf_B62TpsYMlA:HF6ka6MD8To-fvRWUI5F-A&quot; style=&quot;width: 100%&quot; fetchpriority=&quot;high&quot;&gt;&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/68604.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/68604.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/69179.html?view=comments#comments</comments>
  <category>keyboards</category>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/68915.html</guid>
  <pubDate>Thu, 03 Nov 2016 08:57:21 GMT</pubDate>
  <title>Ещё об веб-иконки</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/68915.html</link>
  <description>&lt;p&gt;В предыдущих сериях: &lt;a href=&quot;http://yurikhan.livejournal.com/53638.html&quot; target=&quot;_blank&quot;&gt;иконочные шрифты&lt;/a&gt;, &lt;a href=&quot;http://yurikhan.livejournal.com/65496.html&quot; target=&quot;_blank&quot;&gt;отсутствие хинтинга в SVG-иконках&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Новый идиотский тренд: мало того, что иконки запихивают в шрифт, так ещё и задают как лигатуры. То есть слово search, набранное шрифтом Material Icons, превращается в иконку лупы.&lt;/p&gt;

&lt;p&gt;При отсутствии соответствующего шрифта всё это выглядит как ужас:&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;max-width: 100%&quot; src=&quot;https://imgprx.livejournal.net/765eff126869ce51689468f5ef47b048e716768d410f5e260edd124be8431e0b/P2WlxyVijxKvg25v9cdSUkMdsf-ah7h0xluQTrlbjt6d9BHAndSnRkMpT056H0p0pQ0HzGyIMlIVTh8BnAw-7U8OhzrGO-aP_hVXqx5mJhehHuKNs9NHiGEdtxF9b3hX4Ea7tH4:gRo-gxr9_FsfjUR6qc5rAQ&quot; fetchpriority=&quot;high&quot;&gt;&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/68275.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/68275.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/68915.html?view=comments#comments</comments>
  <category>usability</category>
  <category>web</category>
  <category>idiots</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/68857.html</guid>
  <pubDate>Mon, 31 Oct 2016 16:23:30 GMT</pubDate>
  <title>Свой-чужой</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/68857.html</link>
  <description>&lt;p&gt;А вот довелось мне намедни написать емейлом некий запрос (пока не важно) в одну организацию. И сегодня я получил оттуда ответ. С ответом &lt;em&gt;ниже&lt;/em&gt; цитаты.&lt;/p&gt;

&lt;p&gt;Так приятно, чёрт возьми.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/68023.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/68023.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/68857.html?view=comments#comments</comments>
  <category>mail</category>
  <category>netiquette</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/68560.html</guid>
  <pubDate>Thu, 20 Oct 2016 09:38:02 GMT</pubDate>
  <title>Вебдизигнеро-проклинательное</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/68560.html</link>
  <description>&lt;p&gt;У того человека, который придумал, что люди не любят читать чистый чёрный текст, пусть кофе всегда будет разбавлен два к одному.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/67829.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/67829.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/68560.html?view=comments#comments</comments>
  <category>web</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/68206.html</guid>
  <pubDate>Tue, 11 Oct 2016 09:53:00 GMT</pubDate>
  <title>За что я не люблю YAML</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/68206.html</link>
  <description>&lt;p&gt;&lt;a href=&quot;http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Спецификация JSON’а&lt;/a&gt; вмещается в пять страниц и её может читать пятиклассник. Однажды прочитанная, она укладывается в голову навсегда.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.yaml.org/spec/1.2/spec.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Спецификация YAML&lt;/a&gt; — это 84 страницы мелкого умного текста. Попробуйте запомнить, чем отличается &lt;code&gt;unquoted&lt;/code&gt;, &lt;code&gt;&apos;single-quoted&apos;&lt;/code&gt;, &lt;code&gt;&quot;double-quoted&quot;&lt;/code&gt;, &lt;code&gt;| literal&lt;/code&gt; и &lt;code&gt;&amp;gt; folded&lt;/code&gt; скаляры, и как в них работает удаление ведущих пробелов.&lt;/p&gt;

&lt;p&gt;И ещё вот эта грабля с массивами и отображениями, эта дурацкая неоднородность в окрестности нуля:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Массив из двух элементов
array2:
  - foo
  - bar

# Убираем один, получаем массив из одного элемента
array1:
  - foo
  #- bar

# Убираем один, получаем пустой массив?
array0:
  #- foo
  #- bar

# Отображение из двух ключей
map2:
  foo: bar
  baz: quux

# Убираем один, получаем отображение из одного ключа
map1:
  foo: bar
  #baz: quux

# Убираем один, получаем пустое отображение?
map0:
  #foo: bar
  #baz: quux&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;А вот фиг. Значения &lt;code&gt;array0&lt;/code&gt; и &lt;code&gt;map0&lt;/code&gt; — &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Сейчас начнутся возражения, что если тебе нужен пустой массив или пустое отображение, то напиши &lt;code&gt;[]&lt;/code&gt; или &lt;code&gt;{}&lt;/code&gt; соответственно. Ну так продемонстрируйте, как это будет выглядеть в вышеприведённых примерах. Чтоб раскомментирование элемента немедленно приводило обратно к одноэлементной коллекции.&lt;/p&gt;

&lt;p&gt;Опять-таки, если мы согласны писать скобки и запятые, почему мы не пишем JSON?&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/67566.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/67566.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/68206.html?view=comments#comments</comments>
  <category>soft</category>
  <category>json</category>
  <category>yaml</category>
  <category>ansible</category>
  <category>idiots</category>
  <lj:security>public</lj:security>
  <lj:reply-count>7</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/67841.html</guid>
  <pubDate>Sat, 24 Sep 2016 17:48:50 GMT</pubDate>
  <title>Юникодное</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/67841.html</link>
  <description>&lt;p&gt;А вот с каких пор и хрено́в ЖЖ стал заменять юникодные символы на иконки? И как это отключить?&lt;/p&gt;

&lt;p&gt;↔ ← здесь должен быть символ стрелки влево-вправо&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Upd.&lt;/b&gt; Это скрипт Twitter Emoji. Блокировать для начала &lt;code&gt;twemoji.min.js$script&lt;/code&gt;, а там дальше видно будет.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/67135.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/67135.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/67841.html?view=comments#comments</comments>
  <category>lj</category>
  <category>idiots</category>
  <category>unicode</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/67590.html</guid>
  <pubDate>Mon, 12 Sep 2016 08:27:23 GMT</pubDate>
  <title>Мой провайдер идиот</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/67590.html</link>
  <description>&lt;p&gt;Пьеса в трёх действиях, пяти картинах, PG-13 (демонстрация обнажённых сетевых коннекторов, возможно грубая лексика).&lt;/p&gt;

&lt;h2&gt;Действие первое&lt;/h2&gt;
&lt;h3&gt;Картина первая&lt;/h3&gt;

&lt;p&gt;&lt;i&gt;Среда, 2016-09-07, 12:30 UTC+7. &lt;b&gt;Я&lt;/b&gt; сижу на работе. Входит &lt;b&gt;Мониторинг&lt;/b&gt;.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Мониторинг&lt;/b&gt; &lt;i&gt;(красным жирным Ариалом 24pt)&lt;/i&gt;: PROBLEM Alert! &lt;i&gt;(Спокойно:)&lt;/i&gt; Connection to host […] timed out after 10 seconds.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; А! Что! Кого? &lt;i&gt;(Захожу по ssh через IP-адрес от запасного провайдера.)&lt;/i&gt; Доложить обстановку!&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Маршрутизатор:&lt;/b&gt; Докладываю: Дом.ru — исправен, МТС — исправен, внутренняя сеть — исправна, Электронный город — нет линка. Работаем через МТС.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Так держать.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Занавес.&lt;/i&gt;&lt;/p&gt;

&lt;h3&gt;Картина вторая&lt;/h3&gt;

&lt;p&gt;&lt;i&gt;Вечер. &lt;b&gt;Я&lt;/b&gt; дома. Заглядываю на антресоль, проверяю все соединения. Линка нет. Выхожу в тамбур, открываю щиток.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Ух ты, ничоси.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Крупным планом розетка RJ-45 на боковой стенке ниши щитка. На крышке розетки чёрным маркером: «142-ЭГ». Снизу в розетку входит кабель, подписанный «142-4». Сверху — пустое отверстие под кабель провайдера.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;i&gt;&lt;b&gt;Я&lt;/b&gt; снимаю крышку розетки.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Крупным планом та же розетка без крышки. В ней нет остатков жил — кабель выдернут, а не обрезан.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Занавес.&lt;/i&gt;&lt;/p&gt;

&lt;h3&gt;Картина третья&lt;/h3&gt;

&lt;p&gt;&lt;i&gt;Тот же вечер. Чат техподдержки Электронного города.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; У меня пропал кабель. &lt;i&gt;(Описываю последовательность событий, см. выше.)&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Павел&lt;/b&gt; &lt;i&gt;(орфография и пунктуация сохранена)&lt;/i&gt;: Сейчас сформирую Вам заявку, чтобы приехала на место ремонтная бригада, выяснила причину и устранила неисправности. Уточните Ваш контактный номер телефона, подъезд и этаж пожалуйста&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; &lt;i&gt;(оставляю телефон и адрес).&lt;/i&gt; Когда соберётесь чинить, позвоните мне за полчаса.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Павел:&lt;/b&gt; Ближайшее время могу предложить к сожалению только на субботу с 12 дня до 8 вечера. Уточните в какое время будете находиться дома?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Пусть будет 12 дня.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Занавес.&lt;/i&gt;&lt;/p&gt;

&lt;h2&gt;Действие второе&lt;/h2&gt;
&lt;h3&gt;Картина четвёртая&lt;/h3&gt;

&lt;p&gt;&lt;i&gt;Суббота, 2016-09-10, 12:35. &lt;b&gt;Я&lt;/b&gt; дома.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я&lt;/b&gt; &lt;i&gt;(в телефон)&lt;/i&gt;: Заявка 2488669. Мне обещали бригаду с 12 до 13 и позвонить за полчаса. Сейчас 12:36 и ещё никто не звонил.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Оператор:&lt;/b&gt; Минутку. &lt;i&gt;(Музыкальная пауза.)&lt;/i&gt; Я связалась с ремонтниками, они в вашем районе, просто не заметили, что нужно вам позвонить.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Проходит около десяти минут. Звонок в дверь. Входят &lt;b&gt;Ремонтник 1&lt;/b&gt; и &lt;b&gt;Ремонтник 2&lt;/b&gt;.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я&lt;/b&gt; &lt;i&gt;(открываю щиток)&lt;/i&gt;: Вот ваша розетка. Вот мой кабель в квартиру. Вашего кабеля нет.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ремонтник 1:&lt;/b&gt; У, надо доступ на чердак. ЖЭУ сегодня не работает, передоговаривайтесь на понедельник, а мы пошли. &lt;i&gt;(Уходят.)&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я&lt;/b&gt; &lt;i&gt;(закрываю за ними дверь. В телефон:)&lt;/i&gt; Приходили ваши люди, посмотрели на розетку, сказали, что нужен доступ на чердак, развернулись и ушли. Почему о доступе не позаботились заранее?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Оператор:&lt;/b&gt; Часто проблемы с кабелем бывают в подъезде между квартирой и техэтажом.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я&lt;/b&gt;: Я живу на 9 этаже 9-этажного дома. Между мной и техэтажом нет &lt;em&gt;ничего&lt;/em&gt;. Павел должен был сразу догадаться, что доступ к техэтажу понадобится обязательно.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Оператор:&lt;/b&gt; И ещё у операторов поддержки на сайте нет информации о том, как работают управляющие компании.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Надо, чтоб была. А то я теряю время, вы теряете время, ремонтники теряют время.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Оператор:&lt;/b&gt; Давайте переназначим заявку на понедельник. Могу предложить время с 15 до 16.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Позвоните мне за полчаса. Это я сегодня дома и мне в принципе без особой разницы, позвонили мне или нет. А в понедельник я буду на работе и хочу дойти спокойно, а не бегом.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Занавес.&lt;/i&gt;&lt;/p&gt;

&lt;h2&gt;Действие третье&lt;/h2&gt;
&lt;h3&gt;Картина пятая&lt;/h3&gt;

&lt;p&gt;&lt;i&gt;Понедельник, 2016-09-12, 10:25. &lt;b&gt;Я&lt;/b&gt; собираюсь на работу. Выхожу из квартиры в тамбур. Щиток открыт, &lt;b&gt;Ремонтник 3&lt;/b&gt; просовывает приспособление для протяжки кабелей в кабель-канал в сторону чердака.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Здравствуйте. Вы от какой компании?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ремонтник 3:&lt;/b&gt; Электронный город. Мы тут мимо проходили и решили вам заодно кабель протянуть. &lt;i&gt;(Показывает на розетку.)&lt;/i&gt; Вы же переключаетесь?&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Средним планом розетка RJ-45, болтающаяся свободно в щитке. На крышке тем же чёрным маркером: «142-HomeNet». Слева в неё входит кабель с коннектором, справа — кабель.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Ни в коем случае. С чего вы решили? В щитке четыре розетки, подписанные квартирой 142: вот 142-HomeNet, ныне МТС; вот 142-Дом.ru; вот ваша 142-ЭГ, видите, кабеля нет. И ещё вот 142-телефон.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Ремонтник 3:&lt;/b&gt; Ой, я не увидел остальные розетки.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Не надо видеть, надо позвонить и спросить. Ну так вот, вот в этой розетке должен появиться интернет, а вот в этих двух он должен остаться.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Занавес.&lt;/i&gt;&lt;/p&gt;

&lt;h2&gt;Эпилог&lt;/h2&gt;

&lt;p&gt;&lt;i&gt;Понедельник, около 12 часов. &lt;b&gt;Я&lt;/b&gt; на работе.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я&lt;/b&gt; (через ssh): Маршрутизатор, доложить обстановку.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Маршрутизатор:&lt;/b&gt; Дом.ru — исправен, МТС — исправен, внутренняя сеть — исправна; ЭГ — линк есть, но интерфейс опущен. Работаем через МТС.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Я:&lt;/b&gt; Поднять интерфейс ЭГ.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Маршрутизатор:&lt;/b&gt; Есть поднять интерфейс ЭГ. IP-адрес получен. Работаем через ЭГ.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Занавес, хэппи-энд.&lt;/i&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;Вот спрашивается:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Кому могло понадобиться выдрать мне кабель?&lt;/li&gt;
&lt;li&gt;Почему техподдержка на сайте не думает о том, с какой вероятностью понадобится доступ к техэтажу, и как работает ЖЭУ?&lt;/li&gt;
&lt;li&gt;Почему вторая ремонтная команда не звонит мне за полчаса уже после того, как я поругался на первую?&lt;/li&gt;
&lt;li&gt;Что было бы, если бы я по случайному совпадению не вышел из квартиры ровно в то время, когда они там работали? Они бы оторвали мне МТС? Откуда вообще идея, что при починке существующего или протяжке нового подключения можно сломать действующее другое?&lt;/li&gt;
&lt;li&gt;Кто должен был бы исправлять ситуацию дальше?&lt;/li&gt;
&lt;li&gt;Через сколько итераций процесс бы сошёлся?&lt;/li&gt;
&lt;/ul&gt;
&lt;a name=&apos;cutid1-end&apos;&gt;&lt;/a&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/66985.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/66985.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/67590.html?view=comments#comments</comments>
  <category>mts</category>
  <category>dom.ru</category>
  <category>cn.ru</category>
  <category>idiots</category>
  <category>networks</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/67344.html</guid>
  <pubDate>Fri, 02 Sep 2016 13:45:52 GMT</pubDate>
  <title>Логировать фронт, а не уровень</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/67344.html</link>
  <description>&lt;pre&gt;&lt;code&gt;while not done():
    task = pop(queue)
    try:
        do(task)
    except Exception as e:
        log(&quot;Cannot do %s: %s&quot;, task, e)
        # possibly sleep(5)
        # possibly push(queue, task)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Что не так на этой картинке?&lt;/p&gt;

&lt;p&gt;Если ошибка в обработке задачи вызвана внешними условиями — интернет отвалился, сервер упал, место на диске где-то кончилось — то с большой вероятностью она будет повторяться, пока не починится.&lt;/p&gt;

&lt;p&gt;Логи с одной и той же повторяющейся ошибкой с разными задачами читать крайне неинтересно.&lt;/p&gt;

&lt;p&gt;Правильно — запоминать тип результата и логировать его изменение. В том числе — с ошибки на успех: «Ух ты, сервер поднялся, работаем дальше». Или так: «Помнишь того чувака с китайским IP’шником, который всё никак не мог к нам залогиниться по ssh? Так вот он таки зашёл!» 😨&lt;/p&gt;

&lt;p&gt;Design issue — продумать эквивалентность на множестве ошибок. Чтоб, с одной стороны, не спамить, а с другой — не терять полезную информацию.&lt;/p&gt;&lt;a name=&apos;cutid1-end&apos;&gt;&lt;/a&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/66683.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/66683.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/67344.html?view=comments#comments</comments>
  <category>logging</category>
  <category>soft</category>
  <category>usability</category>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/67299.html</guid>
  <pubDate>Mon, 22 Aug 2016 11:01:26 GMT</pubDate>
  <title>CLI как язык</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/67299.html</link>
  <description>&lt;p&gt;Синтаксис аргументов командной строки следует рассматривать и проектировать аналогично синтаксису человеческого языка. В частности, в нём бывают различные части речи и члены предложения.&lt;/p&gt;

&lt;p&gt;Название бинарника может быть глаголом в повелительном наклонении (&lt;code&gt;reboot&lt;/code&gt;) или существительным в роли обращения (&lt;code&gt;firefox&lt;/code&gt;, &lt;code&gt;git&lt;/code&gt;). В последнем случае отсутствие аргументов соответствует запуску приложения с пользовательским интерфейсом; если аргументы есть, то первый — это опять глагол в повелительном наклонении (&lt;code&gt;git fetch&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Ключ без аргумента соответствует наречию, обычно в роли обстоятельства образа действия (&lt;code&gt;--quietly&lt;/code&gt;, &lt;code&gt;--verbosely&lt;/code&gt;; по истерическим перчинам устоялось написание без суффикса -ly).&lt;/p&gt;

&lt;p&gt;Ключ с аргументом — это косвенное дополнение, где имя ключа играет роль предлога (&lt;code&gt;install &lt;b&gt;-t /usr/bin&lt;/b&gt; foo&lt;/code&gt; — &lt;i&gt;установить &lt;b&gt;в /usr/bin&lt;/b&gt; foo&lt;/i&gt;); или уточняющее родовое слово в составе прямого дополнения (&lt;code&gt;install &lt;b&gt;-d /var/lib/foo&lt;/b&gt;&lt;/code&gt; — &lt;i&gt;установить &lt;b&gt;каталог /var/lib/foo&lt;/b&gt;&lt;/i&gt;).&lt;/p&gt;

&lt;p&gt;Позиционный аргумент — это прямое дополнение (&lt;code&gt;git clone git://github.com/git/git.git&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Это, конечно, не все паттерны — что-то я наверняка упустил.&lt;/p&gt;

&lt;p&gt;Базовый язык для команднострочного интерфейса — разумеется, английский. (Если бы командную строку изобрёл японец, глагол ставился бы последним, а &lt;code&gt;sudo&lt;/code&gt; записывалось бы как 下さい [kudasai] после глагола.)&lt;/p&gt;

&lt;p&gt;Собственно, я это всё к чему? У системы виртуализации/контейнеризации LXC есть команды &lt;code&gt;lxc-start&lt;/code&gt;, &lt;code&gt;lxc-stop&lt;/code&gt; и несколько других. И все они принимают название контейнера, над которым работать, именованным аргументом (&lt;code&gt;lxc-start -n foo&lt;/code&gt;). Жутко бесит. Очевидно же, что это должно быть прямое дополнение.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/66551.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/66551.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/67299.html?view=comments#comments</comments>
  <category>soft</category>
  <category>lxc</category>
  <category>syntax</category>
  <category>cli</category>
  <lj:security>public</lj:security>
  <lj:reply-count>4</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/66924.html</guid>
  <pubDate>Fri, 12 Aug 2016 17:20:04 GMT</pubDate>
  <title>[bpi] Диагностика загрузки сервера</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/66924.html</link>
  <description>&lt;p&gt;Недавно я поменял домашний сервер. Раньше на антресоли лежал обычный десктоп, жужжал вентиляторами и жрал электричество. А теперь стоит Banana Pi R1.&lt;/p&gt;

&lt;p&gt;Что хорошо: электричества потребляет всего ничего. На борту двухъядерный гигагерцовый ARM, гигабайт памяти и встроенный свитч о пяти портах наружу и одном на матплату. И 2.5-дюймовый жёсткий диск.&lt;/p&gt;

&lt;p&gt;Что плохо: подсистема питания сделана не очень надёжно, и от этого иногда винчестеру перестаёт хватать питания. Он останавливается, потом пытается снова раскрутиться, потом снова останавливается. И так пока не придёшь и не передёрнешь ему питание.&lt;/p&gt;

&lt;p&gt;Ещё может не повезти и при включении он пойдёт проверять файловые системы. По умолчанию проверка запускается в режиме «проверять, но не чинить». Чтобы чинилось автоматически, нужно прописать в &lt;code&gt;/etc/default/rcS&lt;/code&gt; строчку &lt;code&gt;FSCKFIX=yes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;А ещё хочется видеть прогресс загрузки. Монитор каждый раз не натаскаешься, а надо знать, когда он запустил проверку диска, когда закончил, когда начали подниматься сервисы, и когда загрузка закончена.&lt;/p&gt;


&lt;p&gt;Может быть, потом я соберусь докупить подходящий мелкий мониторчик, но это потом. А сейчас у нас есть один светодиод, контролируемый (под ядром 4.4.14-bananian) псевдофайлом &lt;code&gt;/sys/devices/platform/leds/leds/bananapi:green:usr/trigger&lt;/code&gt;. Собственно, остаётся написать инит-скриптов, которые будут запускаться в правильные моменты и переключать режим светодиода.&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;&lt;th style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Фаза загрузки&lt;/th&gt;
&lt;th style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Условия&lt;/th&gt;
&lt;th style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Триггер&lt;/th&gt;
&lt;th style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Поведение&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Загрузчик (U-boot)&lt;br&gt;Загрузка ядра&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;code&gt;none&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Выключен&lt;br&gt;Мигает два раза светодиодами портов свитча&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Начало runlevel’а S&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;pre&gt;&lt;code&gt;Default-Start: S&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;code&gt;timer&lt;/code&gt;&lt;sup&gt;&amp;dagger;&lt;/sup&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Мигает с частотой 1&amp;nbsp;Гц&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Начало проверки ФС&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;pre&gt;&lt;code&gt;Should-Start: hdparm
Default-Start: S
X-Start-Before: checkroot&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;code&gt;heartbeat&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Две вспышки, пауза, …&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Конец проверки ФС&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;pre&gt;&lt;code&gt;Should-Start: checkfs
Default-Start: S&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;code&gt;timer&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Мигает с частотой 1&amp;nbsp;Гц&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Начало загрузки сервисов&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;pre&gt;&lt;code&gt;Default-Start: 2 3 4 5&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;code&gt;default-on&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Светится ровно&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Система загружена&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;pre&gt;&lt;code&gt;Required-Start: $all
Default-Start: 2 3 4 5&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;&lt;code&gt;none&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: left; vertical-align: baseline&quot;&gt;Выключен&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;&lt;sup&gt;&amp;dagger;&lt;/sup&gt; Чтобы работал триггер &lt;code&gt;timer&lt;/code&gt;, нужно загрузить модуль ядра &lt;code&gt;ledtrig-timer&lt;/code&gt;. Причём обычный способ (через &lt;code&gt;/etc/modules&lt;/code&gt;) работает позже, чем мне это нужно, поэтому ручками, командой &lt;code&gt;modprobe ledtrig-timer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;В &lt;code&gt;/etc/init.d&lt;/code&gt; складываем пять инит-скриптов по следующему шаблону:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#! /bin/sh
### BEGIN INIT INFO
# Provides:          &lt;var&gt;название&lt;/var&gt;
# &lt;var&gt;условия&lt;/var&gt;
# Short-Description: Blink Banana Pi green LED at start of bootup
### END INIT INFO

case &quot;$1&quot; in
start|&quot;&quot;)
    echo &lt;var&gt;триггер&lt;/var&gt; &amp;gt;/sys/devices/platform/leds/leds/bananapi:green:usr/trigger
    ;;
restart|reload|force-reload)
    echo &quot;Error: argument &apos;$1&apos; not supported&quot; &amp;gt;&amp;2
    exit 3
    ;;
stop)
    # No-op
    ;;
status)
    exit 3
    ;;
*)
    echo &quot;Usage: &lt;var&gt;название&lt;/var&gt;.sh [start|stop]&quot; &amp;gt;&amp;2
    exit 3
    ;;
esac

:&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Далее выполняем для них всех &lt;code&gt;update-rc.d &lt;var&gt;название&lt;/var&gt;.sh defaults&lt;/code&gt;, и готово.&lt;/p&gt;&lt;a name=&apos;cutid1-end&apos;&gt;&lt;/a&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/66195.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/66195.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/66924.html?view=comments#comments</comments>
  <category>bananapi</category>
  <category>hard</category>
  <lj:security>public</lj:security>
  <lj:reply-count>4</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/66754.html</guid>
  <pubDate>Mon, 08 Aug 2016 14:22:17 GMT</pubDate>
  <title>Омонимическое</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/66754.html</link>
  <description>&lt;p&gt;Из обсуждения, как людям объяснять Git:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;X: Do &lt;em&gt;not&lt;/em&gt; mention DAG to people who do not have a formal computer science background. […] The word “graph” has a completely different meaning to laypeople.&lt;/p&gt;

&lt;p&gt;Me: You mean the graph plot? Well, in Russian the word for graph-as-in-graph-theory is an homonym of the word for count-as-in-count-Dracula.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/65925.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/65925.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/66754.html?view=comments#comments</comments>
  <category>git</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/66443.html</guid>
  <pubDate>Mon, 08 Aug 2016 10:46:59 GMT</pubDate>
  <title>Альтернативная этимология</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/66443.html</link>
  <description>&lt;dl&gt;
&lt;dt&gt;ар‧хи‧ва́ж, &lt;i&gt;сущ., неод., м., 2-е скл.&lt;/i&gt;&lt;/dt&gt;
&lt;dd&gt;Действие по гл. &lt;i&gt;архивировать&lt;/i&gt;.&lt;/dd&gt;
&lt;dt&gt;ар‧хи‧ва́ж‧ный, &lt;i&gt;прил.&lt;/i&gt;&lt;/dt&gt;
&lt;dd&gt;Относящийся к архиважу. &lt;i&gt;Я к вам по архиважному вопросу.&lt;/i&gt;&lt;/dd&gt;
&lt;/dl&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/65668.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/65668.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/66443.html?view=comments#comments</comments>
  <category>puns</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/66048.html</guid>
  <pubDate>Tue, 05 Jul 2016 19:10:42 GMT</pubDate>
  <title>Язык для описания графов</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/66048.html</link>
  <description>&lt;p&gt;Хочу человеческий синтаксис для описания графов.&lt;/p&gt;

&lt;p&gt;Что у нас сейчас есть: &lt;a href=&quot;https://en.wikipedia.org/wiki/Category:Graph_description_languages&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Graph description languages&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Половина из них основана на XML, что хорошо для инструментов, но плохо для написания руками.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;DOT спроектирован математиками и из-за этого тоже излишне многословен. Мы можем определить в графе дефолтные свойства вершин и рёбер, и это позволяет немного экономить. Но если у нас в графе два типа рёбер, то один можно сделать дефолтным, а второй приходится выписывать каждый раз:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;digraph G {
  edge [arrowhead=empty] # inheritance

  Derived -&amp;gt; Base

  Aggregate -&amp;gt; Part [arrowtail=odiamond, arrowhead=open] # aggregation
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Или можно определить подграф и рёбра второго типа определять в нём, что плохо для локальности (часто хочется описывать рёбра, относящиеся к одной вершине, рядом):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;digraph G {
  subgraph {
    edge [arrowhead=empty] # inheritance
    Derived -&amp;gt; Base
  }
  subgraph {
    edge [arrowtail=odiamond, arrowhead=open] # aggregation
    Aggregate -&amp;gt; Part
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Как надо:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Есть классы вершин и рёбер. Все общие свойства вершин или рёбер одного класса описываются в определении класса. Важно, что определения классов можно вынести в библиотеки и подключать их, когда надо.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Минимальное определение вершины состоит из имени класса вершины и имени вершины, на отдельной строке, через пробел. Далее опционально индивидуальные свойства вершины. (Тут решить между синтаксисом со скобками и разделителями или просто indentation-based.) Имя может быть одним словом или произвольной строкой в кавычках.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Минимальное определение ребра состоит из имени начальной вершины, имени класса ребра и имени конечной вершины, также на отдельной строке через пробел, также с опциональным блоком свойств.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Пример:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;node.class [shape=box]
node.interface [shape=circle]
edge.is-a [arrowhead=empty]
edge.implements [arrowhead=empty, style=dashed]
edge.has-a [arrowtail=odiamond, arrowhead=open]
edge.owns-a [arrowtail=diamond, arrowhead=open]

interface IThing

class Base

class Derived
Derived is-a Base
Derived implements IThing

class Part

class Aggregate
Aggregate has-a Part&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Буду в отпуске, сяду и напишу парсер этого и конвертор в DOT.&lt;/p&gt;

&lt;p&gt;Stretch goal: какой-нибудь способ указать, что одни «node1 relation node2» отображать рёбрами, а другие — вложением в кластер-подграф. Типа &lt;code&gt;nginx deployed-on cache-server&lt;/code&gt;.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/65344.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/65344.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/66048.html?view=comments#comments</comments>
  <category>design</category>
  <category>graphviz</category>
  <category>wishlist</category>
  <lj:security>public</lj:security>
  <lj:reply-count>6</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/65898.html</guid>
  <pubDate>Sat, 02 Jul 2016 16:03:11 GMT</pubDate>
  <title>Альтернативная химия</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/65898.html</link>
  <description>&lt;p&gt;Где-то в параллельной вселенной магнаты и магниты — это соли магниевой и магнистой кислот, соответственно.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/65105.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/65105.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/65898.html?view=comments#comments</comments>
  <category>puns</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/65718.html</guid>
  <pubDate>Sun, 26 Jun 2016 15:35:36 GMT</pubDate>
  <title>Электрический свет продолжает наш день</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/65718.html</link>
  <description>&lt;p&gt;Берём таблицу &lt;a href=&quot;http://world-weather.ru/pogoda/russia/novosibirsk/sunrise/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;времён восхода/заката&lt;/a&gt; за последний год. Видим такую фигню: зимой восход в девять, закат в четыре. Летом восход в четыре, закат в девять. Астрономический полдень плавает в районе 12:30. Что как бы указывает на примерное соответствие поясного и астрономического времени, но ни фига не соотносится с реальными надобностями.&lt;/p&gt;

&lt;p&gt;Если у меня рабочий день начинается скрам-митингом в 11:00 и кончается в 19:30, то просыпаюсь я в 9–9:30. Значит, летом первые пять часов светового дня я тупо просыпаю. А вечером темнеет раньше, чем хочется спать.&lt;/p&gt;

&lt;p&gt;Зимой с утром как-то получше, но вся вторая половина рабочего дня приходится на световую ночь.&lt;/p&gt;

&lt;p&gt;Впрочем, в этом году новосибирские чиновники внезапно взялись за ум (или что у них есть… ещё там), провели опрос и с 24 июля зона Asia/Novosibirsk переходит из UTC+6 в UTC+7. Соответственно, световой день летом — с пяти до десяти, зимой — с десяти до пяти, полдень ≈13:30.&lt;/p&gt;

&lt;p&gt;Как по мне, направление правильное, но мало. Будь моя воля, я б токийское время установил, UTC+9.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/64906.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/64906.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/65718.html?view=comments#comments</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/65496.html</guid>
  <pubDate>Thu, 02 Jun 2016 18:52:07 GMT</pubDate>
  <title>О граблях SVG-иконок</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/65496.html</link>
  <description>&lt;p&gt;Четыре года назад я &lt;a href=&quot;http://yurikhan.livejournal.com/53638.html&quot; target=&quot;_blank&quot;&gt;жаловался&lt;/a&gt; на тенденцию запихивать векторные иконки в кастомные шрифты и стучал ногами, что надо использовать SVG. В этом году ГитХаб это сделал.&lt;/p&gt;

&lt;p&gt;Ну и что же мы теперь имеем: мыло.&lt;/p&gt;

&lt;p&gt;Потому что в шрифтах есть хинтинг, привязывающий тонкие линии к пиксельной сетке. А в SVG его &lt;a href=&quot;https://www.w3.org/Graphics/SVG/WG/wiki/Proposals/SVG_hinting&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;ещё&lt;/a&gt; нет.&lt;/p&gt;

&lt;p&gt;Поэтому вот они нарисовали иконки, выровняли их так, чтоб при дефолтных стилях было чётко, ну и всё. А я предпочитаю шрифт достаточного размера и интерлиньяж посвободнее, и у меня на рабочем месте они съезжают на полпикселя. Причём не все. (На домашней машине у меня HiDPI, поэтому SVG-иконки выглядят просто отлично.)&lt;/p&gt;

&lt;p&gt;По-правильному, надо в SVG для тех линий, которые важно привязать к сетке, указывать атрибут &lt;code&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;shape-rendering=&quot;crispEdges&quot;&lt;/a&gt;&lt;/code&gt;. Но в качестве костыля можно накладывать его сверху при помощи юзерстиля. Только для тех иконок, где есть тонкие вертикальные или горизонтальные линии.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@namespace svg url(http://www.w3.org/2000/svg);

@-moz-document domain(&quot;github.com&quot;) {
  
  .octicon-plus, .octicon-file-directory, .octicon-file-text,
  .octicon-graph, .octicon-book, .octicon-trashcan, .octicon-repo,
  .octicon-comment
  { shape-rendering: crispEdges !important; position: relative; left: 0.1px }

}&lt;/code&gt;&lt;/pre&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/64693.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/64693.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/65496.html?view=comments#comments</comments>
  <category>github</category>
  <category>svg</category>
  <category>web</category>
  <category>icons</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/65074.html</guid>
  <pubDate>Thu, 02 Jun 2016 18:14:11 GMT</pubDate>
  <title>Задачка проектировщику протоколов</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/65074.html</link>
  <description>&lt;p&gt;Раздаточный материал: &lt;a href=&quot;http://extapi.wialon.com/hw/cfg/WialonRetranslator%201.0.pdf&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Описание
протокола WialonRetranslator 1.0&lt;/a&gt; (PDF, 156K, 3 не очень плотных страницы)&lt;/p&gt;

&lt;p&gt;Задача 1: Перечислите ошибки, допущенные при документировании этого протокола.&lt;/p&gt;

&lt;p&gt;Задача 2*: Перечислите ошибки, допущенные при проектировании этого протокола.&lt;/p&gt;

&lt;p&gt;Комменты &lt;strong&gt;не&lt;/strong&gt; скринятся. Ответы выложу через пару-тройку дней.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Upd:&lt;/b&gt; &lt;span  class=&quot;ljuser  i-ljuser  i-ljuser-type-P     &quot;  data-ljuser=&quot;kgeorgiy&quot; lj:user=&quot;kgeorgiy&quot; &gt;&lt;a href=&quot;https://kgeorgiy.livejournal.com/profile/&quot;  target=&quot;_self&quot;  class=&quot;i-ljuser-profile&quot; &gt;&lt;img  class=&quot;i-ljuser-userhead&quot;  src=&quot;https://l-stat.livejournal.net/img/userinfo_v8.png?v=17080&amp;v=923.1&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://kgeorgiy.livejournal.com/&quot; class=&quot;i-ljuser-username&quot;   target=&quot;_self&quot;   &gt;&lt;b&gt;kgeorgiy&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; нашёл практически все ошибки документирования.&lt;/p&gt;

&lt;p&gt;Ответы&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; не указан рекомендуемый TCP-порт.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Спорное решение:&lt;/b&gt; бинарный протокол. Лучше было взять json и паковать его gzip’ом.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка проектирования:&lt;/b&gt; протокол не самосинхронизирующийся — начав с середины потока, нельзя найти начало ближайшего полного пакета.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Неудачная терминология:&lt;/b&gt; «пакет». Ассоциируется с пакетами TCP/IP.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Неоднозначная терминология:&lt;/b&gt; «байт». Однозначный термин — «октет».&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; из всех характеристик, которыми задаются целочисленные и вещественные поля, указаны только размеры. Для целых чисел длиннее 1 байта нужно задавать ещё порядок байт (little- или big-endian); для всех целых — знаковость (знаковое или беззнаковое); для знаковых — представление отрицательных чисел (two’s complement, one’s complement, sign-and-magnitude, biased). Для вещественных — порядок байт; плавающая или фиксированная точка; если фиксированная, то по какому основанию и сколько разрядов; если плавающая, то какие биты отвечают за мантиссу, какие за экспоненту. (Достаточно сказать слово IEEE 754.)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка проектирования:&lt;/b&gt; размер всего пакета — little-endian, все остальные целочисленные поля — big-endian, все вещественные поля — little-endian. Следовало взять один порядок и придерживаться его.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; не указана кодировка текстовых полей (ASCII или UTF-8; если текст в каких-то других кодировках, то это ошибка проектирования).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка проектирования:&lt;/b&gt; конец строки определяется по нулевому байту. В бинарном протоколе удобнее передавать длину строки в начале.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; для поля времени не указана точка отсчёта (1970-01-01T00:00:00Z).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; не объяснено назначение флагов.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка проектирования:&lt;/b&gt; флаги частично дублируют имя блока.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; для набора блоков не указана минимальная и максимальная кратность, не сказано, могут ли повторяться блоки с одинаковым именем, и важен ли порядок.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; не перечислены возможные значения типа блока. В примере все блоки имеют тип 3003 (0xBBB) и не объясняется его назначение.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; для полей «Размер пакета» и «Размер блока» не указано, от какого и до какого октета считать.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; не описана семантика скрытия параметров.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; для физических величин не указана единица измерения, направление, начало отсчёта и область значений. (Пример: долгота в градусах к востоку от Гринвича (от −180 до, но не включая 180), широта в градусах к северу от экватора (от −90 до 90 включительно), высота в метрах над уровнем моря, скорость в километрах в час (≥ 0), курс в градусах по часовой стрелке от истинного севера (от 0 до, но не включая 360).)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка проектирования:&lt;/b&gt; поле долготы поставлено перед полем широты. Канонический порядок географических координат — (широта, долгота[, высота]).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; «являются интуитивно понятными». Что именно нужно было задокументировать — &lt;del&gt;интуитивно понятно&lt;/del&gt; тип данных для всех блоков, единицу измерения для напряжения и уровня сигнала gsm, семантику всех блоков.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; вопросы тайминга пакетов и подтверждений («Следующий пакет не передаётся, пока не получено подтверждение для предыдущего» или что-то такое).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; полупустая страница перед разбором примера создаёт впечатление конца документа.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ошибка документирования:&lt;/b&gt; шестнадцатеричные дампы в примере следовало разбить на октеты и строчки по 16 октетов и подписать смещения для удобства чтения.&lt;/li&gt;
&lt;/ul&gt;
&lt;a name=&apos;cutid1-end&apos;&gt;&lt;/a&gt;

&lt;p&gt;Вот с такой фигнёй иногда приходится работать.&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/64444.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/64444.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/65074.html?view=comments#comments</comments>
  <category>protocols</category>
  <category>soft</category>
  <category>work</category>
  <lj:security>public</lj:security>
  <lj:reply-count>3</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/64960.html</guid>
  <pubDate>Sat, 16 Apr 2016 16:10:45 GMT</pubDate>
  <title>Кроссоверное</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/64960.html</link>
  <description>&lt;p&gt;&lt;a href=&quot;http://lib.ru/CARROLL/alisa2.txt&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;На столе лежала&lt;/a&gt; какая-то книга; Алиса взяла её и стала листать, поглядывая время от времени на Белого Короля. (Она всё ещё волновалась за него и держала чернила наготове — на случай, если ему снова станет плохо.) Она надеялась, что сумеет прочитать в книге хоть одну страничку, но всё было написано на каком-то непонятном языке.&lt;/p&gt;

&lt;p&gt;Вот как это выглядело.&lt;sup&gt;8&lt;/sup&gt;&lt;/p&gt;

&lt;div style=&quot;display:inline-block;transform:scalex(-1)&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;http://omiliya.org/article/puski-byatye-lyudmila-petrushevskaya.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Пуськи бятые&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Сяпала Калуша с Калушатами по напушке. И увазила Бутявку, и волит:&lt;/p&gt;
&lt;p&gt;— Калушата! Калушаточки! Бутявка!&lt;/p&gt;
&lt;p&gt;Калушата присяпали и Бутявку стрямкали. И подудонились.&lt;/p&gt;
&lt;p&gt;А Калуша волит:&lt;/p&gt;
&lt;p&gt;— Оёё! Оёё! Бутявка-то некузявая!&lt;/p&gt;
&lt;p&gt;Калушата Бутявку вычучили.&lt;/p&gt;
&lt;p&gt;Бутявка вздребезнулась, сопритюкнулась и усяпала с напушки.&lt;/p&gt;
&lt;p&gt;А Калуша волит калушатам:&lt;/p&gt;
&lt;p&gt;— Калушаточки! Не трямкайте бутявок, бутявки дюбые и зюмо-зюмо некузявые. От бутявок дудонятся.&lt;/p&gt;
&lt;p&gt;А Бутявка волит за напушкой:&lt;/p&gt;
&lt;p&gt;— Калушата подудонились! Зюмо некузявые! Пуськи бятые!&lt;/p&gt;
&lt;/div&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/64012.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/64012.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/64960.html?view=comments#comments</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/64636.html</guid>
  <pubDate>Tue, 02 Feb 2016 14:57:53 GMT</pubDate>
  <title>Луч поноса широким сайтам</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/64636.html</link>
  <description>&lt;p&gt;Когда я пришёл в веб, считалось дурным тоном делать сайты, не помещающиеся в 800×600.&lt;/p&gt;

&lt;p&gt;Потом распространились разрешения 1024×768, 1152×864, 1280×1024 и, наконец, 1600×1200. В какой-то момент вебостроители решили, что 1024 пикселя в ширину есть у всех. А у кого нет, тот лох.&lt;/p&gt;

&lt;p&gt;Потом пошла мода на 16:10 и 16:9 и разрешения типа 1920×1080. И вот про это разрешение поговорим подробнее.&lt;/p&gt;

&lt;p&gt;Дело в том, что при 24 дюймах диагонали, формате 16:9 и разрешении 1920×1080 CSS-пикселей &lt;small&gt;(тех, которые 1/96 дюйма, а не обязательно один минимальный элемент изображения)&lt;/small&gt; уже начинает быть удобно работать не с одним развёрнутым на весь экран окном, а с двумя неперекрывающимися половинками. И в такой конфигурации сайту в браузере остаётся 960px ширины, с поправкой на скроллбар — ≈940px.&lt;/p&gt;

&lt;p&gt;Сто́ит вспомнить правила приличия девяностых и двухтысячных. Сайт не должен вызывать горизонтального скроллинга при ширине окна в 940px.&lt;/p&gt;

&lt;p&gt;(Персональные лучи поноса — Альфа-Клику, Гитхабу, Гуглу, Джире, Пейпэлу, библиотеке Сафари Букс Онлайн, всей сети Стек Эксчендж и Яндекс-Погоде.)&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/63991.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/63991.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/64636.html?view=comments#comments</comments>
  <category>css</category>
  <category>usability</category>
  <category>web</category>
  <lj:security>public</lj:security>
  <lj:reply-count>9</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/64460.html</guid>
  <pubDate>Wed, 20 Jan 2016 18:06:40 GMT</pubDate>
  <title>Раздумья о файловых менеджерах</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/64460.html</link>
  <description>&lt;p&gt;Когда-то в прошлой жизни я сидел на Windows. Там был FAR. FAR был инструментом для всего.&lt;/p&gt;

&lt;p&gt;Потом я пересел на X11/GNU/Linux. Там FAR’а нет. Есть отдельно Midnight Commander, у которого убогий редактор, и отдельно Emacs, у которого убогий файловый менеджер. Об Emacs’е я здесь и сейчас говорить не буду. Буду говорить о классе программ, позиционирующихся как файловые менеджеры. Говорить буду резко и в основном для себя и про себя. Всем остальным читателям к каждому высказыванию неявно добавлять «IMHO».&lt;/p&gt;

&lt;p&gt;Итак, что такое файловый менеджер? Многие считают, что файловый менеджер — это две синие панельки, между которыми можно копировать файлы. Ну и изредка запускать команды шелла. А вот и ни фига.&lt;/p&gt;

&lt;p&gt;Функция запуска команд шелла первична. Первое, что должно быть в файловом менеджере — это командная строка и буфер с результатами выполнения команд. Панели вторичны и нужны для удобного выбора файловых аргументов к этим командам и для естественного порядка ввода команд (сначала — что и куда (или с чем), потом уже — что делать). Панели можно прятать (&lt;kbd&gt;Ctrl+O&lt;/kbd&gt;). Командную строку прятать нельзя.&lt;/p&gt;

&lt;p&gt;Как это решается в &lt;code&gt;mc&lt;/code&gt;? У терминала есть два буфера. Один — бесконечная лента с прокруткой. Другой — размером с окно, экран для приложений. Панели отображаются в этом самом альтернативном буфере. &lt;kbd&gt;Ctrl+O&lt;/kbd&gt; переключает между этими двумя буферами. За панелями работает настоящий живой шелл (в подпроцессе, связанном с псевдотерминалом, создаваемым Midnight Commander’ом, чтобы последний мог посылать в него команды помимо пользователя). Под панелями отображается имитация. Если пользователь набирает в неё команду и жмёт &lt;kbd&gt;Enter&lt;/kbd&gt;, &lt;code&gt;mc&lt;/code&gt; прячет панели и посылает введённую команду в шелл. Если пользователь гуляет по каталогам, &lt;code&gt;mc&lt;/code&gt; посылает в шелл команду &lt;code&gt;cd куда/теперь/перейти&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Чем плоха имитация комадной строки, и почему в FAR’е это было незаметно?&lt;/p&gt;

&lt;p&gt;В Windows у нас есть один командный процессор, &lt;code&gt;cmd.exe&lt;/code&gt;, с довольно скудными средствами редактирования командной строки, историей и рудиментарным tab completion’ом. В GNU/Linux у нас есть десять тысяч шеллов, и каждый со своими особенностями. И tab completion у них очень развитый.&lt;/p&gt;

&lt;p&gt;Соответственно, пользователь, пересевший с голого &lt;code&gt;cmd&lt;/code&gt; на FAR, не испытывает никаких неудобств. Ну может, разве что, придётся переучиться историю листать не стрелками вверх/вниз, а &lt;kbd&gt;Ctrl+E&lt;/kbd&gt;/&lt;kbd&gt;Ctrl+X&lt;/kbd&gt;. Пересесть с &lt;code&gt;bash&lt;/code&gt;’а на &lt;code&gt;mc&lt;/code&gt; невозможно, потому что сразу теряешь почти весь completion. В командной строке под панелями работает только дополнение имён файлов. В шелле за панелями работает всё. Содержимое командной строки &lt;code&gt;mc&lt;/code&gt; никак не связано с командной строкой шелла, пока не нажмёшь &lt;kbd&gt;Enter&lt;/kbd&gt;. Поэтому, когда ты написал &lt;code&gt;git checkout&lt;/code&gt; и хочешь вспомнить, как называется нужный тебе бранч, у тебя есть выбор: либо спрятать панели, выполнить за ними &lt;code&gt;git branch&lt;/code&gt;, запомнить нужное имя, вернуть панели, ввести имя ветки; либо выругаться, стереть всё, спрятать панели, набрать &lt;code&gt;git checkout&lt;/code&gt; и воспользоваться completion’ом.&lt;/p&gt;

&lt;p&gt;А что нужно, чтобы иметь полноценный completion в панелях?&lt;/p&gt;

&lt;p&gt;Долго думать не нужно, чтобы понять, что имитация командной строки не катит. В ней, в принципе, можно было бы с большими трудозатратами эмулировать, скажем, bash completion. Даже с его API расширения. Но если у пользователя основной шелл — &lt;code&gt;zsh&lt;/code&gt;, то он будет страдать. Нет, нам нужен под панелями настоящий шелл. Причём, в идеале, тот же самый, который и за панелями. Чтобы при включении/отключении панелей у нас сохранялось содержимое командной строки.&lt;/p&gt;

&lt;p&gt;Ни один файловый менеджер под GNU/Linux, если верить некоторым участникам linux.org.ru, так не делает. Потому что сложно. Это ж надо на лету менять размер псевдотерминала и при включённых панелях рулить отображением. Поди ещё и всю функциональность эмулятора терминала придётся самому поддерживать. Да ну нафиг, тут придётся половину &lt;code&gt;tmux&lt;/code&gt;’а в проект принести.&lt;/p&gt;

&lt;p&gt;А что если мы… принесём в проект &lt;em&gt;весь&lt;/em&gt; &lt;code&gt;tmux&lt;/code&gt; как чёрный ящик?&lt;/p&gt;

&lt;p&gt;Пруф-оф-концепт:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;На старте запускаем &lt;code&gt;tmux&lt;/code&gt; с отдельным (от пользовательского) конфигом, на отдельном управляюшем сокете, с новой сессией.&lt;/li&gt;
&lt;li&gt;Делим первое и пока единственное окно на две части (они будут называться %0 и %1). Нижнюю (%1) стягиваем до минимума и пускаем в ней шелл.&lt;/li&gt;
&lt;li&gt;В %0 пускаем панели.&lt;/li&gt;
&lt;li&gt;Панель с шеллом держим почти всегда активной (чтоб в ней был курсор). В нашем конфиге &lt;code&gt;tmux&lt;/code&gt;’а биндим клавиши, которые будут обрабатываться панелями, чтоб они перехватывались и отправлялись в панели.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Теперь можно остановиться и посмотреть, что же мы получили.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Зная истинное имя сокета сессии, мы можем повелевать всеми её окнами и панелями.&lt;/li&gt;
&lt;li&gt;Например, мы можем слать в шелл нажатия клавиш и текстовые строки: при гулянии по каталогам выполняем &lt;code&gt;tmux -L $имя_сокета send-keys -t %1 C-u &apos; cd /usr/share&apos; Enter C-l C-y&lt;/code&gt; (&lt;kbd&gt;C-u&lt;/kbd&gt; для сохранения командной строки и &lt;kbd&gt;C-y&lt;/kbd&gt; для восстановления — bash- и user-specific, но можно сделать настраиваемым).&lt;/li&gt;
&lt;li&gt;Также у нас есть многоэкранный и многопанельный движок. Мы можем легко по &lt;kbd&gt;F3&lt;/kbd&gt; открывать внешний вьюер в новом экране, по &lt;kbd&gt;F4&lt;/kbd&gt; — внешний редактор в новом экране. А это значит, что реализовывать-то надо только собственно панели, ну и, может быть, какие-нибудь внутренние команды для удобной работы с файлами.&lt;/li&gt;
&lt;li&gt;По &lt;kbd&gt;Ctrl+O&lt;/kbd&gt; просто зумим или раззумливаем панель с шеллом.&lt;/li&gt;
&lt;/ul&gt;&lt;a name=&apos;cutid1-end&apos;&gt;&lt;/a&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/63673.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/63673.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/64460.html?view=comments#comments</comments>
  <category>soft</category>
  <category>far manager</category>
  <category>tmux</category>
  <category>usability</category>
  <category>mc</category>
  <lj:security>public</lj:security>
  <lj:reply-count>8</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/64226.html</guid>
  <pubDate>Mon, 28 Dec 2015 10:53:14 GMT</pubDate>
  <title>Напишите мне email</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/64226.html</link>
  <description>&lt;p&gt;Повадились тут интернет-провайдеры звонить мне в телефон.&lt;/p&gt;

&lt;p&gt;Интернет-провайдеры, Карл, в телефон!&lt;/p&gt;

&lt;p&gt;Я допускаю, что мой интернет-провайдер может позвонить мне в телефон в трёх случаях:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Моё оборудование, подключённое к сети провайдера, своим действием или бездействием наносит ущерб ему или другим пользователям.&lt;/li&gt;
&lt;li&gt;Другие пользователи наносят ущерб моему оборудованию.&lt;/li&gt;
&lt;li&gt;Я заранее договорился с провайдером о каких-либо работах, где требуется моё присутствие.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;По всем остальным вопросам, уважаемые интернет-провайдеры, пишите мне на email. В том числе с предложениями перейти на более выгодный мне, вам или нам обоим тарифный план. Я визуал и для принятия решения мне нужно видеть глазами имеющиеся и предлагаемые условия. Не говоря уже о том, что как моя работа, так и мои хобби требуют концентрации, а ваши звонки её разрушают.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://imgprx.livejournal.net/3bcccfc0ae28491ebb3a34838f185dc5b0fc1e3880aafa9c04175cafc9918079/P2WlxyVijxKvg25v9cdSUkMdsf-ah7h03EGGXrBcgd7W6lbXmszqC0UoFEJ5CgJ4u0NSmS6RMVMUTh0jngx06E4WtG7ALdaS5VVFqBVvPi3lHfecpNNbmXlvvy1ic2Qe4kmx-2ZXE8t_BT5NcgCVuBIy:btSc9m2HdsPmDQPOauA9Dg&quot; fetchpriority=&quot;high&quot;&gt;&lt;/p&gt;&lt;a name=&apos;cutid1-end&apos;&gt;&lt;/a&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/63257.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/63257.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/64226.html?view=comments#comments</comments>
  <category>mts</category>
  <category>dom.ru</category>
  <category>mail</category>
  <category>phone</category>
  <category>isp</category>
  <category>cn.ru</category>
  <category>life</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
  </item>
  <item>
  <guid isPermaLink='true'>https://yurikhan.livejournal.com/63827.html</guid>
  <pubDate>Tue, 01 Dec 2015 09:37:24 GMT</pubDate>
  <title>О пользе объектно-ориентированных UI</title>
  <author>yurikhan</author>
  <link>https://yurikhan.livejournal.com/63827.html</link>
  <description>&lt;p&gt;Или о бесявости отсутствия таковых.&lt;/p&gt;

&lt;dl&gt;

&lt;dt&gt;&lt;p&gt;&lt;strong&gt;Альфа-Клик&lt;/strong&gt;, интернет-банк Альфа-Банка. Чтобы сделать перевод между счетами, приходится (1) навестись на «Переводы» в строке меню, (2) в попап-меню ткнуть в «Между своими счетами», выбрать в выпадающих списках сначала (3) счёт Откуда, потом (4) счёт Куда, потом (5) ввести сумму. Именно в этом порядке, потому что преждевременная валидация ввода.&lt;/p&gt;&lt;/dt&gt;

&lt;dd&gt;&lt;p&gt;Как должно быть: В списке счетов вижу название и текущий остаток. (1а) Дрэг-эн-дроп из текущего остатка на другой счёт открывает форму перевода, заранее заполненную исходным и целевым счетами, остаётся только (2а) ввести сумму. (1б) Клик в название открывает выписку. На экране выписки тоже должна быть (2б) кнопка «Перевести отсюда», открывающая ту же форму с предзаполненным исходным счётом, остаётся (3б) выбрать целевой счёт и (4б) ввести сумму. Если переводим не между своими счетами, то сценарий (б) тот же самый, только в (3б) указываем счёт получателя не выбором из списка своих счетов, а каким-то другим способом (выбор из закладок или, на худой конец, заполнение формы с опциональным созданием закладки).&lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;&lt;p&gt;&lt;strong&gt;Zabbix&lt;/strong&gt;, система мониторинга с веб-мордой. Вижу график трафика по семи серверам. Хочу добавить к нему недавно развёрнутый восьмой. Для этого приходится: (1) в строке меню навестись на Configure; (2) вспомнить, определён ли график для какого-то Хоста или в каком-то Шаблоне; (3) ткнуть соответственно в Hosts или Templates; (4) найти нужный хост или шаблон в двухстраничной таблице; (5) ткнуть в ссылку Graphs в его строке; (6) в открывшемся списке графиков этого хоста ткнуть в нужный график.&lt;/p&gt;&lt;/dt&gt;

&lt;dd&gt;&lt;p&gt;Как должно быть: На странице с графиком должна быть кнопка «Конфигурировать это».&lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;&lt;p&gt;&lt;strong&gt;Outlook Web Access&lt;/strong&gt;, веб-морда к корпоративной почте. Чтобы подписаться на рассылку, приходится: (1) в меню опций ткнуть в Options; (2) ткнуть в Groups; (3) нажать кнопку Join; (4) в открывшемся диалоге ткнуть в нужную группу; (5) в окне информации о группе нажать кнопку Join.&lt;/p&gt;&lt;/dt&gt;

&lt;dd&gt;&lt;p&gt;Как должно быть: (1) На вкладке People или на главной можно поиском найти нужную группу. (2) В панели информации о группе должна быть кнопка «Вступить в это».&lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;&lt;p&gt;&lt;strong&gt;Gajim&lt;/strong&gt;, jabber-клиент. Чтобы добавить контакт, нужно: (1) выбрать в меню Actions | Add contact | (нужный jabber-аккаунт); (2) в диалоге ввести JID; (3) в выпадающем списке выбрать группу.&lt;/p&gt;&lt;/dt&gt;

&lt;dd&gt;&lt;p&gt;Как должно быть: Ростер уже сгруппирован сначала по аккаунтам, потом по группам. (1) В контекстном меню группы должен быть пункт «Добавить сюда». Остаётся (2) в диалоге ввести JID.&lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;&lt;p&gt;&lt;strong&gt;Magit&lt;/strong&gt;, git-фронтэнд для Emacs’а. Чтобы создать новую ветку от текущего коммита, нужно: (1) нажать &lt;kbd&gt;b B&lt;/kbd&gt; (&lt;code&gt;magit-branch-and-checkout&lt;/code&gt;); (2) ввести хэш или имя ветки начального коммита или согласиться на предлагаемый по умолчанию; (3) ввести имя новой ветки.&lt;/p&gt;&lt;/dt&gt;

&lt;dd&gt;&lt;p&gt;Как должно быть: (1) В графе коммитов навести курсор на нужный коммит; (2) дать команду «создать ветку отсюда»; (3) ввести имя новой ветки.&lt;/p&gt;&lt;/dd&gt;

&lt;dt&gt;&lt;p&gt;&lt;strong&gt;Jenkins&lt;/strong&gt;, инструмент для continuous integration. Чтобы склонировать задачу, нужно (1) ткнуть New Item, (2) выбрать радиокнопку Copy existing item, (3) выбрать клонируемую задачу из комбо-списка.&lt;/p&gt;&lt;/dt&gt;

&lt;dd&gt;&lt;p&gt;Как должно быть: В контекстном меню задачи должен быть пункт «Склонировать это».&lt;/p&gt;&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;&lt;strong&gt;Правило:&lt;/strong&gt; Пользователь, видящий в интерфейсе объект, должен мочь непосредственно с него отдавать команды, принимающие этот объект в качестве любого параметра.&lt;/p&gt;

&lt;p&gt;Положительные примеры: на картах в карточке здания «Проехать сюда» и «Проехать отсюда». В почтовиках «Filter messages like this».&lt;/p&gt;

&lt;span style=&quot;font-size: smaller;&quot;&gt;This entry was originally posted at &lt;a href=&quot;http://yurikhan.dreamwidth.org/63091.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://yurikhan.dreamwidth.org/63091.html&lt;/a&gt;.&lt;/span&gt;</description>
  <comments>https://yurikhan.livejournal.com/63827.html?view=comments#comments</comments>
  <category>gajim</category>
  <category>monitoring</category>
  <category>usability</category>
  <category>magit</category>
  <category>mail</category>
  <category>banking</category>
  <category>jenkins</category>
  <category>git</category>
  <category>zabbix</category>
  <category>owa</category>
  <category>jabber</category>
  <category>alfaclick</category>
  <lj:security>public</lj:security>
  <lj:reply-count>6</lj:reply-count>
  </item>
</channel>
</rss>
