Комментарии 34
Простое пишется легко на чём угодно. Сложное пишется сложно. Если упрощаем второе, то сложность кто-то как-то должен сократить. Вот это и должны быть вы с тем самым большим количеством кода. Но у вас, скорее всего, времени жизни не хватит.
Смысл любого нового языка сегодня один — он нравится автору. Всё остальное — от лукавого.
Да, ещё есть вариант «попроще» — включить в массовый язык какой-то другой, по возможности тоже массовый, язык. Сложность здесь ограничивается написанием компилятора для этого тяни-толкая. Такой вариант вы сможете реализовать. Но, похоже, выбран вариант «язык, который нравится мне», что означает — его никто не знает. Соответственно, перспектив без поддержки гуглов — около нуля, потому что без рекламы новое не взлетит. Ну и функционал будет сильно урезанный, ибо время жизни, а потому — ну кому надо учить новое, да ещё и урезанное?
В общем — поболтать о принципах программирования, это можно, но свой новый язык — оставьте надежду. Лучше раньше, потому что позже будет тяжелее. Хотя можно поупираться, это даст возможность наиграться и самому понять, что игра проиграна, но в обмен на много убитого времени.
Мечтателям и творцам сегодня одна дорога — в рабы к гуглам. Потому что сами они договориться тупо не хотят, ведь «мне нравится» важнее любого здравого смысла. Но может кто-то уже вырос из этих детских штанишек и готов к компромиссам? Не с гуглами, а с такими же людьми. Иначе кроме рабства так ничего и не будет.
Вы упрётесь в количество кода, который нужно написать.
Простое пишется легко на чём угодно. Сложное пишется сложно. Если упрощаем второе, то сложность кто-то как-то должен сократить. Вот это и должны быть вы с тем самым большим количеством кода. Но у вас, скорее всего, времени жизни не хватит.
Да, согласен. Полноценный язык я сделать сам не смогу. Мне были интересны принципы построения такого гибридного языка. Я потратил на их исследования довольно много времени. И решил поделиться результатами.
Да, ещё есть вариант «попроще» — включить в массовый язык какой-то другой, по возможности тоже массовый, язык. Сложность здесь ограничивается написанием компилятора для этого тяни-толкая. Такой вариант вы сможете реализовать. Но, похоже, выбран вариант «язык, который нравится мне», что означает — его никто не знает.Этот вопрос открыт. Возможные варианты — это полноценный язык, компилятор в байт-код для JVM или другой виртуальной машины, фреймворк по типу GraphQL. Вариант с фреймворком был бы идеальным с практической точки зрения, но, к сожалению, придется пожертвовать некоторой частью функционала. В реальности же у меня сейчас есть только пруф оф концепт версия интерпретатора, на которой я тестировал свои идеи. Я планирую написать об этом подробно, но немного позже.
Мечтателям и творцам сегодня одна дорога — в рабы к гуглам.
… готов к компромиссам? Не с гуглами, а с такими же людьми.
Не ясно, так одна дорога в рабы или есть альтернативная дорога компромиссов с людьми? Если первое, то как же тогда родится что-то объективно не соответствующее специфике текущих бизнесов? Если второе, так вроде автор и не против критики. Даже как раз ее запрашивает.
Вообще, идея оочень актуальная. Современные клиенты сейчас переворачивают традиционные бизнесы с ног на голову. Требуют невообразимое — учитывать свои персональные хотелки! Представьте, под клиента в таком смысле последний раз подстраивались сотни лет назад ублажая дворян. Но то были 0,01% избранных. А сейчас нужно облизать каждого владельца лопаты — жуткие 20% населения земли! Бизнесам одним не справиться, и они лезут в экосистемы. Хуже того, в суперапы. Лезут не образно, а всем своим бизнес-кодом. И это совершенно новое. Это то, что убъет одни языки и родит новые ныне неведомые. Одно только понятно — они будут значительно декларативными, ибо в этом и суть захода: бизнесы теперь декларируются у экосистем. Вы поймите, ВСЯ старая ИТ-жизнь — коту под хвост!
Если кто-нибудь думает, что жизнь устаканилась и власть гуглов хоть сколько-нибудь перманентна, то, ну что же, для них видимо есть важные новости. Все только начинается.
Сегодня — нет. Но завтра, возможно, будет альтернатива.
>> Если первое, то как же тогда родится что-то объективно не соответствующее специфике текущих бизнесов?
Ну очевидно же — вопреки соответствующей специфике текущих бизнесов.
>> Современные клиенты сейчас переворачивают традиционные бизнесы с ног на голову. Требуют невообразимое — учитывать свои персональные хотелки!
А чего такого невообразимого в простом человеческом желании комфорта? И где есть такие бизнесы, которые реально учитывают персональные хотелки? Пустозвонную декларации про «персональный подход» не предлагать. Так же как и включение в приложения пункта меню «настройки».
>> Это то, что убъет одни языки и родит новые ныне неведомые.
Языки программирования не имеют отношения к бизнесу. Бизнес использует результат работы программиста, который, в свою очередь, использует языки программирования. Для бизнеса язык — как один из тысячи болтов в купленной машине, плевать бизнесу на этот болт, если сломается — отдаст в сервис всю машину.
>> Вы поймите, ВСЯ старая ИТ-жизнь — коту под хвост!
Опять мимо. Жизнь есть штука сложная, составленная из миллионов компонентов. Миллион компонентов никуда не денется. Хотя нектороые отомрут, да.
Сегодня — нет. Но завтра, возможно, будет альтернатива.
Ок, по факту так.
Ну очевидно же — вопреки соответствующей специфике текущих бизнесов.
Да, тут можно вспомнить идею гугла "каждый пятый день кодте что хотите". Ну не знаю. Условно, день в неделю — ничего.
А чего такого невообразимого в простом человеческом желании комфорта?
Это вы у бизнеса спросите, что такого сложного учитывать простые ПЕРСОНАЛЬНЫЕ желания людей. ) На самом деле реально сложно, но стало проще (см. про экосистемы).
И где есть такие бизнесы, которые реально учитывают персональные хотелки? Пустозвонную декларации про «персональный подход» не предлагать. Так же как и включение в приложения пункта меню «настройки».
А их пока и нет. Но появление экосистем ситуацию меняет, т.к. хотя бы ВОЗМОЖНОСТЬ персонализации с ходу есть — банки, чаты, курьеры и соц.сети знают нас лично. И теперь лишь вопрос времени — обогащение этой инфы "покупательскими" подробностями. Например, Сбер выдав мне кредит на машину может перепродать инфу о ней бизнесам своей экосистемы. Если среди них окажется автосервис, я могу рассчитывать получить соответствующее умное предложение.
И, соответственно, ИТ автосервиса теперь должен уметь отслеживать и "продажно" реагировать на эти тригеры. Думается им не обойтись без освоения Semantic Tech в целом и Data-Centric в частности — я на это ставлю.
Языки программирования не имеют отношения к бизнесу. Бизнес использует результат работы программиста, который, в свою очередь, использует языки программирования.
Да понятно, конечно связь не прямая. Но если кодерам раз за разом будут ставиться принципиально новые задачи и инструменты им придется выбирать раз за разом новые. Вот так бизнес и убьет. Ну ладно, не бизнес, а принципиально новая бизнес-ситуация.
Опять мимо. Жизнь есть штука сложная, составленная из миллионов компонентов. Миллион компонентов никуда не денется. Хотя нектороые отомрут, да.
Верно, в 99% случаев изменения бизнес-ландшафта не могут подставить миллионы компонентов. Но нам повезло — речь идет о 1%. Смена парадигм. Она не каждый год и даже не каждое столетие происходит. Угроза нависла именно над "миллионами".
И не стоит обращаться к личному опыту — это вот только год как пошло. Пока, считай, еще никого и не коснулось.
А после этого уже планирую подробно рассказать о своем языке. Сначала об основных его понятиях — способах определения фактов и понятий, наследовании, правилах. Затем о связях с логическим программированием — логических переменных, предположениях о закрытости/открытости мира, отрицании, элементах логики высших порядков. А также о заимствованиях из мира SQL — вложенных определений понятий, агрегировании. Это займет 3 публикации.
Дальше будет рассказ, как объединить логический язык моделирования с ООП и функциональным программированием. Будет обзор функционально-логических языков — Curry и OZ, подходов к онтологически-ориентированному программированию. Планирую рассказать, как можно совместить конструкции языка моделирования с ООП моделью на семантическом уровне. Как решена проблема совмещения поиска с возвратом с императивным и мультипоточным стилями программирования. Как можно организовать области видимости понятий и фактов. Как можно реализовать процедуру логического вывода.
После этого, хочу рассмотреть пару примеров применения языка, приближенных к реальности. А в конце — основные варианты реализации языка.
Многие публикации будут связаны с вопросами и проблемами компьютерной логики, причем с теоретическими вопросами.
Иными словами, разбивая задачу на несколько частей (подзадач), каждую из них вы решаете на том языке, который для этого подходит наилучшим образом. И все это в рамках одной программы.
Механическое объединение нескольких языков не позволит этого сделать. Оно усложнит код, его понимание, разработку, отладку. Оно может быть полезен в некоторых задачах, например, при поддержке legacy кода, но так и не смогло завоевать популярности.
Вы понимаете, что ни одна серьезная бизнеслогика не будет строится на непойми каком самопальном языке, где непонятно в чем причина ошибки — то ли разработчик накосячил, то ли компилятор кривой?
Кроме того, в серьезных приложениях всегда приходится искать баланс между простотой кода, его эффективностью (скоростью работы) и загрузкой машины.
SQL я могу вообще прямо в коде использовать на любом из языков ILE. Но это далеко не всегда эффективно. Часто красивый SQL запрос или слишком грузит машину (и не проходит через нагрузочное тестирование) или работает слишком медленно (и его приходится декомпозировать или вообще уходить на другую логику).
Кроме того, сложные задачи часто не ограничиваются только бизнеслогикой, нужна еще обвязка — распараллеливание обработки на несколько заданий с организацией батчмашины, где необходим контроль за работой заданий-обработчиков со стороны мастер-задачи, организация межпроцессного обмена данными и т.п. И там приходится использовать несколько языков — ядро батчмашины пишется на С т.к. там в основном системные вещи — сокеты/пайпы/DTAQ, запуск/остановка дочерних заданий, контроль их состояния. А логическая часть (отбор данных в мастере, обработка в дочках) уже на других языках — там логика.
Это все из личной практики решения реальных задач.
Ну и насчет популярности — можете назвать другие, кроме ILE от IBM, попытки реализации подобного подхода? Я вот не сталкивался с таким.
Т.е. Вы хотите сказать, что сможете поднять такой язык, довести его до уровня стандартизации, поддерживать его?
Нет, самостоятельно я конечно сделать этого не смогу. Но могу поделиться своими идеями с IT сообществом.
Кроме того, в серьезных приложениях всегда приходится искать баланс между простотой кода, его эффективностью (скоростью работы) и загрузкой машины.
Кроме того, сложные задачи часто не ограничиваются только бизнеслогикой, нужна еще обвязка
Согласен, но именно в этом я вижу преимущества гибридного подхода — каждую задачу можно решить с помощью наиболее подходящих инструментов. Основную часть бизнес логики можно реализовать в логическом стиле, там где нужна тонкая оптимизация — разбавить логический стиль функциональным или императивным. А вся обвязка будет реализована так же как и раньше — в функциональном или ООП стиле.
Ну и насчет популярности — можете назвать другие, кроме ILE от IBM, попытки реализации подобного подхода? Я вот не сталкивался с таким.
Я тоже не сталкивался. Я имел в виду, что ILE технология не является мейнстримом, пока что это скорее нишевое решение для специфических задач. Думаю, что это потому, что писать код одновременно на нескольких языках неудобно, а взаимодействие таких частей кода будет довольно ограниченным, например, только вызовами процедур. Гибридный подход позволяет соединить компоненты гораздо более тесно.
Согласен, но именно в этом я вижу преимущества гибридного подхода — каждую задачу можно решить с помощью наиболее подходящих инструментов.
Что я и делаю в рамках ILE :-)
Думаю, что это потому, что писать код одновременно на нескольких языках неудобно
Вот уж никаких проблем с этим. Это куда проще, чем городить монструозный гибридный язык.
Я имел в виду, что ILE технология не является мейнстримом, пока что это скорее нишевое решение для специфических задач.
Просто оно реализовано в рамках платформы AS/400, которая сама по себе является нишевой.
И да. Любое решение существует для специфических задач. И лучше всего им соответсвует. А за любую универсальность придется платить. Снижением эффективности, например.
взаимодействие таких частей кода будет довольно ограниченным, например, только вызовами процедур
А вот это уже вопрос архитектуры. При правильном разделении подзадач этого более чем достаточно.
Гибридный подход позволяет соединить компоненты гораздо более тесно.
Вы уверены, что монолит, представляющий из себя спагетти из разных подходов, будет удобен в дальнейшей поддержке и, не дай бог, модификации?
Во что обойдется, например, расширение логики в виде добавления нескольких полей в таблицу? Или изменение условий отбора объектов для последующей разработки?
Модульность тем и хороша, что логика модуля заключена в нем одном. Изменение логики одного модуля при условии сохранения его интерфейса не потребует переработки всего остального кода.
На личном опыте — в одной из систем перешел со старенькой ParadoxEngine на более современный FireBird Server только переписыванием одного модуля работы с БД (<20% кода). А это принципиально разные БД.
Просто за счет правильной организации структуры модулей и их взаимодействия.
Это куда проще, чем городить монструозный гибридный язык.
Вы уверены, что монолит, представляющий из себя спагетти из разных подходов, будет удобен в дальнейшей поддержке и, не дай бог, модификации?
Во что обойдется, например, расширение логики в виде добавления нескольких полей в таблицу? Или изменение условий отбора объектов для последующей разработки?
Я надеюсь, что он не будет монструозным. По крайней мере, цель как раз в том, чтобы упростить работу с бизнес-логикой. Чтобы ее можно было выразить более кратко и четко по сравнению с традиционным ООП подходом, в том числе облегчить ее модификацию.
Любая бизнеслогика обернута системными вещами той или иной сложности. Выше приводил пример с параллельной обработкой больших объемов данных в заданном временном окне. Там всегда есть время, в которое нужно уложиться (временное окно) и предельная загрузка сервера в этом временном окне — мы не можем выходить за нее с учетом того, что кроме нашей задачи там крутится еще несколько тысяч фоновых процессов.
Т.е. есть модуль логики и модуль обвязки (например, батчмашина с контролем фоновых обработчиков, транспортом раздачи заданий и т.п.)
И язык должен позволять не только изощренную логику реализовать, причем, сделать это с минимальными затратами времени и мощности процессора, но еще и предоставлять возможность работать на достаточно низком уровне системных API. Опять же, с минимальными затратами времени и процессора.
В случае ILE ядро батчмашины пишется на С/С++ (пайпы, контроль фоновых заданий и т.п.) Логика — на RPG (чаще на SQLRPG — RPG код со встроенными в него SQL операторами).
Иногда приходится отказываться от применения SQL поскольку он неэффективен. Простейший пример — есть выборка где присутсвует
where field in (val1, val2, val3, ...)
причем, список значений и их количество при каждом вызове разные. Т.е. нам надо каждый раз диамически строить SQL строку. И каждый раз при каждом вызове будет вызываться построение плана, оптимизация и только потом выполнение. Что в рамках данного куска кода будет занимать изрядную долю времени и процентов 30 процессорных ресурсов (от общего для данной процедуры).
Отказ от SQL в пользу «нативного» RPG (там есть возможность прямой работы с таблицами) не только ускорила выполнение этой процедуры процентов на 10, но и снизила процентов на 30 загрузку процессора.
Да, это не так концептуально и красиво. Но это эффективно. А когда в рамках только одной задачи вызов этой процедуры происходит несколько десятков миллионов раз, это весьма существенно.
История вполне реальная.
Но если бы приложение загружало бы одни сущности из базы данных, другие из XML документов, третьи из запроса к другому сервису в JSON формате, преобразовывало их в свой внутренний формат, затем фильтровало и склеивало вместе, то в этом случае мой подход помог бы описать всю эту бизнес логику более кратко и понятно.
В данном конкретном случае гибридный язык, над которым я работаю, будет скорей всего избыточным.
Скорее, недостаточным. Поскольку его «гибридность» весьма ограничена, а «данный конкретный случай» для нас скорее типичен чем исключителен. Задач, где объем обрабатываемых данных велик и требуется распараллеливание обработки у нас вагон и маленькая тележка.
Но если бы приложение загружало бы одни сущности из базы данных, другие из XML документов, третьи из запроса к другому сервису в JSON формате, преобразовывало их в свой внутренний формат, затем фильтровало и склеивало вместе, то в этом случае мой подход помог бы описать всю эту бизнес логику более кратко и понятно.
И что мешает это сделать средствами того же SQL?
--These examples operate on the following JSON document:
--{
--"id" : 901,
--"name" : { "first":"John", "last":"Doe" },
--"phones": [ { "type":"home", "number":"555-3762"},
--{ "type":"work", "number":"555-8792"}]
--}
--List the employee id, first name, last name, and first phone type and number:
SELECT U."id", U."first name",U."last name",U."phone type",U."phone number"
FROM EMPLOYEE_TABLE E
JSON_TABLE(E.jsondoc,
’lax $’
COLUMNS( "id" INTEGER,
"first name" VARCHAR(20) PATH ’lax $.name.first’,
"last name" VARCHAR(20) PATH ’lax $.name.last’,
"phone type" VARCHAR(20) PATH ’lax $.phones[0].type’,
"phone number" VARCHAR(20) PATH ’lax $.phones[0].number’)
) AS U
--Returns:
--id first name last name phone type phone number
----- ---------- --------- ---------- ------------
--901 John Doe home 555-3762
--List the employee id, first name, last name, and all available telephone types and numbers:
SELECT U."id", U."first name",U."last name",U."phone type",U."number" AS "phone number"
FROM EMPLOYEE_TABLE E
JSON_TABLE(E.jsondoc,
’lax $’
COLUMNS( "id" INTEGER,
"first name" VARCHAR(20) PATH ’lax $.name.first’,
"last name" VARCHAR(20) PATH ’lax $.name.last’,
NESTED PATH ’lax $.phones[*]’
COLUMNS (
"phone type" VARCHAR(20) PATH ’lax $.type’,
"number" VARCHAR(20) )
)
) AS U
--Returns:
--id first name last name phone type phone number
----- ---------- --------- ---------- ------------
--901 John Doe home 555-3762
--901 John Doe work 555-8792
И для XML
--List as a table result the purchase order items for orders with a status of 'NEW'.
SELECT U."PO ID", U."Part #", U."Product Name",
U."Quantity", U."Price", U."Order Date"
FROM PURCHASEORDER P,
XMLTABLE(XMLNAMESPACES(’http://podemo.org’ AS "pod"),
’$po/PurchaseOrder/itemlist/item’ PASSING P.PORDER AS "po"
COLUMNS "PO ID" INTEGER PATH ’../../@POid’,
"Part #" CHAR(6) PATH ’product/@pid’,
"Product Name" CHAR(50) PATH ’product/pod:name’,
"Quantity" INTEGER PATH ’quantity’,
"Price" DECIMAL(9,2) PATH ’product/pod:price’,
"Order Date" TIMESTAMP PATH ’../../dateTime’
) AS U
WHERE P.STATUS = ’NEW’
Так что опять ничего нового.
Правда, с точки зрения эффективности, есть более быстрые и менее процессорнозатратные способы. Есть YAJL (весьма быстрый и экономный по процессорному времени) для JSON, есть встроенные в RPG XML-INTO и XML-SAX
В одной из моих задач (как раз сейчас в работе) требуется парсинг XML весьма сложной структуры (вложенные друг в друга массивы, русские тэги, куча необязательных элементов...)
А потом еще достаточно хитрый алгоритм раскладки всего этого по 9-ти таблицам с анализом того, что там уже есть, сравнением, определением необходимых изменений, переносом старых версий данных в архивные таблицы (для возможного последующего отката).
И да, данные поступают из очереди (MQ). Т.е. есть некоторый процесс-монитор очереди, который определяет появление в очереди нового сообщения, определяет по заголовку его тип, по типу находит в настроечной таблице соответсвующий обработчик и передает ему сообщение на обработку.
Статус обработки сообщения отправляется обратно в очередь отправителю.
Тоже вполне типовая для нас задача.
В данном случае XML-INTO не подходит — он работает с простыми структурами (зато там ничего не надо делать — объявляешь DS — структура из нескольких полей в RPG — соответствующую XML и вызываешь XML-INTO — на выходе сразу получаешь заполненные значениями поля). А XML-SAX работает замечательно — быстро и разбирает XML любой сложности и степени вложенности.
В одной из моих задач (как раз сейчас в работе) требуется парсинг XML весьма сложной структуры (вложенные друг в друга массивы, русские тэги, куча необязательных элементов...)
А потом еще достаточно хитрый алгоритм раскладки всего этого по 9-ти таблицам с анализом того, что там уже есть, сравнением, определением необходимых изменений, переносом старых версий данных в архивные таблицы (для возможного последующего отката).
Вот это будет отличным примером!
Предположим, что у нас есть документ со списком товаров, которые описываются набором атрибутов. Один из атрибутов — это информация о наличии товара у поставщиков, представляющая собой массив. Элементом массива будет объект, включающий айди поставщика, количество товара и цену. А в некоторых случаях вместо количества — список доступных размеров одежды или обуви, внутри которого уже количество товара:
<products>
<product id="...">
<name>...</name>
<description>...</description>
<providers>
<provider id="...">
<price>
<value>...</value>
<currency>...</currency>
</price>
<amount>...</amount>
</provider>
<provider id="...">
<price>...</price>
<sizes>
<size>
<value>...</value>
<amount>...</amount>
</size>
</sizes>
</provider>
....
Предположим, что необходимо извлечь данные о количестве товара у поставщиков, сравнить их с данными в БД и синхронизировать изменения.
Для начала опишем структуру документа в вие набора понятий. Предположим, что данные из файла представлены понятием xml_products:
concept newProductProviders (id=p.id, providers=p.providers) from xml_products p;
concept newProductAmount
(productId=pv.id, providerId=pd.id, amount=pv.amount)
from newProductProviders pd, {p.providers} as pv
where defined(pv.amount);
concept newProductSizeAmount
(productId=pv.id, providerId=pd.id, size=s.value, amount=s.amount)
from newProductProviders pd, {p.providers} as pv, {pv.sizes} as s
where defined(pv.sizes);
С другой стороны у нас есть таблица в БД, в которой хранятся текущие размеры товаров и их количество. Представим ее содержимое в виде понятия:
concept existingProductSizeAmount
(id, productId, providerId, size, amount)
by DBTable(connProvider, "product_size_amount");
Теперь можно сравнить данные из документа и БД:
//соединяем оба множества с помощью left join
concept productComparison (new=n, old=o)
from newProductSizeAmount n, optional (existingProductSizeAmount e where e.productId=n.productId and e.providerId=n.providerId and e.size=n.size) o;
//объекты для вставки в БД
concept productSizeAmountToInsert is c.new
with lastUpdated=CUR_DATE()
from productComparison c where not defined(c.old);
//объекты для обновления в БД
concept productSizeAmountToUpdate is c.old
with lastUpdated=CUR_DATE(), size=c.new.size
from productComparison c where defined(c.old);
//объекты для удаления из БД
concept productSizeAmountToDelete is existingProductSizeAmount old
where old.lastUpdated<CUR_DATE();
Это была декларативная часть. А теперь императивная часть
//загрузить данные из XML файла
import xml_products from XML("products_amount.xml", "products");
//синхронизировать их с БД, например, с помощью того же понятия, которое загружало данные
//можно даже понятия передать в качестве аргументов, пусть они сами найдут нужные значения и/или сгененрируют SQL код на основе описаний понятий
existingProductSizeAmount.insert(productSizeAmountToInsert);
existingProductSizeAmount.update(productSizeAmountToUpdate);
existingProductSizeAmount.delete(productSizeAmountToDelete);
Таким должен быть код обработчика сообщения.
Я пока не готов подробно обсуждать эффективные алгоритмы всех этих преобразований. Я планирую позаимствовать их из таких фреймворков для in-memory data processing как Spark или BigQuery. Очевидно, что по эффективности они будут уступать SAX парсерам и ручной склейке данных. Но зато код гораздо короче, понятней и быстрее в разработке и поддержке.
Я тоже неоднократно сталкивался с подобными задачами, но если честно, решение их традиционным императивным способом всегда нагоняло на меня тоску.
Вот пример (он упрощенный сильно)
- <PPT_CATALOG>
<FileDate>16.10.2017</FileDate>
<LastMessage>0</LastMessage>
- <СписокРешений xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
<ВерсияФормата>1.0</ВерсияФормата>
<ДатаСписка>2017-10-16</ДатаСписка>
- <СписокАктуальныхРешений>
- <Решение>
- <ТипРешения>
<Идентификатор>3</Идентификатор>
<Наименование>Решение МВК</Наименование>
</ТипРешения>
<НомерРешения>7-дсп</НомерРешения>
<ДатаРешения>2017-03-14</ДатаРешения>
<Орган>Межведомственная комиссия по противодействию финансированию терроризма</Орган>
- <ВидРешения>
<Идентификатор>1</Идентификатор>
<Наименование>Решение на приостановление (заморозка)</Наименование>
</ВидРешения>
- <СписокСубъектов>
- <Субъект>
<ИдСубъекта>8349984888</ИдСубъекта>
- <ТипСубъекта>
<Идентификатор>2</Идентификатор>
<Наименование>Физическое лицо</Наименование>
</ТипСубъекта>
- <ФЛ>
<ФИО>МОЛЧАНОВ МУРАД АНДРЕЕВИЧ</ФИО>
<Фамилия>МОЛЧАНОВ</Фамилия>
<Имя>МУРАД</Имя>
<Отчество>АНДРЕЕВИЧ</Отчество>
<ФИОЛат>MOLCHANOV MURAD ANDREEVICH</ФИОЛат>
<ДатаРождения>1993-08-15</ДатаРождения>
<ГодРождения>1993</ГодРождения>
<МестоРождения>Г. АДЫГЕЙСК ТЕУЧЕЖСКОГО РАЙОНА РЕСПУБЛИКИ АДЫГЕЯ</МестоРождения>
<ИНН>010701070387</ИНН>
- <СписокДокументов>
- <Документ>
- <ТипДокумента>
<Идентификатор>1631726</Идентификатор>
<Наименование>ПАСПОРТ РФ</Наименование>
</ТипДокумента>
<Серия>7907</Серия>
<Номер>503236</Номер>
<ОрганВыдачи>ВЫДАН ТП ОФМС ПО РЕСПУБЛИКЕ АДЫГЕЯ В ТЕУЧЕЖСКОМ РАЙОНЕ РЕСПУБЛИКИ АДЫГЕЯ</ОрганВыдачи>
<ДатаВыдачи>2007-09-11</ДатаВыдачи>
</Документ>
</СписокДокументов>
</ФЛ>
- <СписокАдресов>
- <Адрес>
- <ТипАдреса>
<Идентификатор>6</Идентификатор>
<Наименование>Гражданство</Наименование>
</ТипАдреса>
<ТекстАдреса>РОССИЙСКАЯ ФЕДЕРАЦИЯ</ТекстАдреса>
</Адрес>
- <Адрес>
- <ТипАдреса>
<Идентификатор>2</Идентификатор>
<Наименование>Адрес места регистрации</Наименование>
</ТипАдреса>
<ТекстАдреса>РЕСП АДЫГЕЯ, Г АДЫГЕЙСК, УЛ ЛЕНИНА, Д 24, КВ 14</ТекстАдреса>
- <Страна>
<Наименование>РОССИЙСКАЯ ФЕДЕРАЦИЯ</Наименование>
<Код>643</Код>
</Страна>
<ОКАТО>79403000000</ОКАТО>
</Адрес>
- <Адрес>
- <ТипАдреса>
<Идентификатор>5</Идентификатор>
<Наименование>Адрес местонахождения</Наименование>
</ТипАдреса>
<ТекстАдреса>РЕСП АДЫГЕЯ, Г АДЫГЕЙСК, УЛ ЛЕНИНА, Д 24, КВ 14</ТекстАдреса>
- <Страна>
<Наименование>РОССИЙСКАЯ ФЕДЕРАЦИЯ</Наименование>
<Код>643</Код>
</Страна>
<ОКАТО>79403000000</ОКАТО>
</Адрес>
</СписокАдресов>
<РешениеПоСубъекту>Осуществить замораживание (блокирование) денежных средств и иного имущества, принадлежащих указанному лицу, гуманитарное пособие не назначать.</РешениеПоСубъекту>
</Субъект>
</СписокСубъектов>
</Решение>
</СписокАктуальныхРешений>
</СписокРешений>
</PPT_CATALOG>
Это неполный пример, полного нет под рукой. Там еще всякие «другие наименования» могут быть и еще что-то…
Или вот такое
- <TERRORISTS_CATALOG>
<FileName>01.01.2020</FileName>
<NUM>362ПЭ</NUM>
<DATE>01.01.2020</DATE>
<ID>3758452944></ID>
<LastMessage>0</LastMessage>
- <TERRORISTS>
<TERRORISTS_NAME><![CDATA[СУЛТАНОВ ЛЕЧИ РАСУЛОВИЧ* (Mounir el Moutassadeq;Pahlawan Shamsuddin)]]></TERRORISTS_NAME>
<ID_NEW>5639</ID_NEW>
<PERSON_TYPE>4</PERSON_TYPE>
<IS_TERRORIST>1</IS_TERRORIST>
<INN />
<BIRTH_DATE><![CDATA[20.08.1981]]></BIRTH_DATE>
<DESCRIPTION><![CDATA[В РОЗЫСКЕ]]></DESCRIPTION>
<ADDRESS><![CDATA[IN PRISON IN GERMANY; IN PRISON IN GERMANY]]></ADDRESS>
<TERRORISTS_RESOLUTION><![CDATA[]]></TERRORISTS_RESOLUTION>
<BIRTH_PLACE><![CDATA[СТ. ОРДЖОНИКИДЗЕВСКАЯ СУНЖЕНСКОГО РАЙОНА ЧИАССР]]></BIRTH_PLACE>
<PASSPORT><![CDATA[ПАСПОРТ РФ: 8303 596899 ВЫДАН БАКСАН РОВД 27.01.2004,ПАСПОРТ РФ: 8309 964133 03.08.2009,ПАСПОРТ РФ: 8314 255832 ВЫДАН ОТДЕЛОМ УФМС РОССИИ ПО КАБАРДИНО-БАЛКАРСКОЙ РЕСПУБЛИКЕ В БАКСАНСКОМ РАЙОНЕ 06.03.2015,]]></PASSPORT>
</TERRORISTS>
</TERRORISTS_CATALOG>
Тут в одном теге несколько имен (осноовное и дополнительные), несколько паспортов, которые надо по шаблону паспорта РФ проверить и если попадает, то распарсить на номер, кем и когда выдан и т.п.
Там еще парсинг адресов может быть с выделение города, улицы, дома, квартиры и т.п. со всякими возможными вариациями.
И раскладывается все это по нескольким таблицам — отдельно данные, отдельно имена, отдельно документы, для ФЛ один набор, для ЮЛ другой и прочее и прочее…
Раскладка тоже со сравнениями что изменилось, что добавилось, что удалилось по каждой таблице. И при этом все что меняем — старую версию в архив т.к. возможна операция отката к предыдущему состоянию.
Ну и скорость должна быть. И процессор не грузить сверх меры… И еще куча условий всяких.
И да. Если ваша деклартивная версия 3000 тких записей будет грузить секунду, а моя императивная полсекунды, то на прод пойдет моя. Без разговоров. Это даже не обсуждается. А тем паче, если загрузка процессора по PEX у моей ниже будет.
Понимаете, мы решаем задачи бизнеса. А задача бизнеса — это не красивый код. А эффективная работа. На красоту кода им плевать.
Понятность и легкость сопровождения — это комментарии в коде + документация в ТЗ. Что на входе, что на выходе, общий алгоритм разработки. А дальше уже толковый разработчик поймет что к чему. А бестолковых не держим.
И да. Если ваша деклартивная версия 3000 тких записей будет грузить секунду, а моя императивная полсекунды, то на прод пойдет моя. Без разговоров. Это даже не обсуждается. А тем паче, если загрузка процессора по PEX у моей ниже будет.
Понимаете, мы решаем задачи бизнеса. А задача бизнеса — это не красивый код. А эффективная работа. На красоту кода им плевать.
Тут я с вами не соглашусь. Скорость разработки и легкость поддержки тоже важна для бизнеса. Часто бывает, что выгоднее потратиться на вычислительные ресурсы, чем увеличивать штат разработчиков.
Спасибо за комментарии! Эта дискуссия была для меня полезной.
Часто бывает, что выгоднее потратиться на вычислительные ресурсы, чем увеличивать штат разработчиков.
Вот предствьте ситуацию. Кластер из трех серверов. На каждом 16 процессоров PowerS928 (12 ядер SMT8 на процессор). Больше в сервер не лезет. Это предел. Памяти по 2.5Тб на сервер, можно увеличить. Стоимость нового, более мощного, сервера пара-тройка сотен тысяч долларов.
В пиковые периоды нагрузка на сервер может превышать 90%.
Перегрузка сервера приводит к замедлению работы определенных систем. Потенциально — остановке каких-то из подсистем. Если это, к примеру, платежная система, то сотни тысяч (если не миллионы) клиентов оказываются в ситуации невозможности расплатиться картой в магазине. Если такое продлится несколько часов, то это в лучшем случае репутационные потери. Если более длительное время — штрафы от регулятора с очень многими нулями. В пределе — лишение лицензии за неисполнение обязательств перед клиентами.
Если отказывает система контроля платежей, возникает риск пропустить «плохой» платеж (например, связанный с финансированием террористической деятельности). Тут последствия будут тоже очень жесткими.
Ну и так далее.
Вот вам оценка риска. Как думаете — что дешевле — подвергаться таким рискам или все-таки держать команду высококвалифицированных разработчиков, службу сопровождения и т.п.?
Рисковать может бизнес где цена риска относительно невелика. А стоимость вычислительных ресурсов сравнима со стоимостью разработчика.
В нашем случае весь упор делается на надежность, предсказуемость и эффективность работы системы. Пусть и ценой повышения стоимости разработки.
Скорость разработки, легкость поддержки достигается введением стандартных решений. Тех, что обкатаны, проверены нагрузочными тестами и прозрачны для сопровождения.
Как пример — многопоточная обработка. Да, наша система поддерживает posix threads. Но они не рекомендованы к использованию. Т.е. можно, но потребуется строгое обоснование что это наилучшее решение из возможных. Обычно же для распараллеливания мы используем фоновые задания (batch job) запускаемые из головного системной командой submit job (SBMJOB) или функцией spawn (если модуль пишется на С/С++). Преимущество в том, что сопровождение всегда может посмотреть статус каждого задания в системе и при необходимости вручную остановить задание, которое начало вести себя некорректно (команда ENDJOB в терминале).
Также есть документ «Нефункциональные требования к функционалу на платформе IBMi» Касательно SQLтам есть, например, такое:
Использование MERGE для больших объёмов данных запрещено. На время выполнения создаются блокировки записей в количестве кратном выполненным изменениям, что при большом их объёме приводит к замедлению работы сервера.
Использование таких выражений как ORDER BY, GROUP BY, DISTINCT, UNION и др. приводит к сортировке данных, что является очень тяжелой операцией. Допустимо только в случае необходимости.
Минимизируйте количество обращений к базе данных, используя multi-row SELECT/INSERT.
Минимизируйте и оптимизируйте использование WHERE с OR. Нужно чтобы каждый набор критериев “между” OR работал по индексу.
При разработке запросов SQL необходимо исключить возможность выбора SQL оптимизатором неиндексированного полного просмотра таблиц большого объема. Иначе это может приводить к длительным блокировкам областей таблицы и как следствие к ошибкам в процессах использующих эти таблицы.
Необходимо избегать использования в программе SQL функций Declare Scroll Cursor (избегать именно ключевого слова Scroll), т.к. в этом случае SQL оптимизатор использует иной маршрут для оценки времени выполнения запроса и может сработать ограничение сессии на максимальное время выполнения и система запретит его выполнение.
В остальных разделах (примеры):
Необходимо минимизировать использование операций полного открытия/закрытия объектов БД в алгоритмах функциональных модулей. В случае многократного использования программного объекта в рамках одного процесса, операция полного открытия объектов БД должна осуществляться один раз, на стадии инициализации.
В случае необходимости обработки больших объемов информации, программный модуль, где это возможно, должен использовать последовательное блочное чтения. Причем при обработке таблиц БД, с записью больших размеров (более 512 Байт), предпочтение должно отдаваться работе с переопределением файла, в котором будет указана настраиваемая глубина разовой операции чтения с диска.
В случае, если алгоритм подразумевает обновление небольшого процента (до 5%) считываемых записей таблицы БД, необходимо разделять объявление таблиц для операций чтения и обновления.
Необходимо избегать частого создания/пересоздания временных объектов, в том числе во временной библиотеке QTEMP. Если обойтись без них нельзя, то объект должен создаваться в рамках задания один раз и не пересоздаваться при повторных запусках модуля.
Использование параметра компилятора ACTGRP(*NEW) или кода заставляющего реинициализироваться программу при следующем запуске (например: установка LR индикатора в RPG), при создании программных модулей должно быть обоснованно и использоваться исключительно в крайних случаях. Ре-инициализация, в случае необходимости, должна реализовываться в алгоритме программы, а не использованием таких радикальных способов. Постоянная реинициалазиция и переоткрытие файлов требует выделения сегментов памяти, которые выделяет один системный процесс Гипервизор. И при большой интенсивности таких запросов он будет узким местом. При этом на обслуживание конфликтов ресурсов потребляется довольно много.
Должна быть реализована возможность остановки обработчиков за короткое время (1-2 сек) в штатном режиме, без потери данных/разрыва транзакции. В случае долгой работы задание может быть остановлено по ENDJOB *IMMED в любой момент.
В функциональность должна быть заложена возможность работы в многопоточном режиме, если функция не обеспечивает чисто инфраструктурных функций, которые не могут быть масштабированы.
Распределение нагрузки (системных ресурсов) на каждый из потоков обработки должно быть эффективным (как правило, равномерное распределение).
Если алгоритм многопоточной обработки нельзя реализовать без предварительного отбора данных, обеспечивающего эффективное распределение между потоками, и эта процедура не может быть масштабирована, то она должна быть максимально оптимизирована с точки зрения длительности ее работы.
Система должна обладать возможностью эффективно использовать предоставляемые аппаратные ресурсы без ухудшения характеристик производительности вплоть до 90% загрузки аппаратных ресурсов.
Новый продукт должен работать как минимум не хуже заменяемого, как в части длительности отдельных конечных операций, так и по потребляемым процессорным ресурсам
И это далеко не все. Там еще очень много чисто специфических требований.
Но даже это должно дать возможность понять что требуется от разработчика у нас (и, я думаю, в любом серьезном бизнесе). Т.е. уметь писать «красивый» код это очень малая толика требуемых навыков. На первом месте, как у же сказал — надежность и эффективность.
Как думаете — возможно создать мультипарадигменный язык, на котором можно выполнять все изложенные выше требования? По крайне мере управлять всем этим?
В котором не будет скрыто под капотом (исключительно ради красоты кода и легкости разработки) нечто такое, что будет подобные требования нарушать.
У нас разработка ведется на достаточно низкоуровневых (с точки зрения степени интеграции логики) языках. Бизнес-логика на RPG (при необходимости туда включается SQL код). Работа с системными ресурсами (где это надо для обвязки) — С/С++. Для работы на уровне команд ОС есть CL — командный язык, на котором можно писать программы и компилировать их (например, все инсталляторы патчей пишутся на нем).
При необходимости модули на разных языках могут собираться в один исполняемы программный объект — в этом суть концепции ILE с оптимизацией межязыковых вызовов процедур и передачи аргументов «через границу языка» в процессе сборки.
Ну и естественно, у нас используются только проверенные решения. Нельзя просто взять и протащить на прод что-то скачанное откуда-то из сети без тщательного и всестороннего тестирования (в том числе и нагрузочного).
Также не приветствуются велосипеды. Т.е. мы расширяем свою переиспользуемую кодовую базу, но это делается совместными усилиями с обсуждением архитектурных решений и выработкой единой для всех концепцией. И потом глубоко документируется (не просто описываются интерфейсы, но и их поведение в разных ситуациях).
Вот такой подход к разработке.
Так что все что я тут писал, это не критика Вашей идеи, а просто взгляд на нее со своей болотной кочки.
Тут в одном теге несколько имен (осноовное и дополнительные), несколько паспортов, которые надо по шаблону паспорта РФ проверить и если попадает, то распарсить на номер, кем и когда выдан и т.п.
Там еще парсинг адресов может быть с выделение города, улицы, дома, квартиры и т.п. со всякими возможными вариациями.
Поскольку язык гибридный, то для парсинга паспорта можно можно написать функцию, которая будет возвращать ассоциативный массив, а затем использовать ее в определении понятия. Даже можно сджоинить ее результат с другими понятиями.
У нас разработка ведется на достаточно низкоуровневых (с точки зрения степени интеграции логики) языках.
Это скорее специфика платформы, построенной на суперсерверах. В WEB проектах чаще масштабируют приложение на много дешевых серверов. Аренда сервера на AWS будет стоит около 1000$ в год. Это приблизительно зарплата за 2 дня среднего разработчика из США. Если удастся повысить скорость разработки хотя бы процентов на 10, то это будет иметь экономический смысл. Во-первых, можно сэкономить на количестве разработчиков, а во-вторых быстрее вывести продукт на рынок (что для бизнеса может быть гораздо важнее).
Поскольку язык гибридный, то для парсинга паспорта можно можно написать функцию, которая будет возвращать ассоциативный массив, а затем использовать ее в определении понятия. Даже можно сджоинить ее результат с другими понятиями.
Угу. В том случае, если это Паспорт РФ. Но вообще-то это ДУЛ — документ, удостоверяющий личность. Там может быть какой-то иностранный паспорт, военный билет и вообще что угодно. Так что для начала придется понять — соответствует ли формат строки шаблону паспорта РФ или нет :-)
Делается это на регулярках. И ими же вытаскиваются составные часть если проверка шаблона прошла успешно.
Там что-то типа такого:
ПАСПОРТ РФ: {0,}[0-9]{4} {0,}[0-9]{6} {0,}ВЫДАН.{0,}[0-3][0-9][ -\\.][01][0-9][ -\\.][12][0-9]{3}.{0,}
Если прошло, то парсим. Нет — значит это или не паспорт РФ, или данныее криво введены.
Причем там может быть как
ПАСПОРТ РФ: <серия> <номер> ВЫДАН <кем выдан> <дата выдачи в виде dd.mm.yyyy>
так и ПАСПОРТ РФ: <серия> <номер> ВЫДАН <дата выдачи в виде dd.mm.yyyy> <кем выдан>
Так что дату выдачи еще отдельно ищем по регулярке
[0-3][0-9][ -\\.][01][0-9][ -\\.][12][0-9]{3}
Это скорее специфика платформы, построенной на суперсерверах. В WEB проектах чаще масштабируют приложение на много дешевых серверов.
Ну… Примерно такая же специфика будет во многих задачах. Например, задачи, которые занимаются управлением и мониторингом каких-то процессов. Там тоже на первом месте эффективсность т.к. все должно обрабатываться с минимальными задержками (а есть участки кода, которые вообще очень критичны по времени выполнения т.к. ограничены жесткими таймаутами).
Так что скорее web разработка специфична в плане вольности обращения с ресурсами.
Так что скорее web разработка специфична в плане вольности обращения с ресурсами.
Да, согласен. Уже начинаю забывать, что одним вебом программирование не ограничивается.
Хотя, конечно, много примеров и обратного. Людей в этой области работает много, и далеко не все из них достаточно профессиональны.
Сам всю жизнь работал в таких областях, где или эффективно, или никак — эффективность и надежность всегда ставились на первое место. Т.е. постоянно приходилось свой уровень подтягивать до требуемого.
Хотя это всегда были достаточно узконишевые вещи.
А ещё бывает так, что со временем база данных выросла и сервер начинает тормозить. Вы думаете, из той же 1С начинают выковыривать SQL-операторы и заменять на что-то более шустрое? Я вас умоляю! Просто покупают новый сервер. А бывает, что разработка ещё не закончилась, а уже все согласны купить новый сервер. Потому что так сказали головастые мужики. А неголовастым и возразить нечего.
Да, порою оказывается так, что дешевле купить новый сервер, который переварит некоторую неэффективность, чем платить программистам за долгую и кропотливую разработку.
Новый сервер стоит $200k примерно. А их как минимум три штуки в кластере.
Вы думаете, из той же 1С начинают выковыривать SQL-операторы и заменять на что-то более шустрое? Я вас умоляю! Просто покупают новый сервер.
И Вы считаете такой подход нормальным? Сколько было стонов про ту же винду, каждая версия которой требует все более мощного железа? Это оно и есть — проблемы разработки (нет желания платить более квалифицированным разработчикам) переваливают на пользователя — пусть он покупает более мощное железо.
Но реальные факты из жизни говорят, что такое имеет место быть. Как говорит одесская пословица, если проблему можно решить за деньги, то это не проблема, а расходы. Вот заказчик/собственник и решает, что дешевле — то ли новый сервер купить, то ли выкинуть старое ПО и написать заново новое.
Тут тот случай, когда скупой платит дважды — сначала сэкономили на покупке решения подешевле, потом вкладываемся в улучшение железа и в конечном итоге приходим к тому что дальнейшее улучшение железа уже или невозможно, или безумно дорого. И начинаем понимать, что изначально держать свою команду разработчиков оказалось бы в итоге дешевле.
Я в этой картине ничего не рисовал от себя. Всё из жизни.
В сложном технологическом бизнесе правильным будет вкладывать деньги в команду, оптимизировать решение, проектировать его с учетом масштабирования и т.п.
А мелком и среднем достаточно заказать на стороне сайт-визитку или приложение для учета чего-нибудь. Решение будет быстрым, дешевым и неоптимальным. Проще потратиться на дополнительное оборудование, чем тратить время и деньги на высокооплачиваемых разработчиков (попробуй их еще найди) и разработку сложного специализированного решения.
Проектируем мульти-парадигменный язык программирования. Часть 1 — Для чего он нужен?