amarao: (Default)
Если при чтении кода какого-то ПО человеком, который это ПО только использовал, ему всё понятно, значит, это ПО не прячет сложность.

Хорошее ПО прячет сложность от пользователя. Это означает, что исходный код ПО содержит в себе сложность, о которой потребитель ПО не знает. Наоборот, если потребитель очень хорошо знает эту сложность, ПО плохо её прячет.

Из этого можно сделать вывод, что большая часть хорошего ПО очень сложна. Можно даже довести до максимы, чем более в использовании простое ПО, тем оно сложнее для чтения.
amarao: (Default)
Одно из направлений боевой философии (т.е. самой настоящей философии на фронтире человеческого разума, но с запретом на "воду" и аппеляции к плохо определённым фантазиям автора) является разработка языков программирования.

Ни что так сильно не влияет на объяснение нашего понимания знания, знания о знании, причинно-следственной связи, логике, как язык программирования. Модель, которую представляет язык программирования, это же философия чистой воды. Все эти "передача по значению" против "передачи по ссылке", r-value l-value, placement expression, это же чистой воды философия, причём высочайшего порядка, обладающая практической реализацией (доказывающей непротиворечивость по факту реализации).
amarao: (Default)
Я недавно написал про ощутимое изменение core values после чтения ГЭБ. У него есть много последствий, и оно из них - это проблема выбора направления движения.

Когда мы стоим на позиции редукционизма, то есть ставим своей целью понять как работает система через понимание как работают её части, или даже нижележащая подсистема, то наше направление движение понятно: есть нечто и мы хотим понять её части. Например, столкнувшись с языком программирования нас начинает интересовать как он использует память, как выглядет его кодогенерация, как он решает проблему раскручивания исключений и т.д.; а может быть, мы даже не особо интересуемся его потрошками, но нам очень интересно, какими именно инструкциями он добивается от процессора такой быстрой работы.

Направление простое, потому что имея целое, и разделив его на части, мы не получим существенно больше. Мы можем обнаружить, что процессор умеет больше, чем использует компилятор, но в отношении самого компилятора мы тожно не увеличим сложность. Редукция обладает анти-эмергентным свойством, то есть "набор деталей менее сложен, чем само устройство". Это невероятно привлекательная модель, потому что мы от сложного переходим к простому. В каком-то смысле это аналог дифференцирования. Оно сильно проще интегрирования и мы практически всегда можем его сделать. Несколько монстров-контрпримеров совершенно не мешают работать с большинством других функций без особых проблем.

Редукция сужает поле для исследования и понимания. Достаточно целенаправленная редукция (с фильтрацией точно не существенных подсистем) позволяет добраться до ответа очень быстро. Именно так работает отладка: открываешь код и ищешь где именно сломано. Поломка вероятнее всего будет либо локальная (простой вариант), либо результат взаимодействия нескольких подсистем (трудный случай).


А теперь мы отказываемся от редукционизма, как метода понимать систему. И куда тогда? Окей, холизм, холизм. Холизм чего? Системы? Но если мы остаёмся на одном уровне системы, то мы получаем очень скудную информацию: знание о том, как устроена система.

В редукционизме мы понимаем как устроена нижележащая система, то есть мы можем применить это знание к множеству других систем, построенных на том же принципе (один из аргументов ассемблерофилии - я знаю как они все работают, потому что все они используют ассемблер).

Так что в холизме мы вынужены искать движение вверх, то есть искать метасистему из которой мы можем рассматривать изучаемую систему как частный случай. Если мы это не делаем, то мы теряем мультипликативный эффект знаний.

И куда и как мы двигаемся тогда? Вместо очевидного направления редукционизма мы получаем несчётное множество метасистем, в которой наша система является частным случаем. Как мы можем понять, какая из метасистем наиболее интересна? Более того, где эта метасистема? Что изучать-то? Мы же не придумываем, мы изучаем. У нас есть необходимость в изучении метасистемы, но она не описана, у нас нет документации или даже "кусков кода" для изучения.

