Комментарии 88
Ну и с ACID я так и не понял, что вы собираетесь делать. У SQL есть вполне декларативная и простая модель с блокировками (более) или update conflict'ами при RR/SERIALIZABLE уровнях изоляции. Как вы тот же остаток предлагаете целостным поддерживать?
2) Остатки не нужно блокировать, остаток при каждой операции генерируется новый. Блокировать нужно кэш на момент расчета этого остатка, самое простое решение — мьютекс на коллекцию, реально конечно придется заморочиться с уровнями изоляции, но сейчас у меня задача только прототипирование идеи, принципиальных проблем не вижу, если все данные в памяти, то наложить блокировку уж точно не сложнее, чем в РСУБД.
Ну и не понял зачет этот огород со смещениями и seek и read, если SQL умеет это делать сам и из коробки.
2) Ну то есть ручные пессимистичные блокировки. Опять-таки SQL это из коробки, а главное куда эффективнее за счет оптимистичных блокировок умеет делать.
То есть я так и не понял чем вас SQL не устраивает?
У них всех узкое место — блокировки
Так их не от хорошей жизни делают. А именно потому что в ERP целостность данных действительно важна. Тут если остаток поплывет, это будет очень плохо (куда хуже чем незагруженная фотка в условном инстраграмме). И как раз версионные СУБД с их оптимистичными блокировками позволяют более менее эффективно решать проблему целостности, не сильно жертвуя масштабируемостью. То что многие учетные системы используют ручные пессимистичные блокировки это конкретно кривость рук их разработчиков, но вы то же предлагаете тоже самое.
и неконтролируемое расползание ошибок пользовательских алгоритмов по сотне таблиц (из тысячи штатных)
Это решается построением еще одного уровня абстракции над SQL. Но никак не переходом на NoSQL, где с этим может быть все еще хуже.
Изменить схему хранения данных, поле добавить — выгоняй пользователей на час, и т.д.
Вообще ЕМНИП СУБД позволяют очень много вещей делать не выгоняя пользователей. Не говоря уже о том, что динамическое изменение структуры по ходу и надежность — это противоположные вещи.
Мне нужна биг-дата ERP
Вообще у вас странная ERP. 24x7 (что уже редкость), с петабайтами данных и триллионами транзакций (что строго говоря для SQL на примитивной логике тоже не проблема, вспомните убер) и с логикой где не нужны выборки по условиям и целостность данных. Вы уверены что такие ERP существуют? И вообще в моем понимании ERP это именно что сложно-функциональные бизнес-приложения с высокими требованиями к целостности. А что это в вашем представлении?
По последнему вопросу — я достаточно с ERP поработал, и с нашими, и с ненашими, нет там высоких требований к плотности транзакций — максимум что я видел в штатном режиме работы — это одна транзакция в секунду :) Больше только в режиме закрытия периода, а это обычно по ночам. У биллингов и финтеха намного больше, вот там нужны вообще in-memory СУБД. А данных в ERP накапливается много, аудируемость важна, защита от злонамеренного разработчика или админа. Неспроста придумали и старательно форсят функциональное программирование — оно не про скорость, оно про надежность и тестируемость кода.
Проектик этот — чисто исследовательский, по результатам которого я кое-чему научился, и понял, что например могу миллиард записей обработать за минуты (а не часы)
дурное дело нехитрое.
запустил select count(*)
в ms sql с условием, не попадающим в индексы, на таблице с 200кк записей, в один поток — 24с. экстраполируем на миллиард записей — 2 минуты. если убрать option (maxdop 1)
— будет в разы быстрее.
Неспроста придумали и старательно форсят функциональное программирование — оно не про скорость, оно про надежность и тестируемость кода.
А причем тут функциональное программирование? Это классная штука не спорю, но его можно одинаково «компилировать» как в SQL (что многие и делают) так и в NoSQL. И причин «компилировать» все в SQL куда больше, прежде всего из-за важных оптимизаций (с индексами и параллелизмом) и ACID из коробки.
Ни одна из известных мне систем не масштабируется до уровня триллиона транзакций и петабайта данных
а ваша система с fullscan на каждый чих масштабируется?
них всех узкое место — блокировки, и неконтролируемое расползание ошибок пользовательских алгоритмов по сотне таблиц (из тысячи штатных)
из статьи:
К примеру, триггер документа «продажа» делает следующее:
как тут без блокировок/транзакций решается проблема с race condition при одновременном обновлении баланса двумя пользовтелями?
Потому что это квинтэссенция 1С, JavaScript (простите, TypeScript) и Функционального Программирования. Иногда человек так упарывается в своих заблуждениях, что начинает считать труды поколений разрабов до него глупыми заблуждениями.
начинает считать труды поколений разрабов до него глупыми заблуждениями.Вы что-то перепутали, я такого точно не говорил :)
Каждый инструмент хорош там, где он выполняет именно то ради чего создавался. И чем он менее универсален, тем лучше. А «умные дяди» работают за деньги и клепают что им скажут (а говорят, по моему опыту, клепать «универсальное» с кучей нахлабучек на каждый случай жизни сферического коня в вакууме), так что сколько бы сумоист не тренировался, а в паркуре лучшим не станет ;) ИМХО
Да вот то ж.
Крайне странные представления и о ERP, и о бигдате.
Какая-то исследовательская кривулька с фуллсканами, не тестированная даже на трех юзверях, вдруг стала продуктом уровня Enterprise (мы-то считали, что это когда хотя бы юзверей 100 стабильно годами работают в системе, и она не падает).
Вот что происходит, когда модные слова NoSQL, bigdata, функциональное программирование ложаться на неокрепшие мозги, и там в результате пермутаций рождается навязчивая идея, что все зло от SQL, хотя это наиболее эффективный инструмент для работы со структурированной информацией.
Хочется задать вопрос — а вот hadoop, spark, это у нас все же считается бигдатой, или только файлы с Json, которые парсятся TypeScript достойны носить это гордое имя?
Я к тому, что вот можно со скаловским DSL Quill написать строго в функциональном программировании (уж коли вам оно так нравится) с типобезопасностью и лямбдами что-то типа такого:
val q = quote {
for {
p < — query[Person]
a < — query[Address].join(a => a.fk == p.id)
c < — query[Company].leftJoin(c => c.zip == a.zip)
} yield (p,a,c)
}
ctx.run(q) //: List[(Person, Address, Option[Company])]
(отсюда github.com/getquill/quill)
А оно там само скомпилируется (о ужас!) в Spark SQL, выполнится на Hadoop кластере по простым паркетным файлам многотерабайтного объема, и никаких велосипедов изобретать не потребуется, достаточно просто выгрузить данные из обычной (настоящей) ERP в Hadoop.
PS
Хотя, на самом деле вы SQL на скале написали, семантика join, только со стрелочками. И никакой иммутабельности в помине.
Если говорить про экземпляры кейс-классов и коллекции, в скале все по умолчанию иммутабельное, а джойны — в данном случае чистые функции с лямбдами в параметрах, в функциональном стиле.
Но вы, очевидно, под этим термином подразумеваете запрет на изменение данных, что легко можно организовать даже в 1С: Бухгалтерия т.н. закрытием периода, и отьемом прав работы в закрытом периоде, отьемом прав на редактирование справочников. Хотя в случае с выгрузкой, ваши данные в hadoop и так никто не тронет.
Но уж точно эта проблема не решается переходом с SQL на NoSQL, в результате чего рождается "бигдата" из многократно задублированной при денормализации информации.
Разве что можно сьездить на конференцию и сказать "Мы работаем с ПЕТАБАЙТОМ!!!", но и то когда будете рассказывать подробности, конфуз может выйти. )
900 мегабайт данных должны работать за 0.1с на запрос на чайнике.
Преимущество реляционного решения — вообще можно обойтись без хранения промежуточных остатков. Их можно моментально получить полным пересчетом. По таблице с числовыми полями даже mysql справится.
Кроме того ваша система ляжет на сложных репортах, уже проходил это на одном из проектов на CouchDb.
Пришлось переносить все на mssql
Так в любой ERP количество промежуточных данных на порядок больше количества документов
С промежуточными данными вы явно преувеличиваете. В 1С остатки хранятся для промежуточных периодов (по умолчанию по дням ЕМНИП, а потом по месяцам) и то только потому что а) они пытаются аналитику за далекие периоды в оперативную базу положить б) у них все очень плохо с оптимизацией запросов (в частности predicate push down'ами) и не храни они промежуточные итоги, с производительностью все было бы куда хуже. Так что это не показатель.
Остальные системы в основном хранят только актуальные остатки, а дальше обратным счетом рассчитывают показатели на нужные даты.
у них все очень плохо с оптимизацией запросов (в частности predicate push down'ами)Кстати непонятно почему, ведь там mssql.
А, во-вторых, они весьма вольно обходятся с физмоделью / генерацией запросов (например в составных типах — эдаком суррогате наследования), вставляя туда OR'ы с CASE'ами, где даже MS SQL начинает конкретно чудить.
Из тех кто удалось его хоть немного изменить, я знаю только Odoo — они как раз взяли что-то условно трендовое (python), навернули над ним свой фреймворк (на самом деле это самая важная часть, потому как синтаксис языка это дело второстепенное), сделали интерфейс более современным, ну и главное обеспечили хоть какую-то модульность и сделали маркетплэйс для разработчиков (аля отраслевок 1С). По итогу у них 16к модулей написанных сторонними разработчиками и уже 4 миллиона пользователей как у 1С. Но, надо понимать, что технологический потенциал Odoo ограничен, поэтому это строго говоря только малый бизнес (по западным меркам), ну и в принципе им даже на западе консолидировать рынок вряд ли удастся. Не говоря уже о том, чтобы сильно изменить уже частично консолидированный рынок в России (в тех сегментах куда они лезут).
Обычно так говорят, когда система не позволяет управлять сложностью.
То что я видел, и по своему опыту с реально сложными логиками там будут проблемы, такие же как у условного 1С. А значит текущая их бизнес-модель на рынке среднего и крупного бизнеса не сработает. Модель 1С тоже не сработает, так как так консолидировать рынок они уже не смогут (рынок на западе уже в достаточно mature и конкурентном состоянии и нужно что-то более революционное).
Ну и еще раз питон (как сам язык) это небольшая часть всей платформы (если мы говорим про платформы). Не надо переоценивать его роль. Есть еще штук 10 различных аспектов, где Odoo в чем-то лучше, в чем-то хуже. То есть может даже Odoo и лучше 1С, но не в 10 раз, а значит превратить brownfield в greenfield вряд ли ему удастся.
PS: Например, если взять тоже наследование и полиморфизм в бизнес-приложениях ключевой момент там — поддержка полиморфизма в SQL слое, а это ни Odoo, ни 1С толком не удалось.
поддержка полиморфизма в SQL слое, а это ни Odoo, ни 1С толком не удалось.Уже 2 статьи написал на эту тему, но информация пока не заходит :) Если абстрагироваться от всяких мелочей моего pet-проекта, то останется главное — функционально-ориентированное прикладное API, которое, в отличие от повсеместно используемого процедурного с вкраплением SQL — более масштабируемо в плане управления сложностью, хотя и менее производительно, ведь за все надо платить.
Строго говоря разработчику все равно как это будет выполняться, если выполняться будет быстро и надежно. А у SQL все это есть из коробки. Собственно поэтому SQL по факту и стал стандартом в отрасли.
Все остальное просто лишняя работа, бинарная сериализация или компиляция в SQL — у меня нет свободных ресурсов чтобы это все писать, поэтому беру самое тупое и простое — цикл по файлу. В реальном продукте конечно это будет сделано по-другому (и не мной), наверняка все должно храниться в РСУБД с индексами, но это имеет смысл делать только тогда, когда имеет смысл делать.
Для меня сейчас главное — понять насколько сложным и (не) понятным будет прикладной код для типовых алгоритмов типа расчета себестоимости в производстве или MRP, сколько промежуточных данных придется нагенерить, какие будут связи между этими данными, и т.д.
Вот тут есть пример. Хотя он переусложнен немного для производительности, можно его еще проще сделать.
Функциональщина предполагает работу с потоками данных, а SQL манипулирует стейтом, и это совершенно разные подходы.
В SQL как раз все четко разделено. За изменение стейта отвечает DML, за вычисление данных SELECT. И если таблицу рассматривать как поток данных на нее вполне отлично ложится функциональщина. Подходы как раз очень схожи. Посмотрите хотя бы на LINQ в .Net. Мы с lair много на эту тему спорили. Вот пример как это в .Net скажем сделано.
a) хранить данные специальным образом
б) придумать специальный «потоковый» DSL
в) реализовать продвинутый кэш
г) партиционирование потока + seek() в виде дополнительной плюшки
Честно говоря, понятия не имею, жизнеспособен такой подход или нет, наверняка исследования проводились, но я не нашел, на первый взгляд это дает возможность неограниченного масштабирования при сохранении рантайма простым. А значит диапазон применений — от аудита потока ЭСФ в масштабах страны, до рилтайм анализа сетевого трафика.
PS
Ушел читать про неочередной язык программирования…
То что вы предлагаете это как раз увеличение производительности, за счет значительного упрощения и снижения оверхедов создаваемых SQL серверами (собственно это обычно и называют NoSQL). Но это подходит как раз для фейсбуков / инстаграммов с примитивной логикой, но очень большой нагрузкой. ERP это из другой оперы (я бы сказал противоположной). Вот Тут мы пытались все это немного систематизировать (насколько это в принципе возможно).
Если говорить конкретно про масштабирование, то random access ему никак не мешает.Конечно мешает. Любой мьютекс на шаред-стейт приводит к ожиданиям потоков, а значит ограничивает параллелизм. Даже теорема есть специальная. Не от хорошей жизни придумали хаскель, где в принципе запрещен стейт, а производительность у него весьма впечатляет, по последним бенчам в блоге PsyHaSTe например.
Опять же, если вы свои алгоритмы строите на итераторах без мутабельных таблиц — вам намного реже нужны транзакции, тем более распределенные, таким образом еще одно узкое место отпадает.
PS
По предыдущей ссылке, респект, прочитал, но вы предлагаете языковое улучшение, а не смену парадигмы, поэтому ваш подход назвать функциональным можно с бОльшей натяжкой, чем мой.
Любой мьютекс на шаред-стейт приводит к ожиданиям потоков
Не совсем понял. Ну включите уровень изоляции READ UNCOMMITED и будут у вас потоки читать грязные данные (по принципу что есть то есть) практически без блокировок. То есть параллелизм будет неограничен.
хаскель, где в принципе запрещен стейт
Вот тут есть доля лукавства. Данные то он откуда то берет для вычислений, эти данные и есть state.
То есть если вам дать «фиксированную» SQL базу и политикой безопасности запретить DML (то есть разрешить только SELECT), вот вам и чистая функциональщина получится (тоже без state).
Опять же, если вы свои алгоритмы строите на итераторах без мутабельных таблиц — вам намного реже нужны транзакции, тем более распределенные, таким образом еще одно узкое место отпадает.
Но данные для вычислений откуда то должны браться.
PS
По предыдущей ссылке, респект, прочитал, но вы предлагаете языковое улучшение, а не смену парадигмы, поэтому ваш подход назвать функциональным можно с бОльшей натяжкой, чем мой.
А можно уточнить тогда что вы подразумеваете под функциональным подходом? Чистые функции? Но данные все равно должны как-то попадать в систему, для их использования. То есть если взять тот же SQL, то SELECT — чистые функции, DML — подносчик снарядов для этих чистых функций. Вы же кстати в курсе что SELECT полон по тьюрингу и на нем можно любые вычисления реализовать.
То есть по сути SQL (а точнее SELECT как его основной оператор) это и есть функциональный подход. И кстати причина почему он настолько популярен.
Под ФП я понимаю (это неканонично) прежде всего работу на потоках иммутабельных исходных данных с помощью ленивых итераторов и их композиции. В терминах ERP — вычисления на потоке первичных документов. Конечно, данные, то есть документы, где-то хранятся, но зная что они неизменные, мы можем много чего оптимизировать. В частности распараллелить свой алгоритм «ручками», а не надеяться на рантайм.
Конечно, в этом есть доля лукавства, ведь для любой свертки сложнее чем sum() нужен кэш ранее просмотренных документов (к которым вернуться уже невозможно), а кэш это и есть шаред стейт, со всеми вытекающими проблемами. Но пока я не вижу таких алгоритмов ERP, которые нельзя было бы реализовать таким способом. Пересопоставление в текущем периоде — да, это полное пересоздание мутабельной части журнала документов, то есть блокировка базы, что конечно хуже чем блокировка отдельных записей, но надежда в том что размер текущего периода — это миллионы транзакций, а не трилллионы, и вычисления в памяти переваривают это за секунды.
Собственно для этого в СУБД есть материализованные представления (они выполняют ту же функцию что и ленивые вычисления, с той лишь разницей что вычисляются сразу, а потом только инкрементально обновляются). Другое дело что в современных СУБД они реализованы мягко говоря в очень частных случаях. Но скажем в lsFusion нам удалось реализовать это в общем случае.
но надежда в том что размер текущего периода — это миллионы транзакций, а не трилллионы, и вычисления в памяти переваривают это за секунды.
Еще раз, то что вычисление идет в памяти не панацея. Современные СУБД спокойно забирают всю базу в память и тоже там выполняют все достаточно быстро. Проблема, когда одно и то же действие выполняется очень часто и сотнями разных пользователей. Как я уже писал узкое место в современных ИС не память, а процессор. И тут индексы единственное что может спасти.
основная проблема в их обновлении при изменении данных от которых они зависят (инкрементальные обновления).Если алгоритм оформлен как reduce() то вообще не проблема — появились новые данные, скармливаем редьюсу, и он досчитывает свой аккумулятор. Проблема, если алгоритм не ложится на reduce(), а представляет, например, SQL — тогда инкрементальные обновления это сложно, и нужна СУБД. Самый типичный отчет — сводная таблица, если в агератах функции типа sum(), эта штука легко досчитывается и даже параллелится, а если там count_distinct(), то досчитывается, но не параллелится, и т.д.
индексы единственное что может спасти.Собственно, да, у меня это кэш, кончится тем, что положу его в какой-нибудь Mongo, или даже Postgres. А вот исходные документы скорее останутся в бинарных файлах, так как СУБД отдают курсоры медленней чем файловая система, хотя вроде у оракла своя FS, не тестил.
Если алгоритм оформлен как reduce() то вообще не проблема — появились новые данные, скармливаем редьюсу, и он досчитывает свой аккумулятор. Проблема, если алгоритм не ложится на reduce(), а представляет, например, SQL — тогда инкрементальные обновления это сложно, и нужна СУБД. Самый типичный отчет — сводная таблица, если в агератах функции типа sum(), эта штука легко досчитывается и даже параллелится, а если там count_distinct(), то досчитывается, но не параллелится, и т.д.
Ну то есть только GROUP SUM по сути. А есть еще GROUP LAST, PARTITION, RECURSION, не говоря уже просто о композициях(JOIN) и арифметических/логических операциях. Задача на самом деле очень нетривиальная, прежде всего архитектурно. У Microsoft с Oracle ее решить не получилось. У нас же на нее лет 7 минимум ушло. А поверьте на одном GROUP SUM в ERP вы далеко не уедете.
А вот исходные документы скорее останутся в бинарных файлах, так как СУБД отдают курсоры медленней чем файловая система
Это экономия на спичках. Сейчас память настолько дешевая, что можно хоть всю базу в shared_buffers держать.
PS
Вы в своем продукте замахнулись на гораздо большее — на универсальную СУБД, у меня задача проще — всего лишь ERP :)
Преимущества — экономим место за счет нормализации
У нормализации основное преимущество не экономия места (оно сейчас относительно дешево), а простота использования. То есть данные лежат в одном месте, вы пишите вычисление и оно гарантировано правильное. Денормализация — производительнее, но вам нужно следить за целостностью всех денормализованных данных, что задача очень часто сильно нетрививиальная (ну и собственно и сводится к задаче материализации функций)
Свертки это все хорошо, но данные «хранимые строго упорядоченно со связями» кто заполнять будет? По факту, вы получите 1С регистры, которые просто сумму по измерениям умеют считать, а как помещать данные в / обновлять эти самые регистры, как там делать ограничения и т.п. — «я стратег, а не тактик», а вы разработчики крутитесь как хотите.
В проекте лежит скрипт обновления балансов
Ну то есть балансы вы предлагаете императивно обновлять, а не функционально. Как например тут: documentation.lsfusion.org/pages/viewpage.action?pageId=2228636
Где вы в ФП задаете остаток, а дальше платформа все сама разруливает.
То есть получается вы обеспечите функциональность в одном аспекте, а в остальных у вас будет такая же императивность как и везде.
receivedQuantity 'Суммарный приход' = GROUP SUM quantity(ReceiptDetail d) BY item(d), stock(receipt(d));Вы что, каждый раз рассчитываете остаток от рождества христова? Не верю. Значит остаток таки храните, а функциональщину обеспечиваете магическим рантаймом. Я о таком тоже думал, но передумал, ибо у меня хранятся все балансы на любой момент времени, и смысл функционалить тогда.
shippedQuantity 'Суммарный расход' = GROUP SUM quantity(ShipmentDetail d) BY item(d), stock(shipment(d));
currentBalance 'Текущий остаток' (Item i, Stock s) = receivedQuantity (i, s) (-) shippedQuantity (i, s);
receivedQuantity 'Суммарный приход' (Item i, Stock s) = GROUP SUM quantity(ReceiptDetail d) IF item(d) = i AND
stock(receipt(d)) = s MATERIALIZED;
А вы балансы императивно по сути заполняете. То есть получается «функциональщина» у вас в каких-то отдельных аспектах только есть.
Я о таком тоже думал, но передумал, ибо у меня хранятся все балансы на любой момент времени
и обновление документа задним числом превращается в боль.
- "невозможно" — очень плохое слово, иногда нужно что-то менять в закрытом периоде;
- мне кажется, что с ростом числа учитываемых величин, ваша система рухнет под хранением промежуточных значений, в той же 1с сделано более разумно — сущности вроде остатков хранятся с какой-то периодичностью, достигается компромисс между компактностью хранения и лёгкостью пересчёта с одной стороны, и простотой расчёта значения на произвольный момент с другой.
ну и сама идея "всё в плоском файле без индексов" мне не близка, поиск движений по какой-то гравицапе, которых было три штуки за всё время, превращается в fullscan, отчёт по складу — аналогично; и т.д., и т.п..
2) Только практика ответит на этот вопрос, нужен пилотный проект и пилотный заказчик :) В свою защиту могу сказать, что 1С намного легче сломать или хакнуть, чем предлагаемую. В моей системе достаточно удалить все промежуточные данные (кэш), и истина будет восстановлена из первичных документов. Большие аудиторы, кстати, так и делают, и налоговая тоже.
3) Если аналгогичный запрос движений по гравицапе уже был — запись будет в кэше, и ее достаточно актуализировать на новых документах. Если нас интересует нестандартная свертка (какой еще не запрашивали), но без сальдо и по конкретному периоду (например обороты за прошлый год) — индексировать плоский файл по timestamp — плевое дело. Если фильтр не по времени — тогда извините, фуллскан.
PS
В целом я не против ни СУБД ни индексов, для прототипа выбрал файл только пожалев свое время, но все же хочется минимизировать мутабельность, то есть неконтролируемая правка любых записей в любой момент. В западных ERP к этому прикладывают специальные усилия, но их недостаточно.
Как я уже писал узкое место в современных ИС не память, а процессорВы уверены..? Зачем тогда bson/varint и т.п.? Вроде как процессор как раз самое быстрое место компьютера, потом ОЗУ, за ним сеть и ПЗУ (они разные бывают, так что х.з. кого на первое место поставить)
Плюс, такая тема как избыточное копирование данных между буферами (которым страдает Линукс и не страдает, вроде как, бсд)
Вы же кстати в курсе что SELECT полон по тьюрингу и на нем можно любые вычисления реализовать.а «добавить» строки в возвращаемый результат — нельзя( в итоге либо встраиваемые процедуры писать (я не уверен, позволяют ли они это — решил вопрос вторым способом), либо на бэке это делать (в этом случае дополнительная задержка ввиду меньшей параллельности выполняемых задач)
Допустим, если процесс организован как {Входы, Процессоры, Выходы},
то стоимость Процесса = Стоимость Входов + (Износ Процессоров + Расход ТМЦ)
а стоимость конкретного Выхода = Стоимость Процесса / (Количество Выхода * Коэффициент распределения)
Если предположить, что Потребность любого Процесса клиента удовлетворяется Процессов сервером, который поставляет некоторое количество своих Выходов во Входы Процесса клиента, то цепочка формирования стоимости становится тривиальной структурой и обрабатывается алгоритм в три строчки кода. При этом учитывая, что каждый Процесс запущен (или спланирован) в контексте спецификации производственного заказа, производственного заказа, заказа, контракта, то легко вычислить все соответствующие показатели, вплоть до перераспределения затрат и т.д…
Хотя все эти расчеты нафиг не уперлись, так как прибыль никак не зависит от наличия и/или точности этих расчетов, а цену определяет рынок и /или административный ресурс.
Это все к тому, что парадигмы программирования и т.д. белиберда к реальным задачам бизнеса отношения не имеет.
— Зацикливание графа сопоставлений при наличии возвратных отходов или реклассификации готового продукта в полуфабрикат.
— Дооценки сырья сильно задним числом (когда продукцию произвели и уже продали).
— Коррекция потребностей, уже принятых в работу отделом закупок (купили, а это никому не нужно).
— Коррекция планов производства внутри декады по причине форсмажора.
— Управление резервами по приоритетам (автоматически снять резерв с менее важного, и отдать более важному).
Это все может рекурсивно затрагивать старые данные, и наш принцип иммутабельность будет нарушаться. В классических ERP проще — я там могу в старых записях дозаполнить новые поля, а с журналом документов мне придется любую коррекцию чего-нибудь (да хоть резерва) оформлять отдельным документом. Я пока масштаб бедствия до конца не осознал, видимо нужно придумать какой-то радикально-сложный пример, может Andrew-BUSINESS имеет что-то готовое, либо придется самому ползти медленно и постепенно.
Мы говорим немного на разных языках, нужно учитывать, что я понимаю не все, что Вы пишете, поэтому и отвечать буду немного наугад. Может, что-то пригодится.
1. Две плоскости учета (натуральный и стоимостный) должны быть разделены. Насколько сильно — зависит от потребностей системы, теоретически их можно разделять максимально.
Стоимостная плоскость — это вычисляемые поля на основе натурального учета. И они всегда вторичны по отношению к нему.
2. В начале процедуры калькуляции программа пробегает по данным количественного учета и составляет граф расчета (последовательность вычислений). Строительство графа заканчивается только тогда, когда все входы в него упираются в уже известные данные.
3. Дальше этот граф «раскручивается» — решается последовательность уравнений, в которых могут быть и циклы (системы уравнений).
Не знаю, это как-то поможет понять как решать те проблемы, которые Вы перечислили?
Все эти «классификации» аспектные, любой набор свойств может классифицирован множественно и одновременно и при том динамически. Так что проблем чего то переклассифицировать стоит в системах с единственной «верной» классификацией (типа буховской) на все времена и случаи.
ДоПереОценка и т.д. — виртуальные операции для некоторой отчетности, по сути нафи никому не нужные.
Отдел закупок не может закупать что благорассудится, они исполнители процессов (хранения, перемещения) сгенерированных системой планирования процессов.
Перераспределение резервов происходит автоматически по заданным Политикам потребления заделов системой планирования процессов.
Управление — реакция на изменения стейта :) происходит автоматически по заданным правилам и при нарушении определенных ограничений.
Все эти документы и т.д. — некое представление Процесса (т.е. структурно все это описано как Процесс), потому ничего отдельно оформлять не надо.
Ух ты, почти все раскритиковал, негоже это воще то.
Что бы не удариться во все тяжкое надо почитать про вещи попроще, типа TPL DataFlow. habr.com/ru/post/138531
остутствие промежуточных остатков позволяет простым запросом высчитывать обороты и остатчки и не заглядывать на какую дату каки промежуточные там данные. представте что у вас промежуточный итог на первое января мне надо посмотреть отчет за период с середины декабря по середину января. Могу я просто послать к БД запрос? в вашем случае врядли.
Кроме того это позволяет легко проводить документ=нты любым числом хоть задним хоть передним без пересчета остатков. прибил записи связаные с документом и добавил новые и все.
Я к тому что при нынешней копеечной стоимости железа так усложнять хранилище это экономия на спичках. И никакие nosql пока не переплюнут реляционные БД для учетных систем где данные реляционные по своей природе.
Кроме того это позволяет легко проводить документ=нты любым числом хоть задним хоть передним без пересчета остатков. прибил записи связаные с документом и добавил новые и все.Нельзя этого делать. Как только вы добавите планирование, вы поймете почему. Потребности нельзя вычислять на лету, их нужно фиксировать с определенной периодичностью (например не чаще раза в месяц). Иначе ваш отдел закупок с ума сойдет от такого динамизма.
Вы изобретаете каппа архитектуру. Рекомендую поликбезить сабж.
Спасибо, что оперативно выпустили эту статью, ответив таким образом на мой комментарий.
К сожалению, я понимаю не все технические термины, поэтому могу смотреть на разработку только с точки зрения бизнеса, и идеи мне нравятся.
Буду стараться следить дальше.
Если вдруг нужна будет помощь по методологической части (резервы, себестоимость, цепи поставок) — можете обращаться.
1) проводка-проводка
2) проводка-остаток
Если мы выбираем первый случай, тогда мы можем расчет остатка оформить вычисляемой кэшируемой сверткой, в чисто-функциональном ключе. Я сознательно выбрал второй вариант «проводка — остаток», таким образом остаток нам нужен в системе как самостоятельная сущность, с уникальным ID. Какая может быть функциональщина при организации связей между сущностями?
Любая функция (даже чистая) возвращает какие-то данные, в моем случае — новый документ типа «баланс», тогда как императивный подход подразумевает изменение старой записи регистра «баланс». Чувствуете разницу? Таким образом моя система намного ближе к принципам ФП, чем упомянутая 1С. Про вашу систему пока ничего определенного сказать не могу, решение с материализацией на лету — довольно сильное, но подходы к хранению данных принципиально другие, значит и никакого спора быть не может.
Любая функция (даже чистая) возвращает какие-то данные, в моем случае — новый документ типа «баланс».
Вообще чистая функция (а ФП это именно про чистые функции, потому как не чистые функции это просто процедуры, которые умеют записывать результат в переменные) никак не может возвращать новый документ. Потому как при повторном вызове она получается вернет другой документ, что противоречит ее чистоте. Это никак не ФП.
Чувствуете разницу?
Нет, разница чисто в особенностях реализации. По сути вы просто создаете транзакционный лог. Я бы на вашем месте это скорее блокчейн СУБД, а не функциональной СУБД называл бы. Ведь именно блокчейн это про аудируемость и т.п.
Функциональная функция (простите за тафталогизм) всегда возврщает новые данные, поэтому ФП так критикуем и непопулярен, ведь аллокации памяти это дорого. А если фунция ничего не возвращает, и не меняет старых данных, то это не функция вообще, а черная дыра :)
По сути вы просто создаете транзакционный лог. Я бы на вашем месте это скорее блокчейн СУБД, а не функциональной СУБД называл бы. Ведь именно блокчейн это про аудируемость и т.п.Именно! Вы совершенно верно схватили суть! На такую схему навернуть блокчейн — пять минут программирования, просто вычислить хэш и положить в дерево Меркла. А вот если у нас есть мутабельный регистр «Остатки», то как его надежно защитить от подделок и ошибок? Никак.
Функциональная функция (простите за тафталогизм) всегда возврщает новые данные, поэтому ФП так критикуем и непопулярен, ведь аллокации памяти это дорого.
С чего вы взяли? ФП вообще перпендикулярен работе с памятью (то есть можно по разному делать). И как раз в ФП экономить память (и ее аллокацию) куда проще чем в императивном: а) из-за ленивых вычислений, б) потому что вы можете переиспользовать ссылки на объекты не боясь что их кто-то изменит (если у вас вся архитектура на immutable объектах / чистых функциях, соответственно immutable объекты создаются только в императивной части — процедурах). И кстати поэтому ФП очень популярен именно в системном программировании, потому как на сложных архитектурах при использовании ФП с многопоточностью и памятью (кэшированием) все становится значительно проще.
Именно! Вы совершенно верно схватили суть! На такую схему навернуть блокчейн — пять минут программирования, просто вычислить хэш и положить в дерево Меркла. А вот если у нас есть мутабельный регистр «Остатки», то как его надежно защитить от подделок и ошибок? Никак.
Ну насколько хорош или плох блокчейн это отдельная тема. И находится она в основном в политическо/экономической плоскости, так что к данной статье имеет мало отношения :)
На пути к функциональной СУБД и NoSQL ERP: хранение остатков и расчет себестоимости