Время, как часть платформы ERP-систем

Игры разума - или псевдонаучные исследования? Моя доска вчера...

Игры разума — или псевдонаучные исследования? Моя доска вчера…

Всем привет!

Продолжаю публиковать странные и непонятные статьи.

Но вдруг, кому-то пригодится.

Поехали…

Хочется поговорить о времени, как о состоянии системы.

Но для начала нужна вводная: первая из них — временнАя переменная. С чего стартуем? Стартуем с дебага, как и я когда-то. Сидишь, трейсишь программу, и в дебаге у тебя есть несколько инструментов для похода по исходному коду: какой-нибудь step over, step into, run to cursor, step next. Ну, вроде все есть, но как бы:, а где step back? Вы никогда не пролетали в отладке мимо того, что отлаживаете? И сколько раз приходилось перезапускать отладку? Может, я один такой… несчастливый?

Как раз, проблема в том, что обратные операции неочевидны. Процессоры, (может я и неправ, это просто гипотеза), не могут работать в обратном направлении по исходному коду. Операция степени в обратном направлении — это извлечение корня, например. Возможно, поэтому у нас нет такого очевидного и удобного, лично для меня, инструмента — как вернуться на строку назад от текущей…

Что может помочь? Например, какие-нибудь инструменты логирования. Мы берем область памяти, которая выделена для хранения значения переменной, и записываем в «блокнот», что там происходит. В этом такте одно значение, в следующем другое… Мы формируем логи, так сказать.

Когда мы объявляем переменную, она будет «работать» с момента объявления до момента окончания работы исходного кода (выхода из подпрограммы или удаления этой переменной). Ее значение в процессе может быть многократно изменено без возможности восстановления. Обычно нас это устраивает, и значения в дебаге нас интересуют только в текущий момент. Обычно это говорит о том, что значение «вечно», оно было таким всегда, даже если один такт назад это было не так.

Ну или другой пример. В текстовый файл мы заносим какую-то информацию, что-то типа «здесь был Вася». Сохраняем его, забываем о нем на год, открываем, там эта информация. Чтобы понять когда мы его сохранили, смотрим на реквизиты файла. Дата создания равна дате модификации — все нормально, информация существует и будет существовать «вечно» с момента создания.

Если мы исправим строку на «здесь был Петя» и опять сохраним файл, то по дате модификации можно сказать, что файл изменился. Но какая информация была в нем до этого — неизвестно, и, значит, текущая информация могла быть в нем с момента создания файла. У нас нет логов, мы не можем посмотреть историю, и в будущем эта информация не изменится до тех пор, пока мы сами не захотим ее изменить.

Удалим этот… файл. Что это значит для нас? Возможно этого файла «никогда» не существовало или все-таки «временно» существовал?

«Временно», «никогда», «вечно» — это что-то, что связано со временем.

Работая с БД, проектами в которых есть ORM — добавив реквизит в класс и пройдя через дебри миграций — вы можете сказать что ваш класс существует в текущий момент, и прошлые ревизии кода и версии таблиц БД вам не интересны. Для всей вашей разрабатываемой системы — теперь это также «вечно», как и было до «правок». Вы сразу на всем протяжении времени системы теперь считаете — что так было всегда.

Ворох рефакторинга, дописывания кода, перенос данных, заполнение добавленного реквизита, удаление неиспользуемых ссылок… Конечно, я «утрирую» количество проблем. Но… вот я работаю в сфере — где все это превращается в постоянную головную боль. Мне важно знать, как это все работало, вычислялось и хранилось если не с начала запуска какой-нибудь ERP системы, то хотя бы лет на 15 назад. Все данные, код, классы, иерархия, наименования — важны мне с временными привязками. И да… все это можно делать через бакапы и ворох версий баз… А что делать с данными? Случайно сменил «снабженец» наименование «чупа-чупсов» на «яблоки молодильные» — промазал, бывает… Смотрим логи, поднимаем прошлые версии… долго, и мучительно, пытаемся восстановить — прошлое «наименование», и не факт, что сможем (опять утрирую — пример так себе).

Можно сказать, что проблема в архитектуре, плохая «защита от … пользователя» -, но нет в наших платформах по учету (всякой … важной информации) удобных средств логирования без потери данных. А потеря данных… плохо.

Ладно. Разбавим нытье конструктивом.

Есть у нас какое-то значение «обычного» реквизита в какой-нибудь распространенной учетной системе или наименование объекта. Пусть в текущий момент оно равно «Склад в Калининграде». Если временных меток нет и программно мы это не проверяем, то это значит что можно к этому реквизиту обратиться из условного «прошлого», хотя там этого реквизита (или объекта) могло не существовать.

| ------------------------------- «Склад в Калининграде»--------------------------------------------|

Начало работы ------------ текущий момент -------------------- Завершение работы

Это может быть результат дебага исходника. Мы напоролись на него в текущий момент. Какое оно было до этого момента, сказать сложно, надо «восстанавливать историю», читая исходник (логи), а каким оно будет после следующей итерации мы сказать не всегда можем, исходник может быть очень длинным и не простым в понимании. Но — сейчас оно такое. И имея исходник с очевидными усилиями мы можем понять какое значение будет до завершения работы.

