<?xml version='1.0' encoding='utf-8' ?>

<rss version='2.0' xmlns:lj='http://www.livejournal.org/rss/lj/1.0/' xmlns:atom10='http://www.w3.org/2005/Atom'>
<channel>
  <title>Блокнотик Centaur’а</title>
  <link>https://yurikhan.dreamwidth.org/</link>
  <description>Блокнотик Centaur’а - Dreamwidth Studios</description>
  <lastBuildDate>Mon, 27 Aug 2018 16:11:47 GMT</lastBuildDate>
  <generator>LiveJournal / Dreamwidth Studios</generator>
  <lj:journal>yurikhan</lj:journal>
  <lj:journaltype>personal</lj:journaltype>
  <image>
    <url>https://v2.dreamwidth.org/15796844/1181104</url>
    <title>Блокнотик Centaur’а</title>
    <link>https://yurikhan.dreamwidth.org/</link>
    <width>100</width>
    <height>100</height>
  </image>

<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/70926.html</guid>
  <pubDate>Mon, 27 Aug 2018 16:11:47 GMT</pubDate>
  <title>Ремонтно-методологическое</title>
  <link>https://yurikhan.dreamwidth.org/70926.html</link>
  <description>&lt;p&gt;Когда ремонтнику, приглашённому на три дня доделать остаток ремонта, показываешь все его задачи бумажками, развешенными на канбан-доске «Очередь | В работе | Сделано», собранной из двух попавшихся под руку коробок, он сначала обнаруживает, что его представления об объёме работ были сильно занижены, а сразу за этим порывается сделать как можно больше мелких задачек. (Но по здравом размышлении берёт толстую задачищу на полдня.)&lt;/p&gt;

&lt;p&gt;А вечером, уже собираясь уходить и переодеваясь в штатское, заглядывает на доску — и доделывает мелкую задачку из «В работе».&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=70926&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/70926.html</comments>
  <category>household</category>
  <category>kanban</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/70831.html</guid>
  <pubDate>Thu, 28 Sep 2017 13:13:18 GMT</pubDate>
  <title>Подсветка синтаксиса высших порядков</title>
  <link>https://yurikhan.dreamwidth.org/70831.html</link>
  <description>&lt;p&gt;В старые добрые времена, когда людям нужно было выразить что-нибудь в компьютерном файле, они изобретали новый синтаксис. Потом в чью-то умную голову пришла мысль подсвечивать элементы синтаксиса в текстовых редакторах.&lt;/p&gt;

&lt;p&gt;Потом люди придумали универсальные языки разметки — XML, JSON и YAML — с помощью которых можно выразить всё что угодно. Поэтому теперь вместо синтаксиса часто изобретают схему.&lt;/p&gt;

&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;p&gt;Однако, что у нас с их подсветкой? Возьмём, к примеру, кусочек мета-схемы JSON Schema Draft 04 (который примечателен тем, что описывает свою собственную структуру):&lt;/p&gt;

&lt;pre style=&quot;background-color: white; color: black&quot;&gt;&lt;code&gt;{ &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;$schema&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;http://json-schema.org/draft-04/schema#&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;object&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;properties&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;$schema&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;string&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;format&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;url&quot;&lt;/span&gt;},
    &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;string&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;format&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;url&quot;&lt;/span&gt;},
    &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;type&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;tsring&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;enum&quot;&lt;/span&gt;: [
      &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;null&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;boolean&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;integer&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;number&quot;&lt;/span&gt;,
      &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;string&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;array&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;object&quot;&lt;/span&gt;]},
    &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;format&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;string&quot;&lt;/span&gt;},
    &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;properties&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;object&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;aditionalProperties&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;#&quot;&lt;/span&gt;}},
    &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;additionalProperties&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;#&quot;&lt;/span&gt;},
    &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;enum&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;array&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;items&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;#&quot;&lt;/span&gt;}},
    &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;items&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;#&quot;&lt;/span&gt;}
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Одни сплошные «строковые литералы». В лучшем случае — ключи объектов одним цветом, остальные строки другим. На первом плане — синтаксис самого JSON; а более высокоуровневый синтаксис, построенный поверх JSON’а, остаётся нераскрашенным и непроверяемым на глаз. Найдите две опечатки в примере выше.&lt;/p&gt;

