The post has been translated automatically. Original language: Russian
Unix appeared before I was born. I got to know him much later — already in the late nineties, first from books, then on a real machine with SCO Unix, and then through Linux, the source code of the kernel, and my own experiments.
Many years have passed since then. I've worked with different languages, platforms, databases, networks, clouds, and now with artificial intelligence. But many of the Unix ideas still seem surprisingly correct to me.
At the same time, the system that I am building today is not at all like Unix.
And there is no contradiction in this.
Loving Unix does not mean copying Unix
When talking about the Unix philosophy, it's easy to reduce everything to a few external features: small programs, the command line, text files, and channels between processes.
These are really important parts of Unix, but they appeared in a specific era and solved specific tasks.
Computers were different. Memory was expensive. The user was working through a terminal. The main objects were processes and files. Most of the work was done by a programmer who understood the system well.
Just reproducing these forms today does not mean following the spirit of Unix.
I think it's more important to understand why these solutions appeared in the first place.
Unix teaches you how to deal with complexity
For me, the main idea of Unix is not on the command line.
It's about complexity.
A complex system needs to be taken apart. Each part should have a clear responsibility. The boundaries between the components should be simple. It is advisable not to hide the data unnecessarily. The behavior of the system must remain observable.
And most importantly, you don't need to do complicated things where you can do simple things.
This idea has outlived terminals, magnetic tapes, and old workstations.
It remains useful regardless of the interface of a modern system and where it is executed.
But modern systems solve other problems.
Unix was created in a world where the main object of a program's work was often a file or a stream of bytes.
Today, the system can work with completely different entities.
She may have a long-term condition. The history of changes. Users with different rights. Connections between objects. The rules of the subject area. Automatic actions. Artificial intelligence. Decisions that require human confirmation.
It is difficult to reduce such a system to a chain of programs, each of which reads standard input and writes to standard output.
And you don't have to.
The form must match the task.
The condition is sometimes necessary
Unix is especially beautiful where data goes through a chain of transformations.
We got a stream. Processed it. Passed on. Completed the work.
But many modern tasks require memory.
The system must remember what happened yesterday. Who changed the rule? Which version was active. What was accepted and what was rejected. Which objects are related and why.
It's not just a stream anymore.
A condition appears.
Sometimes developers try to get rid of the condition at any cost, because systems are simpler without it. But if the subject area itself has a condition, trying to hide it only shifts the complexity to another location.
A good architecture does not prohibit the complexity that actually exists in the task.
It prohibits unnecessary complexity.
Knowledge is not an ordinary file
This is especially evident in knowledge-based systems.
Knowledge can have an author. The version. The scope of application. Connection with other knowledge. It can be accepted, rejected, or under consideration.
Sometimes it is important to know not only the statement itself, but also its history.
A simple text file stores text perfectly. But if the relationships between statements, statuses, versions, and origin are important, a richer structure appears.
This is no longer a violation of the Unix philosophy.
This is a recognition of the nature of the data.
Simplicity does not mean that the model is poor
There is a dangerous form of simplicity: to throw out of the model everything that is difficult to implement.
Such a system does turn out to be small, but it ceases to reflect the task correctly.
True simplicity means something else to me. The system should contain only the complexity that is really necessary.
If knowledge has a version, you need to keep the version.
If a decision has to be confirmed by a human, it must be part of the system.
If one object is connected to another, the connection must exist explicitly, and not live only in the developer's head.
A simple architecture does not have to have a primitive model of the world.
Artificial intelligence is also changing the architecture.
The advent of language models has added another type of component.
A regular program executes a fairly precisely defined algorithm. The model works differently. You can transfer text, rules, and context to her and get a result that is not always completely predictable in advance.
Trying to pretend that this is a common feature sometimes hides important system properties.
You need to understand what data was passed to the model, what rules it received, what version of knowledge it used, and where human verification is required.
This means that an additional structure appears around the model.
Again, this is not a reason to abandon simplicity.
On the contrary, this is where simple borders become especially important.
The model must be replaceable
This is where the old Unix philosophy reappears almost literally.
I don't want the whole system to depend on one artificial intelligence model.
The model is a mechanism.
Today, you can use one. Another one will appear tomorrow. Some tasks may no longer require artificial intelligence at all and be solved by a conventional algorithm.
Therefore, knowledge and rules should not belong to the model.
They must exist separately.
The model receives them, applies them, and returns the result.
This is very close to the old idea of a good tool: it does its job, but it doesn't try to own the whole system.
The interface is more important than the implementation
Unix taught us to appreciate the boundaries between components.
Today, instead of a text channel, it can be a programming interface, a message, a tool call, or another way of interacting.
The form has changed, but the question remains the same.
Can one part of the system be replaced without rewriting the rest?
If so, the border was most likely chosen well.
If not, the components know too much about each other.
That is why the idea of modern protocols for interaction between artificial intelligence and tools is close to me. A good protocol allows the system to use the capabilities of a component without knowing its internal structure.
It's very Unix-like, even if it doesn't look like Unix at all.
A person is also a part of the system.
There is another difference in the modern world.
Not all solutions should be fully automated.
Sometimes the system has to prepare a proposal, but the final decision is made by the person. Sometimes a new rule must first be validated. Sometimes the cost of a mistake is too high for a fully automatic action.
In classical programming, a person was often outside: he wrote a program, ran it, and got the result.
In modern systems, a person can be part of the process itself.
This requires an explicit status, decision history, and confirmation points.
It is difficult to imagine such an architecture as a classic software pipeline.
But the principle of transparency becomes even more important here.
I don't want to build a black box.
You can make a system in which artificial intelligence knows everything.
Give him documents, conversation history, instructions, and ask him to make decisions.
At the first stage, it looks very simple.
But then questions arise.
Where did the specific rule come from? Who changed it? Why does the system respond differently today than it did a month ago? How can I delete an outdated solution? How can I use the same knowledge with a different model?
If there is no clear answer to these questions, the system becomes magical.
class="paragraph"> Unix has taught me to be suspicious of such magic.
I want to be able to look inside.
That's why I'm not building Unix.
My modern system has a constant state, versions, connections, rules, history, and interactions with artificial intelligence.
It doesn't have the idea that everything should be a file.
There is no requirement for each component to be a separate small team.
There is no need to turn every interaction into a text channel.
If you look only at the form, it's not Unix at all.
But if you look deeper, there's a lot left.
Knowledge is separated from the mechanism of its application. The components must have clear boundaries. The artificial intelligence model must be replaceable. The rules should be visible. Changes should leave a story. The system should allow a person to understand why a particular action occurred.
For me, this is the real legacy of Unix.
Principle is more important than implementation
Technological solutions are getting old.
Once upon a time, magnetic tape was a normal distribution media. Then came the CDs. Then they started downloading system images from the Internet. Now the server can be created in a few seconds.
The same thing will happen with today's technology.
Specific databases, cloud platforms, language models, and protocols will also become history someday.
Therefore, it is pointless to copy a specific device of the old system.
It is much more interesting to understand the principle that allowed some of her ideas to live for more than half a century.
Unix taught me not to build Unix
Perhaps this is the paradox.
The more I appreciate Unix, the less I want to mechanically copy it.
If the task requires a state, I use the state. If the data requires connections, I create connections. If artificial intelligence is useful, I use artificial intelligence. If a decision has to be made by a person, I leave the decision to the person.
But with every such choice, old questions remain.
Is it possible to make it easier?
Are the boundaries clear?
Is it possible to replace the component?
Where is the data located?
Where are the rules?
Is it possible to explain the behavior of the system?
Have I created unnecessary complexity?
That's what Unix taught me.
Not how to build Unix.
It's about how to build systems.
Unix появился раньше, чем я родился. Я познакомился с ним значительно позже — уже в конце девяностых, сначала по книгам, потом на настоящей машине с SCO Unix, а затем через Linux, исходные тексты ядра и собственные эксперименты.
С тех пор прошло много лет. Я работал с разными языками, платформами, базами данных, сетями, облаками и теперь с искусственным интеллектом. Но многие идеи Unix до сих пор кажутся мне удивительно правильными.
При этом система, которую я строю сегодня, совсем не похожа на Unix.
И в этом нет противоречия.
Любить Unix — не значит копировать Unix
Когда говорят о философии Unix, легко свести всё к нескольким внешним признакам: маленькие программы, командная строка, текстовые файлы, каналы между процессами.
Это действительно важные части Unix, но они появились в конкретную эпоху и решали конкретные задачи.
Компьютеры были другими. Память была дорогой. Пользователь работал через терминал. Основными объектами были процессы и файлы. Большую часть работы выполнял программист, который хорошо понимал систему.
Если сегодня просто воспроизвести эти формы, это ещё не означает следовать духу Unix.
Мне кажется, важнее понять, почему эти решения вообще появились.
Unix учит бороться со сложностью
Для меня главная идея Unix не в командной строке.
Она в отношении к сложности.
Сложную систему нужно разбирать на части. У каждой части должна быть понятная ответственность. Границы между компонентами должны быть простыми. Данные желательно не прятать без необходимости. Поведение системы должно оставаться наблюдаемым.
И главное — не нужно делать сложное там, где можно сделать простое.
Вот эта мысль пережила и терминалы, и магнитные ленты, и старые рабочие станции.
Она остаётся полезной независимо от того, какой интерфейс у современной системы и где она выполняется.
Но современные системы решают другие задачи
Unix создавался в мире, где основным объектом работы программы часто был файл или поток байтов.
Сегодня система может работать совсем с другими сущностями.
У неё может быть долговременное состояние. История изменений. Пользователи с разными правами. Связи между объектами. Правила предметной области. Автоматические действия. Искусственный интеллект. Решения, которые требуют подтверждения человека.
Такую систему трудно свести к цепочке программ, каждая из которых читает стандартный ввод и пишет в стандартный вывод.
И не нужно.
Форма должна соответствовать задаче.
Состояние иногда необходимо
Unix особенно красив там, где данные проходят через цепочку преобразований.
Получили поток. Обработали. Передали дальше. Завершили работу.
Но многие современные задачи требуют памяти.
Система должна помнить, что происходило вчера. Кто изменил правило. Какая версия была активна. Что было принято, а что отклонено. Какие объекты связаны между собой и почему.
Это уже не просто поток.
Появляется состояние.
Иногда разработчики стараются избавиться от состояния любой ценой, потому что системы без него проще. Но если сама предметная область имеет состояние, попытка скрыть его только переносит сложность в другое место.
Хорошая архитектура не запрещает сложность, которая действительно существует в задаче.
Она запрещает лишнюю сложность.
Знания — не обычный файл
Особенно хорошо это видно в системах, работающих со знаниями.
Знание может иметь автора. Версию. Область применения. Связь с другими знаниями. Оно может быть принято, отклонено или находиться на рассмотрении.
Иногда важно знать не только само утверждение, но и его историю.
Простой текстовый файл прекрасно хранит текст. Но если важны отношения между утверждениями, статусы, версии и происхождение, появляется более богатая структура.
Это уже не нарушение философии Unix.
Это признание природы данных.
Простота не означает бедность модели
Есть опасная форма простоты: выбросить из модели всё, что трудно реализовать.
Такая система действительно получается маленькой, но перестаёт правильно отражать задачу.
Настоящая простота для меня означает другое. Система должна содержать только ту сложность, которая действительно необходима.
Если у знания есть версия — версию нужно хранить.
Если решение должен подтвердить человек — это должно быть частью системы.
Если один объект связан с другим — связь должна существовать явно, а не жить только в голове разработчика.
Простая архитектура не обязана иметь примитивную модель мира.
Искусственный интеллект тоже меняет архитектуру
Появление языковых моделей добавило ещё один тип компонента.
Обычная программа выполняет достаточно точно определённый алгоритм. Модель работает иначе. Ей можно передать текст, правила, контекст и получить результат, который не всегда заранее полностью предсказуем.
Попытка сделать вид, что это обычная функция, иногда скрывает важные свойства системы.
Нужно понимать, какие данные были переданы модели, какие правила она получила, какую версию знания использовала и где требуется проверка человеком.
Значит, вокруг модели возникает дополнительная структура.
И снова это не повод отказаться от простоты.
Наоборот, именно здесь простые границы становятся особенно важными.
Модель должна быть заменяемой
Вот здесь старая философия Unix снова появляется почти буквально.
Я не хочу, чтобы вся система зависела от одной модели искусственного интеллекта.
Модель — механизм.
Сегодня можно использовать одну. Завтра появится другая. Какая-то задача вообще может перестать требовать искусственного интеллекта и решаться обычным алгоритмом.
Поэтому знания и правила не должны принадлежать модели.
Они должны существовать отдельно.
Модель получает их, применяет и возвращает результат.
Это очень близко к старой идее хорошего инструмента: он выполняет свою работу, но не пытается владеть всей системой.
Интерфейс важнее реализации
Unix научил ценить границы между компонентами.
Сегодня вместо текстового канала это может быть программный интерфейс, сообщение, вызов инструмента или другой способ взаимодействия.
Форма изменилась, но вопрос остаётся тем же.
Может ли одна часть системы быть заменена без переписывания остальных?
Если да, граница, скорее всего, выбрана удачно.
Если нет, компоненты знают друг о друге слишком много.
Именно поэтому мне близка идея современных протоколов взаимодействия между искусственным интеллектом и инструментами. Хороший протокол позволяет системе использовать возможности компонента, не зная его внутреннего устройства.
Это очень по-Unix, даже если внешне совсем на Unix не похоже.
Человек тоже является частью системы
Есть ещё одно отличие современного мира.
Не все решения стоит автоматизировать полностью.
Иногда система должна подготовить предложение, но окончательное решение принимает человек. Иногда новое правило сначала должно пройти проверку. Иногда цена ошибки слишком высока для полностью автоматического действия.
В классическом программировании человек часто находился снаружи: написал программу, запустил её и получил результат.
В современных системах человек может быть частью самого процесса.
Это требует явного состояния, истории решений и точек подтверждения.
Такую архитектуру трудно представить как классический программный конвейер.
Но принцип прозрачности здесь становится ещё важнее.
Я не хочу строить чёрный ящик
Можно сделать систему, в которой искусственный интеллект знает всё.
Передать ему документы, историю разговоров, инструкции и попросить принимать решения.
На первом этапе это выглядит очень просто.
Но затем возникают вопросы.
Откуда взялось конкретное правило? Кто его изменил? Почему система сегодня отвечает иначе, чем месяц назад? Как удалить устаревшее решение? Как использовать те же знания с другой моделью?
Если на эти вопросы нет ясного ответа, система становится магической.
Unix научил меня относиться к такой магии с подозрением.
Мне хочется иметь возможность заглянуть внутрь.
Поэтому я строю не Unix
Моя современная система имеет постоянное состояние, версии, связи, правила, историю и взаимодействие с искусственным интеллектом.
В ней нет идеи, что всё должно быть файлом.
Нет требования, чтобы каждый компонент был отдельной маленькой командой.
Нет необходимости превращать каждое взаимодействие в текстовый канал.
Если смотреть только на форму, это совершенно не Unix.
Но если смотреть глубже, многое осталось.
Знание отделено от механизма его применения. Компоненты должны иметь ясные границы. Модель искусственного интеллекта должна быть заменяемой. Правила должны быть видимыми. Изменения должны оставлять историю. Система должна позволять человеку понять, почему произошло то или иное действие.
Для меня это и есть настоящее наследие Unix.
Принцип важнее реализации
Технологические решения стареют.
Когда-то магнитная лента была нормальным носителем дистрибутива. Потом появились компакт-диски. Потом образы систем начали скачивать из Интернета. Теперь сервер можно создать за несколько секунд.
То же произойдёт с сегодняшними технологиями.
Конкретные базы данных, облачные платформы, языковые модели и протоколы тоже когда-нибудь станут историей.
Поэтому копировать конкретное устройство старой системы бессмысленно.
Гораздо интереснее понять принцип, который позволил некоторым её идеям прожить больше полувека.
Unix научил меня не строить Unix
Наверное, в этом и заключается парадокс.
Чем больше я ценю Unix, тем меньше мне хочется механически копировать его.
Если задача требует состояния — я использую состояние. Если данные требуют связей — создаю связи. Если искусственный интеллект полезен — использую искусственный интеллект. Если решение должен принять человек — оставляю решение человеку.
Но при каждом таком выборе остаются старые вопросы.
Можно ли сделать проще?
Понятны ли границы?
Можно ли заменить компонент?
Где находятся данные?
Где находятся правила?
Можно ли объяснить поведение системы?
Не создал ли я лишнюю сложность?
Вот этому меня научил Unix.
Не тому, как строить Unix.
А тому, как строить системы.