А если это пользовательские данные? И они меняются произвольно каждую минуту? Дебаг пользователя не произвести — посмотреть в исходник и понять что он будет делать дальше мы не сможем…

Я описал несколько проблем, которые могут возникнуть при работе с кодом и данными:

  1. Отсутствие возможности отката изменений: когда мы изменяем значение переменной или удаляем файл, мы не можем вернуть его к предыдущему состоянию.

  2. Сложность восстановления данных: если данные были случайно изменены или удалены, может быть сложно или невозможно восстановить их.

  3. Потеря данных: если данные были утеряны из-за ошибки или случайного удаления, они могут быть безвозвратно потеряны.

  4. Сложность отслеживания изменений: если изменения в коде или данных происходят часто, может быть трудно отследить все изменения и быстро понять, как система работала в прошлом.

Тут как раз может помочь подход с временнЫми значениями. У каждой реквизита включаем логи, делаем прогнозы на текущий момент и внедряем изменения через Планы. Логи нам дают Историю изменений, причем записываем туда информацию о том что было до изменения и после. «Последнее значение» записываем в «тавтологическую» область «Последнее известное значение», и задаем модельный прогноз на будущее — к примеру равный последнему известному значению, для реализации планов на изменение. Без этого никак (почему так — попытаюсь рассказать ниже).

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

Но это мы про какой-то реквизит… Что мешает нам такое сделать на объектах? Или на классах? Или на исходниках? Мне показалось, что ничего не мешает… Надеюсь я не ошибся, пытаюсь это реализовать в разрабатываемой мной платформе.

Чтоб не быть теоретиком, сотрясающим воздух — проект положили сюда, демка там есть, глубокая альфа (Django+python):

https://github.com/fobyphill/forTea

Свежий дневник разработчика, он же пока мануал — тут.

https://github.com/fobyphill/forTea/tree/main/static/manuals

Ну, а с Планами — есть нюансы с таким подходом. Начинаю объяснять…

Итак примем что State — это все время, прошлое, будущее нашей системы.

Воспользуемся Static/Dynamic подходом, для описания Времени (примеры писал в прошлых статьях — сложных, и местами таких же непонятных…).

Static (История событий + последние факты)

Dynamic (Будущие события)

Static (Факты)

Dynamic (Область Шрёдингера)

Static (Прогнозы)

Dynamic (Планы)

Static (Факты)

Dynamic (Корректировка Факта в прошлом — PPA)

Static (Факты ОШ)

Dynamic (Plan ревизии ОШ)

Static (Факт прогноза)

Dynamic (Plan прогноза)

Static (Факт Плана)

Dynamic (Plan Плана)

Надо это все пояснить.

Рассмотрим картинку

14544c64d6787b8e06a5d88abf723fe4.png

В системе мы двигаемся по времени вперед, регистрируя факты, и во время регистрации фактов отмечаем дату и время регистрации. Но в текущий момент (tnow), когда мы смотрим на текущее состояние системы мы «видим» какой она была на момент последнего факта, а не на момент «сейчас». Зону, откуда мы ведем наше наблюдение я назвал областью Шрёдингера (надеюсь физики меня простят…), потому что наблюдаем последние факты не проводя их ревизию. Взорвалась ли сейчас Бетельгейзе или нет — науке неизвестно, но она могла взорваться сейчас, и узнаем мы об этом позднее, а потом сообщим что она взорвалась 640 лет назад (еще раз простите).

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

Еще эту область можно гипотетически назвать временем опроса системы или квантом факта.

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

Область Шрёдингера нам интересна еще с одной стороны… Она говорит, что План на tnow+1, основанный на последних фактах, зарегистрированных на tnow-1, проходя, через ОШ — получает неопределенность, если не провести ревизию фактов на tnow и накладывает запрет на ввод Планов. Т.е. Планы можно вводить только после ревизии состояния системы (объекта, ревизита) на tnow, и пользуясь моделью, что последние известные факты в будущем не изменятся, или изменятся прогнозируемо.

Также зона ОШ из-за постоянного расширения увеличивает неопределенность в Планах. Чем меньше эта зона, тем более точные Планы. Чем она больше, тем более вероятно что Планы станут невалидными.

Зону Будущего разбиваем на две части: Прогнозы и Планы. Прогноз по своей природе довольно статичный, если мы его определяем с помощью ревизии зоны ОШ. Это наши будущие возможные Факты. Планы — динамические, и их использование при моделировании системы тяжело формализуются, так как в себе содержат неопределенность, порождаемую набегающей зоной ОШ. Для решения неопределенности Планы содержат в себе функции контрактного поведения (Предусловия, постусловия, ивариантность)

Я надеюсь, что смогу с коллегой «Архитектором» в дальнейшем переложить все это на «нормальный» математический язык, чтобы это не выглядело как «болтология». Ожидаю к лету, может что-то раньше появится.

Спасибо за внимание! Надеюсь я ничего не сломал и это все не «игры разума»…

© Habrahabr.ru