&lt;p&gt;Надо — имея на руках схему, валидировать об неё документ и подсвечивать по-разному:&lt;/p&gt;

&lt;ul style=&quot;background-color: white&quot;&gt;
&lt;li style=&quot;color: #5c3566&quot;&gt;ключи, явно допустимые в текущем контексте;&lt;/li&gt;
&lt;li style=&quot;color: #204a87&quot;&gt;ключи, допустимые по шаблону или по принципу «всё, что не запрещено»;&lt;/li&gt;
&lt;li style=&quot;color: #a40000&quot;&gt;ключи, недопустимые в текущем контексте, и примитивные значения, не соответствующие схеме;&lt;/li&gt;
&lt;li style=&quot;color: #8f5902&quot;&gt;значения, явно соответствующие заданным ограничениям;&lt;/li&gt;
&lt;li style=&quot;color: #4e9a06&quot;&gt;все остальные строки.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre style=&quot;background-color: white; color: black&quot;&gt;&lt;code&gt;{ &lt;span style=&quot;color: #5c3566&quot;&gt;&quot;$schema&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;http://json-schema.org/draft-04/schema#&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #5c3566&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #8f5902&quot;&gt;&quot;object&quot;&lt;/span&gt;,
  &lt;span style=&quot;color: #5c3566&quot;&gt;&quot;properties&quot;&lt;/span&gt;: {
    &lt;span style=&quot;color: #204a87&quot;&gt;&quot;$schema&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #8f5902&quot;&gt;&quot;string&quot;&lt;/span&gt;, &lt;span style=&quot;color: #5c3566&quot;&gt;&quot;format&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;url&quot;&lt;/span&gt;},
    &lt;span style=&quot;color: #204a87&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #8f5902&quot;&gt;&quot;string&quot;&lt;/span&gt;, &lt;span style=&quot;color: #5c3566&quot;&gt;&quot;format&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;url&quot;&lt;/span&gt;},
    &lt;span style=&quot;color: #204a87&quot;&gt;&quot;type&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #a40000&quot;&gt;&quot;tsring&quot;&lt;/span&gt;, &lt;span style=&quot;color: #5c3566&quot;&gt;&quot;enum&quot;&lt;/span&gt;: [
      &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;null&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;boolean&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;integer&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;number&quot;&lt;/span&gt;,
      &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;string&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;array&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;object&quot;&lt;/span&gt;]},
    &lt;span style=&quot;color: #204a87&quot;&gt;&quot;format&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #8f5902&quot;&gt;&quot;string&quot;&lt;/span&gt;},
    &lt;span style=&quot;color: #204a87&quot;&gt;&quot;properties&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #8f5902&quot;&gt;&quot;object&quot;&lt;/span&gt;, &lt;span style=&quot;color: #204a87&quot;&gt;&quot;aditionalProperties&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;#&quot;&lt;/span&gt;}},
    &lt;span style=&quot;color: #204a87&quot;&gt;&quot;additionalProperties&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;#&quot;&lt;/span&gt;},
    &lt;span style=&quot;color: #204a87&quot;&gt;&quot;enum&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;type&quot;&lt;/span&gt;: &lt;span style=&quot;color: #8f5902&quot;&gt;&quot;array&quot;&lt;/span&gt;, &lt;span style=&quot;color: #5c3566&quot;&gt;&quot;items&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;#&quot;&lt;/span&gt;}},
    &lt;span style=&quot;color: #204a87&quot;&gt;&quot;items&quot;&lt;/span&gt;: {&lt;span style=&quot;color: #5c3566&quot;&gt;&quot;$ref&quot;&lt;/span&gt;: &lt;span style=&quot;color: #4e9a06&quot;&gt;&quot;#&quot;&lt;/span&gt;}
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=70831&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/70831.html</comments>
  <category>json</category>
  <category>syntax</category>
  <category>xml</category>
  <category>usability</category>
  <category>yaml</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/70494.html</guid>
  <pubDate>Tue, 13 Jun 2017 11:34:09 GMT</pubDate>
  <title>Посоветуйте инструмент код-ревью</title>
  <link>https://yurikhan.dreamwidth.org/70494.html</link>
  <description>&lt;p&gt;Какие есть хорошие инструменты для ревью кода?&lt;/p&gt;