Мы можем сами сконструировать метасистему и изучать её - но мы не знаем как её сконструировать, мы не знаем как её изучать и мы не знаем, та ли эта метасистема, или нет.


Так что холизм, при всей своей привлекательности, не обладает конструктивностью процесса изучения. Наш разумный предел, это изучение самой системы, без метасистемы. Мы можем попытаться расшириться до метасистемы после изучения всех систем в метасистеме, но это очень медленный и трудный процесс. Не напоминает ли он интегрирование? Такое же безнадёжное и работающее только для каких-то отдельных случаев?

Поменяв редукционизм на холизм мы получаем практическую проблему обучения или исследования. Здорово, когда кто-то для нас уже нашёл и создал метасистему, в которой мы можем изучать нашу систему с мультипликативным эффектом. Но чаще всего это не так, и мы получаем выбор между узким (но эмергентным) знанием, или широким, но антиэмергентным.

Вот где-то тут я и ощущаю чувство невозвратной потери от ранее абсолютно положительного жизненного тезиса.
amarao: (Default)
Я долго-долго читал ГЭБ (http://flibusta.is/b/198312, описание в википедии: https://ru.wikipedia.org/wiki/%D0%93%D1%91%D0%B4%D0%B5%D0%BB%D1%8C,_%D0%AD%D1%88%D0%B5%D1%80,_%D0%91%D0%B0%D1%85).

Ещё дольше я её понимаю. В каком-то смысле, в районе научного футуризма - совершенно essential книга.

Флешбэк-спойлер. Книга 1979 года, Но автор сумел предсказать, что chatgpt будет ужасно плохо считать и будет путаться в математике, и что решением будет оснастить её внешним калькулятором, чтобы было проще считать.


Но я не про саму книгу. Долго пережёвывая её идеи, я был вынужден поменять одну из своих фундаментальных ценностей (да-да, не меньше не больше). Традиционно, столкнувшись со сложной системой, моей ценностью было понять как эта система устроена, то есть увидеть её элементарные блоки и принципы, по которым она работает. Архитектурный редукционизм, так сказать.

Одним из проявлений архитектурного редукционизма является "желание ассемблера". Когда-то, давным давно, я отметал всякие хаскелёвые абстракции, как не имеющие отношения к реальности (или имеющие, но по чистой случайности). А реальность эта - в каком байте MBR находится partition table, есть ли suid бит на исполняемом файле, и как именно выглядит вызов функции с точки зрения заполнения регистров (calling convention).

В самом студенческо-школьном виде это выглядело как ассемблерный снобизм, мол, ассемблер - это настоящее, а всё остальное наносное.

Максимализм повыветрился, а вот редукционистская ценность построения знания о системе "снизу вверх" осталась.

И вот, ГЭБ. В котором очень много посвящено как раз проблеме невозможности осознать сложность системы глядя на её редуцированные базовые правила. Половина книги как раз и посвящена построению очень сложного из очень простых механизмов так, что никакое знание об устройстве механизма не может понять то, что строят.

Я бы сказал, что с точки зрения внутренней философии это даже большее откровение, чем рефакторинги факторио, потому что это куда более core value. Это один из элементов мировоззрения, и путём множественных наблюдений я вынужден прийти к выводу, что моё предыдущее убеждение не приводит к тем результатам, которые я ожидал.

Моё предыдущее убеждение: в столкновении с сложным и неизвестным, изучение принципов работы нижележащей системы даёт возможность понять это "сложное и неизвестное" больше, чем если бы время тратилось на "сложное и неизвестное" само по себе.

Я не могу просто так взять и заменить core believe на другой, это слишком большое и сложное изменение; но я признаю, что "закапываться в стек" не является эффективной стратегией изучения. Чем именно надо его заменить я пока не понимаю, пока что я всего лишь пошатнул одно из оснований своего собственного восприятия мира.
amarao: (Default)
Когда софт становится магическим? Не в тот момент, когда мы не понимаем, как он считает. Это, ладно. data in, data out, GLUT всё порешает.

ПО становится "магическим", когда оно делает сайд-эффекты, которые мы не понимаем. Оно меняет в окружающем мире что-то, про существование чего мы не знаем, либо про существование чего мы знаем опосредованно по "ноге слона". Именно сайд-эффекты вне нашего понимания и есть "магия". Соответственно, негативная магия - это неизвестные side causes, когда поведение ПО зависит "от фазы луны", то есть мы не можем понять от чего.
amarao: (Default)

А вот я хочу продолжить думать умное про ансибл, ci/cd и прочую рабочую фигню между гитом и сервером.

Классическое программирование стремится абстрагироваться от ввода-вывода. Идеалом программы (имплементации алгоритма) является полностью определённая функция, которая для заданных входных значений выдаёт определённые выходные. При этом такая программа работает в полностью определённой среде (мы знаем список доступных состояний машины Тьюринга, либо используем только хорошо нам известные функции, если работаем в функциональной модели).

Теперь посмотрим на "best practice для Ansible". Всё, что происходит - это сайд-эффекты. Некоторые из них предсказуемы, некоторые условно предсказуемы, некоторые не совсем предсказуемы. Часть сайд-эффектов имеют в качестве зависимости внешний мир (т.е. могут фейлиться по каким-то внешним причинам не связанным с нашим кодом).

В программировании существует модель описания этого, посредством интерейсов. Мол, у нас неконтролируемое "нечто" снаружи, консистентность внутри, и есть код, задача которого описать "нечто снаружи" в терминах, которые устраивают модель внутри. Если мир расходится с моделью, это это EnvironmentError, который мы можем пытаться описывать в терминах нашей модели (и может, даже, исправлять).

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

И вот тут вот появляется парадигма, условно, админская. Девопс, ансибл, iaac, называйте как хотите. Это форма компьютерного экзестенциализима, которая принимает систему "as is", без чрезмерной строгости. Модель стремится к уменьшению и упрощению, и чем проще модель, тем меньше она отличается от реальности. От модели оставляют только то, что минимально необходимо для решения задачи. Интерпретация происходящего предельно близка к утиной типизации (если у нас получилось сделать то, что нужно, то это хорошо, а что это именно - уже не совсем важно).

В отличие от питона, в котором утиная типизация позволяет экономить на продумывании структур и типов, этот подход решает другую проблему: упрощение интерпретации внешнего мира и взаимодействия с ним.

Почему это упрощение неизбежно?

Потому что сисадминский код взаимодействует с необъятно сложными системами. Каждый второй модуль того же Ансибла, за собой тащит необъятную сложность. Вот, предположим, мы поднимаем виртуалку с постгрес и настраиваем в ней пользователя.

Сначала мы общаемся с пакетным менеджером. Модель пактного менеджера - это граф зависимостей, который разрешается в непротиворечивую комбинацию пакетов, либо оставляет систему в broken state. Взаимодействие с пакетным менеджером в общем случае должно предусматривать графы как структуры данных. Это очень много. Пакетный менеджер так же зависит от системы доверия ключам, которая в свою очередь зависит от даты, установленных ключей и чужих серверов. Ещё у нас могут быть transient проблемы: например, блокировка доступа к пакетному менеджеру из-за параллельного процесса (cloud-init, unattended updates, etc).

Потом мы должны создать образ виртуальной машины. Это в себя влючает тот же пакетный менеджер, но ещё нам надо понимать структуру дисков, взаимоотношения разделов, блочных устройств, mountpoint'ов, трансляцию оных их текущего представления в будущее представление внутри виртуальной машины.

Где-то тут же у нас есть модель файловой системы, поскольку образ будущей VM куда-то положен в файловой системе.

Потом мы погружаемся в мир XML для libvirt'а с одной стороны (надо правильно расставлять атрибуты и ноды внутри xml tree), и в мир устройства виртуальных машин с другой.

Виртуальные машины в свою очередь имеют несколько domain specific областей - концепцию "машины", внутри которой есть PCI-шина (ещё одно дерево с крайне запутанной и сложной логикой), сети (которая включает в себя целые пласты знаний про бриджи, раутинг, macvtap, pci passthrough, nat, etc).

Потом мы оказываемся в опять с пакетным менеджером.

Потом с нами здоровается мануал по postgres, где для правильного описания прав пользователя нужно знать какие базы данных, схемы, таблицы и т.д. нужно давать. И всё это весьма и весьма нетривиально.

Заметим, это всё находится поверх сетевой абстракции хоста, и транспортной абстракции ssh, через (очень хорошо работающий) слой абстрации по запуску питона через ssh внутри ansiballZ.

Это не сложно, это необъятно сложно. Любая попытка "сделать правильно" (т.е. формировать XML как осмысленное дерево, конструирование дерева PCI-устройств, поддержка полной модели прав пользователей postgres или графа зависимостей в apt) приведёт к одному или комбинации нескольких результатов: * Непозводительно медленная разработка (десятки тысяч строк кода), закончившаяся ничем. * Ошибки в описании предметной области, которые критичеки нарушают точность модели (не всё предусмотрено). * Перегрузка получившегося кода излишними понятиями, которые не нужны для достижения результата.

Таким образом, "реализовать правильно" (т.е. реализовать честный интерфейс из предметной области в модель) мы не можем из-за слишком высокой сложности и разнообразности предметной области.

Какие альтернативы? Начать реализовывать правильно и не дореализовать (см список последствий выше). Или... Не реализовывать вообще, а использовать компьютерный экзестенцианализм в чистом виде. Что нас, на самом деле, и приводит к best practices Ансибла: * Список пакетов для установки с retries для защиты от локов. * Хардкоженный список элементов для image builder'а. * template из XML, в котором мы руками пишем львиную долю, заменяя минимальное количество элементов для интерполяции. * Минимальный по сложности код заведения пользователя в postgres, возможно, не обладающий максимальной точностью по правам (если нет такой потребности).

Такой поверхностный подход позволяет сделать быстро и всё, что нужно. При этом он всегда страдает неполнотой и неожиданностями (теперь к transient ошибкам добавляются ошибки ожиданий, потому что мы делаем, например, не xml, а текстовый файл похожий на xml).

Что делать для повышения надёжности? Вместо уточнения и усложнения модели (что приведёт нас в трясину, описанную выше), мы просто стараемся покрыть тестами наши простые сценарии использования, зафиксировать зависимости.

Это всё работает не до конца, потому что IRL может оказываться отличным от наших ожиданий в момент тестов. В конце там ещё один комплект тестов, на этот раз инфраструктурных, которые проверяют, что сделанное одним образом соответствует ожиданиям, проверенным другим образом (поставили postgres apt'ом, проверили, что порт слушает).

Таким образом, философия сайд-эффектов кардинально отличается от философии программирования (как полу-математической дисциплины). Принятие этого факта позволяет избежать довольно распространённого феномена "программировать на ансибле", который бывает двух видов: принятие решений и попытка "понять" предметную область. Есть борьба с принятием решений в ансибле - это героический подвиг во имя улучшения сопровождения (всё время подвиги и не всегда успех), то отказ от "понимания" предметной области (на самом деле - трансляции предметной области в структуры данных), это философская максима, которую легко реализовать, для которой легко заметить отклонения, и в целом, реализуемая задача.

Profile

amarao: (Default)
amarao

June 2025

S M T W T F S
12 3456 7
8 9101112 1314
15161718192021
22232425262728
2930     

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 13th, 2025 06:43 pm
Powered by Dreamwidth Studios