← All posts tagged unix-way

Kim
unix-way Путь юникс, то есть рекомендации по проектированию систем от Кернигана и Пайка, а не Великое Учение По Постороению Безупречных Систем, имеет ряд общеизвестных проблем. Самая банальная из них заключается в том, что UNIX-way не признает существования сложных задач. Согласно советам по дизайну программ [ werc.homelinux.net ] каждую сложную задачу можно разделить на несколько простых и решать их по отдельности. К сожалению это не так. Простые задачи покрывают сложную не полностью, и всё равно требуются тысячи строк кода при отходе от стандартного шаблона использования. В качестве иллюстрации напишу про ситуацию с текстовыми потоками:

Если мы хотим соединить две программы в одну, то всё здорово:
$ cat a b c | gzip -c >data.gz
Если мы хотим при этом параллельно делать ещё какую-то вещь с выводом первой команды, то мы можем написать
$ cat a b c | tee >(gzip -c >data.gz) | grep WARNING
либо
$ cat a b c >/tmp/temp.data ; gzip -c /tmp/temp.data >data.gz & grep WARNING /tmp/temp.data ; wait $! ; rm /tmp/temp.data
несмотря на то что задача фактически не изменилась нам потребовалось, в первом варианте, переписать шелл добавив в него конструкцию >(shell command), кроме того потребовалась реализация программы tee, которая имеет один вход и много выходов. Второй вариант ещё более ужасен: потребовалось создание временного файла который занимает место на диске, потребовалась реализация асинхронного вызова и примитива wait, потребовался код для удаления временного файла. Скажу сразу: первый вариант больше соответствует идеям указанной выше статьи по дизайну програм. Казалось бы это уже конец. Но нам может захотеться вставить разную обработку перед вводом. Тогда придётся писать:
$ cat a <(grep USEFULL b) c | gzip -c >data.gz
либо
$ mkfifo /tmp/b.fifo ; grep USEFULL b >/tmp/b.fifo & cat a /tmp/b.fifo c | gzip -c >data.gz ; rm /tmp/b.fifo
что снова требует добавления ряда конструкций.

В bash указанные задачи решены добавлением тех самых >(...) и <(...), но легко придумать задачи где этих методов соединения текстовых потоков недостаточно и придётся создавать всё более страшные конструкции (скорее всего похожие на вторые варианты решений указанные выше) до тех пор, пока вся система не рухнет под своим весом. С другой стороны если сразу решать задачу как сложную и реализовать систему для произвольного соединения текстовых потоков, то в сумме решение получится проще, компактнее и полнее чем объединение "маленьких утилит решающих свои задачи".