&lt;p&gt;Критерии хорошести, в нулевом приближении, следующие:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Установка on-premise.&lt;/li&gt;
&lt;li&gt;Одно ревью может включать несколько коммитов из разных (но заранее известных) Git-репозиториев. Коммиты каждого репозитория линейно упорядочены. Для каждого файла в ревью ревьюер может смотреть дифф любого подинтервала по своему выбору. (Как в Crucible, если бы он порядок брал из графа, а не выводил из временных меток.)&lt;/li&gt;
&lt;li&gt;Коммент, не являющийся ответом на другой коммент, привязывается к произвольному, в общем случае не непрерывному, подмножеству строк файла. (Как в Crucible.)&lt;/li&gt;
&lt;li&gt;Работает подсветка синтаксиса как минимум для C++, Python’а, Go, шелла, XML, JSON и YAML. Распознавание того, какой синтаксис применять к файлу, работает более умно, чем просто по расширению (в частности, &lt;code&gt;#!/usr/bin/python3&lt;/code&gt; или &lt;code&gt;#!/usr/bin/env python3&lt;/code&gt; для файлов без расширения однозначно указывают на Python).&lt;/li&gt;
&lt;li&gt;Невозможна ситуация, когда отображается строка файла N (типично документационный комментарий) с комментом к ней и при этом существует и не отображается строка N+1 (типично заголовок или прототип функции с аргументами). (То есть не как в GitLab’е.)&lt;/li&gt;
&lt;li&gt;Работает скроллинг средней кнопкой в Firefox’е. (А не как в Crucible — &lt;code&gt;{overflow-y: hidden; overflow-x: auto}&lt;/code&gt; и привет, средней кнопкой скроллится только в стороны.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Большая зелёная кнопка «вмёржить это в master прямо сейчас не думая» категорически нафиг не нужна.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=70494&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/70494.html</comments>
  <category>code review</category>
  <category>soft</category>
  <category>usability</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/70276.html</guid>
  <pubDate>Mon, 22 May 2017 14:30:02 GMT</pubDate>
  <title>Бритва Постела наоборот</title>
  <link>https://yurikhan.dreamwidth.org/70276.html</link>
  <description>&lt;p&gt;Бритва Постела наоборот:&lt;/p&gt;

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

&lt;p&gt;Софт, который в этих условиях выживет, — будет супернадёжен и при этом корректен.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=70276&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/70276.html</comments>
  <category>soft</category>
  <category>razor</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/70136.html</guid>
  <pubDate>Mon, 15 May 2017 17:18:23 GMT</pubDate>
  <title>[git] Записать submodule в .gitmodules</title>
  <link>https://yurikhan.dreamwidth.org/70136.html</link>
  <description>&lt;p&gt;Заметка для себя, чтоб не потерять.&lt;/p&gt;

&lt;p&gt;Типичная задача: добавить сабмодуль в git-репозиторий.&lt;/p&gt;

&lt;p&gt;Решение человека, только что читавшего мануал: &lt;samp&gt;$ &lt;kbd&gt;git submodule add git@host:path/repo.git&lt;/kbd&gt;&lt;/samp&gt;. Клонирует удалённый репозиторий в подкаталог текущего, регистрирует его в .gitmodules и .git/config.&lt;/p&gt;

&lt;p&gt;Как обычно получается у меня: &lt;samp&gt;$ &lt;kbd&gt;git clone git@host:path/repo.git&lt;/kbd&gt;&lt;/samp&gt;. Клонирует удалённый репозиторий в подкаталог текущего и больше ничего не делает. Обнаруживается это где-то ближе к тому моменту, когда добавление сабмодуля нужно закоммитить.&lt;/p&gt;

&lt;p&gt;Соответственно, задача: На входе есть суперпроект (в терминах &lt;cite&gt;git-submodule(1)&lt;/cite&gt;) и внутри него локальная копия репозитория, который нужно сделать сабмодулем. Считаем, что текущий каталог находится внутри суперпроекта, а корень будущего сабмодуля является непосредственным подкаталогом текущего. Решение методом выливания воды из чайника заранее отметаем как неизящное.&lt;/p&gt;

&lt;p&gt;Из инструментов у нас есть &lt;code&gt;git submodule add [-b &amp;lt;branch&amp;gt;] &amp;lt;repository&amp;gt; &amp;lt;path&amp;gt;&lt;/code&gt;. Ветку указывать нужно в редких случаях и можно руками. Путь легко вводится по &lt;kbd&gt;M-RET&lt;/kbd&gt; в Midnight Commander’е. А вот URL репозитория хочется достать и подставить автоматически.&lt;/p&gt;

&lt;p&gt;Достать путь можно так: &lt;samp&gt;$ &lt;kbd&gt;git -C &amp;lt;submodule&amp;gt; config --get remote.origin.url&lt;/kbd&gt;&lt;/samp&gt;.&lt;/p&gt;

&lt;p&gt;Однако писать &lt;samp&gt;$ &lt;kbd&gt;git submodule add $(&amp;lt;строчка выше&amp;gt;)&lt;/kbd&gt;&lt;/samp&gt; каждый раз утомительно, поэтому добавляем алиас:&lt;/p&gt;

&lt;pre style=&quot;border: 1px solid gray; max-width: 100%; overflow-x: scroll&quot;&gt;&lt;samp&gt;$ &lt;kbd&gt;git config --global --edit&lt;/kbd&gt;

&lt;code&gt;[alias]
    subinit = !sh -c &apos;sub=&quot;$1&quot; &amp;amp;&amp;amp; shift &amp;amp;&amp;amp; git submodule add &quot;$@&quot; $(git -C &quot;$sub&quot; config --get remote.origin.url)&apos; -&lt;/code&gt;

&lt;samp&gt;$ &lt;kbd&gt;git subinit repo&lt;/kbd&gt;
Adding existing repo at &apos;repo&apos; to the index

$ &lt;kbd&gt;git subinit repo2 -b master&lt;/kbd&gt;
Adding existing repo at &apos;repo&apos; to the index&lt;/samp&gt;&lt;/samp&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=70136&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/70136.html</comments>
  <category>git</category>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/69884.html</guid>
  <pubDate>Thu, 11 May 2017 06:22:43 GMT</pubDate>
  <title>О википедиях</title>
  <link>https://yurikhan.dreamwidth.org/69884.html</link>
  <description>&lt;p&gt;Мало кто знает, что &lt;i&gt;Википедия&lt;/i&gt; — это форма множественного числа. Вместе — википедия, а каждое в отдельности — википедие.&lt;/p&gt;

&lt;p&gt;It is a little-known fact that &lt;i&gt;Wikipedia&lt;/i&gt; is a plural noun. Collectively they are wikipedia; each one separately is a wikipedium.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=69884&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/69884.html</comments>
  <category>puns</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/69430.html</guid>
  <pubDate>Thu, 04 May 2017 08:17:27 GMT</pubDate>
  <title>[Web] Подсветка при наведении</title>
  <link>https://yurikhan.dreamwidth.org/69430.html</link>
  <description>&lt;p&gt;Если при наведении мышью в какую-то точку кнопки или пункта меню ты эту кнопку или пункт подсветил или поменял курсор мыши на «палец» — ты обязан реагировать на клик в этой конкретной точке.&lt;/p&gt;

&lt;p&gt;Типичная схема нарушения: на клики реагирует ссылка с текстом, а подсветка по :hover’у и вообще всё оформление кнопки висит на контейнере-обёртке с margin’ом в пол-эма. Попадаешь в margin — подсветка есть, реакции на клик нет.&lt;/p&gt;

&lt;p&gt;Лучи поноса в общем направлении Tiny Tiny RSS и Atlassian Crucible.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=69430&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/69430.html</comments>
  <category>web</category>
  <category>usability</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/69129.html</guid>
  <pubDate>Wed, 18 Jan 2017 09:21:22 GMT</pubDate>
  <title>Типы данных для идентификаторов</title>
  <link>https://yurikhan.dreamwidth.org/69129.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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=69129&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/69129.html</comments>
  <category>work</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/68971.html</guid>
  <pubDate>Wed, 28 Dec 2016 06:49:37 GMT</pubDate>
  <title>Новогоднее</title>
  <link>https://yurikhan.dreamwidth.org/68971.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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=68971&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/68971.html</comments>
  <category>центон</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/68819.html</guid>
  <pubDate>Fri, 02 Dec 2016 16:48:08 GMT</pubDate>
  <title>Purple Tentacle keyboard</title>
  <link>https://yurikhan.dreamwidth.org/68819.html</link>
  <description>&lt;p&gt;Окей, оно готово. За этот отпуск я сделал себе клавиатуру.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;max-width: 100%&quot; src=&quot;http://yurikhan.github.io/images/20161118-keyboard/complete.jpg&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;&gt;тут&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Со временем выложу все исходники как open source hardware.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=68819&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/68819.html</comments>
  <category>keyboards</category>
  <category>purple tentacle</category>
  <lj:security>public</lj:security>
  <lj:reply-count>7</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/68604.html</guid>
  <pubDate>Thu, 17 Nov 2016 18:31:42 GMT</pubDate>
  <title>Тизер</title>
  <link>https://yurikhan.dreamwidth.org/68604.html</link>
  <description>&lt;p&gt;Тестируем ранний прототип.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://yurikhan.github.io/images/20161118-keyboard/11-feline-test.jpg&quot; style=&quot;width: 100%&quot;&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=68604&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/68604.html</comments>
  <category>keyboards</category>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/68275.html</guid>
  <pubDate>Thu, 03 Nov 2016 08:57:18 GMT</pubDate>
  <title>Ещё об веб-иконки</title>
  <link>https://yurikhan.dreamwidth.org/68275.html</link>
  <description>&lt;p&gt;В предыдущих сериях: &lt;a href=&quot;http://yurikhan.livejournal.com/53638.html&quot;&gt;иконочные шрифты&lt;/a&gt;, &lt;a href=&quot;http://yurikhan.livejournal.com/65496.html&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;http://yurikhan.github.io/images/20161103-material-icons/google-material-icons.png&quot;&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=68275&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/68275.html</comments>
  <category>web</category>
  <category>idiots</category>
  <category>usability</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/68023.html</guid>
  <pubDate>Mon, 31 Oct 2016 16:23:28 GMT</pubDate>
  <title>Свой-чужой</title>
  <link>https://yurikhan.dreamwidth.org/68023.html</link>
  <description>&lt;p&gt;А вот довелось мне намедни написать емейлом некий запрос (пока не важно) в одну организацию. И сегодня я получил оттуда ответ. С ответом &lt;em&gt;ниже&lt;/em&gt; цитаты.&lt;/p&gt;

&lt;p&gt;Так приятно, чёрт возьми.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=68023&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/68023.html</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.dreamwidth.org/67829.html</guid>
  <pubDate>Thu, 20 Oct 2016 09:37:58 GMT</pubDate>
  <title>Вебдизигнеро-проклинательное</title>
  <link>https://yurikhan.dreamwidth.org/67829.html</link>
  <description>&lt;p&gt;У того человека, который придумал, что люди не любят читать чистый чёрный текст, пусть кофе всегда будет разбавлен два к одному.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=67829&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/67829.html</comments>
  <category>web</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/67566.html</guid>
  <pubDate>Tue, 11 Oct 2016 09:52:58 GMT</pubDate>
  <title>За что я не люблю YAML</title>
  <link>https://yurikhan.dreamwidth.org/67566.html</link>
  <description>&lt;p&gt;&lt;a href=&quot;http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf&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;&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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=67566&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/67566.html</comments>
  <category>soft</category>
  <category>yaml</category>
  <category>idiots</category>
  <category>ansible</category>
  <category>json</category>
  <lj:security>public</lj:security>
  <lj:reply-count>7</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/67135.html</guid>
  <pubDate>Sat, 24 Sep 2016 17:48:49 GMT</pubDate>
  <title>Юникодное</title>
  <link>https://yurikhan.dreamwidth.org/67135.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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=67135&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/67135.html</comments>
  <category>unicode</category>
  <category>idiots</category>
  <category>lj</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/66985.html</guid>
  <pubDate>Mon, 12 Sep 2016 08:27:19 GMT</pubDate>
  <title>Мой провайдер идиот</title>
  <link>https://yurikhan.dreamwidth.org/66985.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;a name=&quot;cutid1&quot;&gt;&lt;/a&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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=66985&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/66985.html</comments>
  <category>mts</category>
  <category>dom.ru</category>
  <category>networks</category>
  <category>cn.ru</category>
  <category>idiots</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/66683.html</guid>
  <pubDate>Fri, 02 Sep 2016 13:45:50 GMT</pubDate>
  <title>Логировать фронт, а не уровень</title>
  <link>https://yurikhan.dreamwidth.org/66683.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;a name=&quot;cutid1&quot;&gt;&lt;/a&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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=66683&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/66683.html</comments>
  <category>usability</category>
  <category>soft</category>
  <category>logging</category>
  <lj:security>public</lj:security>
  <lj:reply-count>2</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/66551.html</guid>
  <pubDate>Mon, 22 Aug 2016 11:01:24 GMT</pubDate>
  <title>CLI как язык</title>
  <link>https://yurikhan.dreamwidth.org/66551.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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=66551&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/66551.html</comments>
  <category>soft</category>
  <category>lxc</category>
  <category>usability</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.dreamwidth.org/66195.html</guid>
  <pubDate>Fri, 12 Aug 2016 17:20:02 GMT</pubDate>
  <title>[bpi] Диагностика загрузки сервера</title>
  <link>https://yurikhan.dreamwidth.org/66195.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;a name=&quot;cutid1&quot;&gt;&lt;/a&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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=66195&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/66195.html</comments>
  <category>hard</category>
  <category>bananapi</category>
  <lj:security>public</lj:security>
  <lj:reply-count>4</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/65925.html</guid>
  <pubDate>Mon, 08 Aug 2016 14:22:14 GMT</pubDate>
  <title>Омонимическое</title>
  <link>https://yurikhan.dreamwidth.org/65925.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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=65925&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/65925.html</comments>
  <category>git</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/65668.html</guid>
  <pubDate>Mon, 08 Aug 2016 10:46:55 GMT</pubDate>
  <title>Альтернативная этимология</title>
  <link>https://yurikhan.dreamwidth.org/65668.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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=65668&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/65668.html</comments>
  <category>puns</category>
  <lj:security>public</lj:security>
  <lj:reply-count>1</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/65344.html</guid>
  <pubDate>Tue, 05 Jul 2016 19:10:40 GMT</pubDate>
  <title>Язык для описания графов</title>
  <link>https://yurikhan.dreamwidth.org/65344.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;&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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=65344&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/65344.html</comments>
  <category>wishlist</category>
  <category>graphviz</category>
  <category>design</category>
  <lj:security>public</lj:security>
  <lj:reply-count>6</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/65105.html</guid>
  <pubDate>Sat, 02 Jul 2016 16:03:06 GMT</pubDate>
  <title>Альтернативная химия</title>
  <link>https://yurikhan.dreamwidth.org/65105.html</link>
  <description>&lt;p&gt;Где-то в параллельной вселенной магнаты и магниты — это соли магниевой и магнистой кислот, соответственно.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=65105&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/65105.html</comments>
  <category>puns</category>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
<item>
  <guid isPermaLink='true'>https://yurikhan.dreamwidth.org/64906.html</guid>
  <pubDate>Sun, 26 Jun 2016 15:35:35 GMT</pubDate>
  <title>Электрический свет продолжает наш день</title>
  <link>https://yurikhan.dreamwidth.org/64906.html</link>
  <description>&lt;p&gt;Берём таблицу &lt;a href=&quot;http://world-weather.ru/pogoda/russia/novosibirsk/sunrise/&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;br /&gt;&lt;br /&gt;&lt;img src=&quot;https://www.dreamwidth.org/tools/commentcount?user=yurikhan&amp;ditemid=64906&quot; width=&quot;30&quot; height=&quot;12&quot; alt=&quot;comment count unavailable&quot; style=&quot;vertical-align: middle;&quot;/&gt; comments</description>
  <comments>https://yurikhan.dreamwidth.org/64906.html</comments>
  <lj:security>public</lj:security>
  <lj:reply-count>0</lj:reply-count>
</item>
</channel>
</rss>
