Дима Дорошев

Посты из блога в категории Dev:

How wonderful it is that everyone's time intervals are measured in the same units and the phrase "in 15 minutes" is understood the same way throughout the civilized world.

There's no such thing as one person's minute lasting longer than another's. Or that in the USA instead of a second, they use some kind of "tick" that equals 1.672 seconds, and a day consists not of 24 hours, but of 4 "quarter-days".

If that were also the case, programmers would go insane. They already have enough to deal with leap seconds and time zones.

Как же хорошо, что у всех интервалы времени измеряются в одинаковых единицах и фразу "через 15 минут" понимают одинаково во всем цивилизованном мире.

Нет такого, что у одного минута длится дольше, чем у другого. Или что в США вместо секунды используют какой-нибудь "тик", который равен 1.672 секунды, и день состоит не из 24 часов, а из 4 "квартосуток".

Если бы еще и такое было, программисты бы вообще свихнулись. Им и так хватает високосных секунд и часовых поясов.

Go: Отложенная обработка событий файловой системы

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

Этот сайт написан на Go, и недавно я решил добавить в него подобный hot-reload для markdown-файлов с постами: кладешь новый файл в папку, веб-сервер это замечает и переналивает внутренний in-memory-storage с публикациями без перезапуска самого себя. При этом мне хотелось именно "слушать" файловую систему, а не сканировать ее раз в несколько секунд.

Читать далее

Абстракции и наследование в Си - стреляем по ногам красиво

TL;DR https://github.com/ddoroshev/c-inheritance

Иногда нет-нет да и хочется что-нибудь абстрагировать и обобщить в коде на Си. К примеру, хочешь ты принтануть содержимое структуры несколько раз, пишешь везде, как дурак, printf("%s %d %f\n", foo->bar, foo->baz, foo->boom), и интуитивно кажется, что есть способ сделать foo->print(foo), и так вообще со всеми структурами, не только с foo.

Возьмем пример: есть некий чувак с именем и фамилией, и есть птица, у которой есть имя и владелец.

typedef struct Person Person;
struct Person {
    char *first_name;
    char *last_name;
};

typedef struct Bird Bird;
struct Bird {
    char *name;
    Person *owner;
};

Чтобы вывести информацию про этих животных, кондовый сишник напишет просто две функции:

void Person_Print(Person *p) {
    printf("%s %s\n", p->first_name, p->last_name);
}

void Bird_Print(Bird *b) {
    printf("%s of %s %s\n", b->name, b->owner->first_name, b->owner->last_name);
}

И будет таки прав! Но что если подобных структур у нас много, а наш мозг испорчен веяниями ООП?

Читать далее

Docker Buildkit: Правильное использование --mount=type=cache

TL;DR Содержимое каталогов, смонтированных через --mount=type=cache, не сохраняется в docker-образе, поэтому кэшировать надо не целевые каталоги, а промежуточные.

В dockerfile:1.3 появилась возможность монтировать файловые системы во время построения образа, в том числе и в целях кэширования: можно кэшировать скачанные пакеты или промежуточные артефакты компиляции.

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

# syntax=docker/dockerfile:1.3
FROM python:3.10

RUN mkdir /pip-packages

RUN --mount=type=cache,target=/pip-packages \
      pip install --target=/pip-packages uwsgi
> docker build -t pip-cache -f Dockerfile.pip .
# ...
[+] Building 14.6s (7/7) FINISHED

Выглядит, что все прошло успешно, но целевой каталог пуст:

> docker run -it --rm pip-cache ls -l /pip-packages
total 0

Что-то явно пошло не так.

Читать далее

Быстрый коммит и пуш

Хочу поделиться shell-функцией gacp (Git Add, Commit and Push), которую я придумал несколько месяцев назад и с тех пор использую ее примерно каждый час:

# fish
function gacp
    git add .
    git commit -m "$argv"
    git push origin HEAD
end
# bash/zsh
function gacp() {
    git add .
    git commit -m "$*"
    git push origin HEAD
}

Пример использования:

> gacp add some new crazy stuff
[master fb8dcc9] add some new crazy stuff
 <...>
Enumerating objects: 12, done.
 <...>
To github.com:foo/bar.git
   912c95d..fb9dcc9  master -> master

Наконец-то больше не придется городить цепочки с && и вставлять кавычки, когда надо написать в сообщении больше одного слова!

B I U

In any text processor (Microsoft Word, Google Docs, LibreOffice), the "bold", "italic", and "underline" buttons are located next to each other:

For decades, the pattern has been established in our minds that these are properties of the same order. If you want to make bold and italic text, you press two buttons next to each other:

If you want bold and underlined text:

I won't talk about underlined italics - that's for special people.

In HTML tags, it's just as simple. There are three tags: b, i, and u. You can nest them inside each other to get the desired combination:

<b><i>bold italic</i></b>
<b><u>bold underlined</u></b>
<i><u>please don't</u></i>

But in CSS, these are completely different properties:

{
/* bold */
font-weight: bold;

/* italic */
font-style: italic;

/* underline */
text-decoration: underline;
}

I can somewhat understand font-weight, but I haven't been able to remember the rules for applying the other two properties for 13 years now. If I need to make underlined text and have no hints, I can simply try all the options until it works:

text-style: underline;
font-style: underline;
font-decoration: underline;
text-underline: true;

It's very annoying. I want it either like this:

font-style: bold;
font-style: bold, italic;
font-style: italic, underline;

Or like this:

font-bold: true;
font-underline: true;
font-italic: true;

That's all I need.

Ж К П

В любом текстовом процессоре (Microsoft Word, Google Docs, LibreOffice) кнопки "полужирный", "курсив" и "подчеркнутый" находятся рядом:

Десятилетиями в голове устаканивался паттерн о том, что это свойства одного порядка. Хочешь сделать полужирный курсив, нажимаешь две кнопки рядом:

Хочешь жирный и подчеркнутый:

Про подчеркнутый курсив не буду - это для особенных людей.

В HTML-тегах с этим тоже просто. Есть три тега: b, i и u. Можно вкладывать их друг в друга и получать желаемую комбинацию:

<b><i>полужирный курсив</i></b>
<b><u>полужирный подчеркнутый</u></b>
<i><u>пожалуйста, не надо</u></i>

А в CSS это совершенно разные свойства:

{
/* полужирный */
font-weight: bold;

/* курсив */
font-style: italic;

/* подчеркнутый */
text-decoration: underline;
}

Про font-weight еще более-менее понятно, но правила применения двух остальных свойств я уже 13 лет не могу запомнить. Если нужно сделать подчеркнутый текст, а подсказок взять негде, я могу просто перебрать все варианты, пока не заработает:

text-style: underline;
font-style: underline;
font-decoration: underline;
text-underline: true;

Очень бесит. Хочется либо так:

font-style: bold;
font-style: bold, italic;
font-style: italic, underline;

Либо так:

font-bold: true;
font-underline: true;
font-italic: true;

Большего мне и не надо.