VAX — инструмент для визуального программирования, или как написать SQL мышкой



    Я хочу рассказать про созданный мною web редактор для «визуального программирования» и его историю создания.

    Случилось как-то мне столкнуться с одной очень надоедливой задачей на работе в компании PimPay, в которой я занимаю должность технического директора. Есть у нас отдел, занимающийся претензионной деятельностью с Почтой России. Ребята ищут потерянные/не оплаченные/не доставленные отправления. В сухом остатке для разработчиков эта задача сводилась к написанию очень большого количества разнообразных и огромных (>150 строк) SQL запросов на диалекте PostgreSQL, которые ОЧЕНЬ часто менялись и дополнялись в силу активного появления новых гипотез, а также поступления новых сведений о заказах.

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

    И тут, как в фильме «Проблеск гениальности» («Flash of Genius»), у меня перед глазами всплыла картина визуального редактора схем (blueprints) из UE4 (Unreal Engine 4), с помощью которых персонажи запускали файрболы в своих врагов:

    image

    Прибежав в тот же вечер домой, я взял первую попавшуюся JavaScript библиотеку, умеющую рисовать красивые прямоугольники и сложные линии — ей оказалась Raphaël от нашего соотечественника DmitryBaranovskiy. Нарисовав пару прямоугольников и подёргав их с помощью библиотечных drag-and-drop, я сразу написал автору библиотеки с вопросом поддерживает ли он её. И не дождавшись ответа (до сих пор), я в ту же ночь наплодил более 1000 строк кода на JavaScript, и моя мечта на глазах почти стала явью! Но предстояло ещё много работы.

    В итоге, что же захотелось сделать:

    • Красивый и удобный редактор в вебе, который предоставляет средства для манипуляции и связывания «узлов» разных типов, которые описываются в доменной схеме, передающейся редактору при инициализации. Тем самым сделать редактор независимым от предметной области.
    • Возможность сериализации ацикличного графа пользователя в древовидную структуру, которую очень легко разбирать (parse) (например JSON) и интерпретировать на любом языке.
    • Предоставить удобный формат для описания типов и компонентов предметной области.
    • Придумать богатую систему типов и ограничений, которая поможет пользователю создавать графы, корректные с точки зрения предметной области.
    • Дать возможность пользователю создавать свои компоненты из комбинаций существующих.

    В итоге вот что получилось:

    image

    Видно, что чертёж (blueprint) состоит из узлов (nodes), которые являются конкретными экземплярами компонентов (component), описанных в схеме предметной области (schema). Узлы соединяют проводами (wires). Провод всегда идёт от выхода (output) одного узла к входу (input) другого (и наоборот). Из одного выхода может идти много проводов, но на вход можно привязать только один.

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

    types:
        # Всегда есть тип Any, который супер-родитель всех типов
        Scalar:
        Numeric:
           extends: Scalar
        String:
           extends: Scalar
        List:
           typeParams: [A]
    

    Таким образом можно выход типа Numeric связать с входом типа Scalar, но не наоборот. Для параметризованных типов вроде List подразумевается ковариативность, т.е. List[String] можно передать в List[Scalar], но не наоборот. Плюс всегда присутствует супер тип Any, наследником которого являются все остальные типы.

    У узлов также могу присутствовать атрибуты, которые не настраиваются с помощью проводов, а пользователь сам вводит в них значения. Для этого существуют концепция valuePicker-ов, с помощью которых можно задавать свой интерфейс ввода значений атрибутов. Из коробки есть просто текстовый инпут и возможность выбора из заранее определённого набора констант.

    Также узлы бывают параметризованы по типам. Например, дан компонент:

    IfThenElse:
      typeParams: [T]
      in:
        C: Boolean  
      out:
        onTrue: @T
        onFalse: @T
    

    При создании узла на базе компонента IfThenElse редактор попросит нас указать тип T и подставит его во все места с T:

    image

    Типы входов и выходов также помогают пользователю при проектировании. Если вы потянете проводок из выхода с типом Numeric и отпустите мышку, то вылезет окно создания компонентов, отфильтрованных таким образом, что там останутся только те, вход которых совместим (conforms) с типом Numeric. И даже автоматически привяжется проводок.

    Заняло всё это примерно чистых тройку человеко-недель, растянутых на добрых 5-6 месяцев. И ещё спустя полгода появились силы что-то задокументировать и заявить об этом миру.

    Итак, господа, настало время творить! Возьмём самый нереальный случай, когда вам надо предоставить «не техническому» пользователю возможность визуально программировать процесс складывания чисел. Мы пониманием, что нам нужен всего лишь один тип Numeric и пару компонентов: возможность задать число (Literal) и возможность сложить два таких числа (Plus). Далее приведён пример схемы данной предметной области: (все примеры схем описаны в формате YAML для наглядности, в реальности же вам надо будет передавать нативные javascript объекты):

    types:
        # Всегда есть тип Any, который супер-родитель всех типов
        Numeric:
            color: "#fff"
          
    components:
      Literal: # Название компонента
        attrs: # Атрибуты
          V: Numeric 
        out: # Исходящие сокеты
          O: Numeric
    
      Plus:
        in: # Входящие сокеты
          A: Numeric
          B: Numeric
        out:
          O: Numeric
    

    Пример собранного редактора с данной схемой и простым графом можно посмотреть тут.

    Поиграйтесь! Нажмите X для создания нового элемента, удалите элемент двойным кликом. Соедините узлы проводками, выделите их все и скопируйте и вставьте через Ctrl+C и Ctrl+V. Потом выделите все Ctrl+A и удалите с помощью Delete. Ведь всегда можно сделать Undo, прибегнув к Ctrl+Z!

    Теперь допустим, наш нехитрый пользователь собрал следующий граф:

    image

    Если мы попросим редактор сохранить наш граф в дерево, то получим:

    [
      {
        "id": 8,
        "c": "Plus",
        "links": {
          "A": {
            "id": 2,
            "c": "Literal",
            "a": {
              "V": "2"
            },
            "links": {},
            "out": "O"
          },
          "B": {
            "id": 5,
            "c": "Literal",
            "a": {
              "V": "2"
            },
            "links": {},
            "out": "O"
          }
        }
      }
    ]

    Как видим нам тут пришло дерево, которое очень легко рекурсивно обойти и получить какой-то результат. Допустим, языком нашего бэкэнда является тоже JavaScript (хотя может быть любой).

    Пишем тривиальный код:

    function walk(node) {
        switch (node.c) {
            case 'Literal':
                return parseFloat(node.a.V);
    
            case 'Plus':
                return walk(node.links.A) + walk(node.links.B);
    
            default:
                throw new Error("Unsupported node component: " + node.component);
        }
    }
    
    walk(tree);

    Если мы прогуляемся такой функцией по вышеуказанному дереву, то получим 2+2=4. Вуаля!

    Очень приятным бонусом является возможность у пользователя определять свои «функции», объединяя существующие компоненты.

    Например, даже имея такую скудную доменную область, где можно просто складывать числа, пользователь может определить свой компонент, который будет умножать заданное число на три:



    Теперь у нас появилась пользовательская функция x3:



    Которой можно воспользоваться, как новым компонентом:



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

    Вернёмся же к нашему первому примитивному примеру складывания чисел. Не смотря на то, что процессор это интегральное устройство, которое только и делает, что складывает — визуально программировать конечному пользователю на уровне сложения чисел будет не очень весело. Нужны более экспрессивные и богатые конструкции!

    Возьмём к примеру замечательный язык SQL. Если присмотреться, то любой SQL запрос на самом деле очень легко раскладывается в дерево (этим и занимается первым делом БД, когда получает ваш запрос). Понаписав достаточное количество типов и компонентов можно получить нечто уже более устрашающее:

    image

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

    localStorage.clear()

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

    SELECT 
         COUNT(o.id) AS cnt
       , (o.created_at)::DATE AS "Дата" 
    FROM tbl_order AS o 
    WHERE o.created_at BETWEEN '2017-1-1'::DATE AND CURRENT_DATE 
    GROUP BY (o.created_at)::DATE 
    HAVING ( COUNT(o.id) ) > ( 100 ) 
    ORDER BY (o.created_at)::DATE ASC

    Который сразу же исполняется и отдаёт готовый отчёт в формате Excel. Переведя данный SQL на человечий, получаем:

    Показать количество загруженных заказов за каждую день в хронологическом порядке, начинания с 1 января 2017 года, выкидывания дни, где загрузили меньше чем 100 заказов. Вполне себе реальный отчёт для бизнеса!

    Схему в формате JSON для данного примера можно посмотреть тут.

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

    Plus:
            typeParams: [T]
            typeBounds: {T: {<: Expr}} # Параметризованный тип 'T' ограничен сверху типом 'Expr',
                                       # что означает, что нам надо сюда передать наследник типа 'Expr'
            in:
                A: @T
                B: @T
            out:
                O: @T
    

    Это как если бы вы в Scala объявили функцию:

    def Plus[T <: Expr](A: T, B: T): T = A + B

    В итоге, подготовив достаточное количество компонентов, и придумав хорошую систему типов (и написав много немного backend кода для обхода деревьев) мы сбагрили дали возможность пользователю составлять свои ad-hoc отчёты на базе SQL. Немного расширив доменную область, мы сильно упростили исходную задачу с фильтрами для поиска проблемных заказов, описанную в начале статьи. А самое главное дали бизнесу возможность самостоятельно тестировать свои гипотезы без привлечения разработчиков. Теперь правда, приходится обучать и писать новые компоненты, но это куда более приятное занятие! Надеюсь, что на SQL и фильтрах дело не остановится, и мы воспользуемся этим инструментом в другим областях проекта.

    Самое главное, что я с радостью передаю этот инструмент в общественное достояние на GitHub под лицензией MIT.

    Кому интересно, есть идеи/задачи по дальнейшему развитию инструмента:
    • Более удобная навигация по компонентам в схеме + их документация для пользователя
    • Сокеты-атрибуты (как в UE4)
    • Возможность определять атрибуты в пользовательских функциях.
    • Режим read-only для отображения схем
    • Узлы кастомной формы (как в UE4), а не только прямоугольники
    • Ускорение и оптимизация для работы с большим количеством элементов
    • Интернационализация
    • Экспорт картинки в SVG/PNG
    • You name it!

    Будет круто, если кому-то захочется воспользоваться этим инструментом на практике и поделиться своим опытом.

    P.S. Ещё круче будет, если кто-то присоединится к разработке инструмента!

    P.P.S. Я проводил презентацию инструмента в компании с помощью данного документа.
    Поделиться публикацией

    Комментарии 88

      +1
      Большую работу проделали.
      Рекомендую обратить внимание на проект The Graph (github, opensource), демо.
      Он является частью целой системы для Flow Based программирования, , есть среда выполнения графов как минимум для nodeJS, и браузера. Можно взять только сам редактор графов, а выполняющее их ядро реализовать самостоятельно. Я например таким образом реализовал ETL загрузчик для OLAP системы.
        0
        Спасибо, буду изучать!
          0

          В MS Access тоже есть похожее.

            0
            ETL загрузчиков же кстати вообще превеликое множество.
              0
              Огромное спасибо за наводку, как раз нужно было что-то именно такое! Просто супер!
              0
              Я думал над похожем подходе для реализации визуального Prolog. Но руки пока не дошли.
                0
                Теперь может дойдут )
                0
                Очень любопытно. Возможно, эта штукенция пригодится мне для работы с Web Audio API. Спасибо за статью.
                  0
                  Хороший пример
                  0
                  Штука прикольная, но есть небольшой баг — если от переменной рисовать стрелку к занятому входу, то все ок — она не рисуется, но если протянуть стрелку в обратном направлении — от занятого входа к переменной, то она создастся, т.е. в один вход будет две стрелки:
                  image
                    +1
                    Спасибо, я думал никто не заметит :) Буду править!
                      0
                      Кстати, еще по тому же скриншоту такая фишка — на схеме в углу экрана показаны только первые две линии, но в реальности он работает по вторым. т.е. у меня 4 числа 1, 10, 100, 1000 сначала я на вход дал 1 и 10, потом от входов протянул линии к 100 и 1000, на мелкой схеме в углу показаны только лини к 1 и 10, а при нажатии на eval получаю 1100
                        0
                        Да, из одного места все ошибки
                        0
                        Вы создали тему на хабре и думали, что среди ее читателей нету тестировщиков? =)
                          0
                          Спасибо, я думал никто не заметит :) Буду править!

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

                      И не дождавшись ответа (до сих пор), я в ту же ночь наплодил более 1000 строк кода на JavaScript
                      , так все таки используется рафаэль? Или своя реализация отрисовки. В исходниках вижу что он подключен.
                        0
                        Да raphael, в нём было всё, что нужно.
                        0
                        А есть какие исследования, показывающие, что научить пользоваться вот такими схемами проще и быстрей, чем научить читать и писать тот же SQL в его традиционном текстовом виде?
                          0
                          Извините, ответил ниже на том же уровне комментария
                          +2
                          В нашем случае — да оказалось всё просто.
                          Как минимум, мы вытащили все значимые таблицы и колонки для пользователей с человеческими именами. С помощью системы типов облегчили JOINы. Для всех enum-like полей создали соответствующие компоненты. Пользователю не надо знать как в системы называются статусы вроде executed, он просто видит удобный выпадающий список.
                          Также мы очень активно пользуемся всеми навороченными фичами PostgreSQL, и в данном случае, очевидно, что работу с hstore/jsonb/array/CTE/хранимками лучше вытащить в визуальные компоненты. Например, такие SQL:
                          SELECT 
                          	  o.delivery_service_external_order_id AS "ШПИ"
                          	, (clm.details#>>'{status,sent_to_russian_post}')::DATE AS "Дата подачи претензии"
                          	, clm.status AS status 
                          FROM tbl_order AS o 
                          INNER JOIN claim.tbl_claim_order AS co  ON o.id = co.order_id 
                          INNER JOIN claim.tbl_claim AS clm  ON co.claim_id = clm.id 
                          WHERE fn_get_param('minimal_faccept_date', ARRAY['CT#' || clm.customer_id])::DATE > '2017-03-01'::DATE

                          вряд ли кто либо из не-технарей согласиться писать :)

                          Плюс бесплатно у нас появляется возможность явно выделить эти фильтры, и отдельно запускать каждый, чтобы в дальнейшем проводить аудит, по какой именно причине заказ по ним отсеялся или наоборот. А имея 200 строчный SQL со ста OR-ами или AND-им тяжело понять, что именно отработало, и надо много чего доделывать.

                          Вообще, SQL не самая сложная область, как я упоминал в статье, всё это дело было вдохновлено UE4 Blueprints, которые вообще в С++ код транслируются.

                          Ну и ещё раз хочу сказать, что сам инструмент не привязан никак конкретно к SQL — его можно использовать в любой области.

                            0
                            В статье написано что инструмент передан в общественное достояние, а в репо на github стоит лицензия MIT. Я не юрист, но на мой взгляд тут есть противоречие, и должно быть и в репо тогда public domain указано. Но я, опять же, не разбираюсь, возможно так и должно быть.

                            Сам проект хорош, обязательно попробую, если подойдёт — буду пользоваться.
                            Читать сложновато, всё в одном файле. Есть планы по переоформлению кодовой базы с использованием какой-нибудь системы сборки?
                              +1
                              В статье написано что инструмент передан в общественное достояние, а в репо на github стоит лицензия MIT. Я не юрист, но на мой взгляд тут есть противоречие, и должно быть и в репо тогда public domain указано.

                              Я тоже не силён в лицензировании ПО, и сама тема не очень интересна, но при публикации проекта пришлось что-то всё таки поизучать. Сначала сразу захотелось повесить WTFPL, но бегло ознакомившись с содержимым https://habrahabr.ru/post/243091/, и посмотрев, что используют некоторые популярные open-source проекты — решил, что MIT вроде краткая и понятная, и без ругательных слов, и вроде позволяет делать с кодом что вам заблагорассудиться.

                              Есть планы по переоформлению кодовой базы с использованием какой-нибудь системы сборки?

                              Да, конечно. Как-то так вышло, что за пару-тройку дней файл разросся до 3к строчек, и мне не хотелось тратить запал на разбитие на файлы :) Плюс, я не front-end разработчик по специализации, и отстал от современных тенденций, поэтому, если посоветуете что-то конкретное — буду благодарен.
                                0
                                Насчёт общественного достояния понятно — по закону России нельзя вот так просто взять и перевести код в общественное достояние, а только по истечении времени (https://habrahabr.ru/post/243091/), отсюда не возникает противоречий и код лицензируется по MIT.

                                Ну, я бы предложил перейти на ES8 (или 7/6) чтобы использовать сахар новых версий, например через https://babeljs.io. Ну и, разбить код как-то, и научиться его собирать в обычную и минифицированную версию. Для сборки модулей берите наверное webpack, а если хотите просто компиляцию общего назначения — gulp.

                                Чуть не забыл: выберите и настройте линтер, например ESLint, JSLint или JSHint — это очень помогает. А ещё пишите тесты: это Mocha или Jasmine.
                                  0
                                  Насчёт общественного достояния понятно — по закону России нельзя вот так просто взять и перевести код в общественное достояние, а только по истечении времени (https://habrahabr.ru/post/243091/), отсюда не возникает противоречий и код лицензируется по MIT.

                                  Всё что я хотел сказать, так это — пользуйтесь на здоровье :) Главное, что лицензия MIT позволяет всем это делать.
                                0

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

                                  0
                                  Да, MIT — лицензия хорошая и классная, но общественное достояние в принципе исключает возможность лицензировать код. Кстати, по сути, лицензия MIT и общественное достояние содержат очень схожие пункты по предоставлению прав, но лицензию можно поменять, если ты автор, а вот отозвать из общественного достояния, вроде как, нельзя. Также нельзя лицензировать то, что является общественным достоянием.
                                    0

                                    А есть где-то примеры передачи кода в public domain? Просто насколько я знаю и лицензия MIT и лицензии Creative Commons так и остаются лицензиями, стараясь приблизиться к идее общественного достояния. Вроде как нигде в мире на данный момент нет возможности как-то иначе отчуждать свои права на произведение.
                                    Как вариант форкнуть пока оно под MIT и пользовать как собственный продукт.

                                      +2
                                      Авторское право — неотчуждаемо.
                                      Автор остается автором всегда.
                                      Есть сложные случаи типа работы по договору и т.п., но это дебри.
                                      Соответственно все вариации свободных и копилефт лицензий описывают случаи интеллектуальной СОБСТВЕННОСТИ а не авторства. Это важный вопрос а не придирка.
                                      Собственно наиболее широкие лицензии вроде MIT реально накладывают только ограничения на необходимость указывать авторство. ИМХО не велика проблема. Есть лицензии которые не требуют и этого.
                                      Упомянутая СС0 предназначена для целей передачи в общественное достояние. Лучше процитирую:
                                      CC0 — передача в общественное достояние от Creative Commons. Произведение, выпущенное по CC0, передано в общественное достояние в максимальной степени, разрешенной законом. Если это невозможно по любой причине, CC0 также предоставляет простую пермиссивную лицензию в качестве запасного варианта. И произведения в общественном достоянии, и простая лицензия, предоставляемая CC0, совместимы с GNU GPL. Если вы хотите передать ваше произведение в общественное достояние, мы рекомендуем вам использовать CC0.

                                      Пермессивная лицензия это когда от тебя требуют только автора указывать. Вроде СС0 лучше, не требуется даже этого… вроде как больше свобод и все такое, но…
                                      Вот не указываешь ты автора. А потом возникают вопросы правомочности использования этого кода. Придется доказывать всю цепочку. что код взял тут, что его давали под СС0, и т.п… Зачем?
                                      Укажи автора и спи спокойно.

                                      ИМХО MIT самая удобная. Единственное что — лично для себя я хочу к ней добавить один дополнительный пункт, что если кто-то присылает пулреквесты или другим образом отправляет свои патчи и доработки, то он автоматически (если не было обсуждено другое) отдает свои права правообладателю основного продукта. Чисто для простоты. Чтобы и код был свободен, и основной разработчик имел развязанные руки — кому не нравится сделает форк.
                                        0

                                        Я говорил не про авторское право, а про все права на произведение. С авторским правом как раз все просто и понятно — из всех ограничений оно разве что может заставлять указывать авторство.
                                        CC0 для кода возможно создает сложности из-за того что каждая версия становится некоторым отдельным куском в общественном достоянии. Хотя конкретно этот момент было бы неплохо уточнить у кого-то более подкованного, чем я.

                                        0
                                        SQlite — самый известный пример.
                                  +1
                                  Круто, сам большой поклонник такого подхода к программированию.
                                    0
                                    Забавно, но никто из комментаторов не указал Blockly

                                    Оно, конечно, выглядит попроще.
                                    Но дело делает.
                                      0
                                      Да тоже крутой инструмент, спасибо! Но он больше, возможно, подходит именно для написания кода или того же SQL. И с использованием переменных и функций, в принципе, можно легко комбинировать вещи.
                                      VAX больше про работу с графом. И SQL здесь, возможно, даже сбивающий пример :)
                                        0
                                        О, scratch для взрослых, спасибо.
                                        +1

                                        На простых примерах выглядит вдохновляюще, но как посмотришь на сложные схемы — уж лучше какой-то текстовый формат...

                                          0
                                          Ощущение понятное. Но оно пропадает, когда начинаете сами творить. Да, чужие графы читать тяжелее. Для борьбы с этим пока есть миникарта и комментарии (клавиша C), которые добавляют пояснения и служат группировкой элементов. Т.е. потянув комментарий, тянутся все элементы в нём. В UE4 Blueprints ещё есть Zoom In/Out, но я ещё не успел реализовать его. На уровне raphael не получилось, ибо и так у меня кастомный panning, Но в планах «логическое» зумирование, когда я меняю саму отрисовку элемента (делаю его меньше, убираю отступы и прочее).
                                            0
                                            Да и опять же, как с вопросом что легче обучить SQL или этому инструменты. Для технарей естественно я не спорю, что легче писать текстом. Но для остальных, причуды любого синтаксиса очень далеки для понимания.
                                            Я думаю, этот инструмент нужен именно в коммуникации между обычными пользователями (для нас это бизнес) и разработчиками.
                                              0
                                              Не факт что проще писать текстом.
                                              Сейчас медленно пытаюсь довести свой фреймворк до вида когда можно показывать.
                                              У меня похожая концепция ориентированная на визуальное редактирование, но пока без визуального редактирования.
                                              У меня в ORM есть понятие «правило».
                                              У модели (активрекорд) есть набор полей у каждого набор правил.
                                              Также есть правила которые влияют на бокс (что-то вроде репозитория, в простейшем случае таблица или папка/файл где лежат все однотипные модели).
                                              Хранится сие в JSON. Например так:
                                              Заголовок спойлера
                                              {
                                                  "#default": {
                                                      "#class" : "app\\prototype\\Model",
                                                      "scenarios": {
                                                          "default": {
                                                          },
                                                          "list": {
                                                              "id": "default"
                                                          },
                                                          "view": {
                                                              "id": "default"
                                                          },
                                                          "search": {
                                                          }
                                                      },
                                                      "box":{
                                                          "#class" : "app\\prototype\\Box",
                                                          "limit": 20
                                                      }
                                                  },
                                                  "registry" : {
                                                      "scenarios": {
                                                          "default": {
                                                              "id": ["string"],
                                                              "type": ["modelType","boxType&value=registry"],
                                                              "created": ["int","ordered","timeCreate","timestamp"],
                                                              "updated": ["int","ordered","timeUpdate","timestamp"],
                                                              "updateHistory":["updateHistory"]
                                                          },
                                                          "list": {
                                                              "id": "default",
                                                              "type":"default"
                                                          },
                                                          "advancedInfo": {
                                                              "id": "default",
                                                              "created": "default",
                                                              "updated": "default"
                                                          }
                                                      },
                                                      "box":{
                                                          "#class": "\\drycore\\orm\\box\\FolderBox",
                                                          "runtimeFolder":"registry"
                                                      }
                                                  },
                                                  "dbConfig": {
                                                      "#parent": "registry",
                                                      "scenarios": {
                                                          "default": {
                                                              "host": ["string","default&value=localhost","block&name=default"],
                                                              "dbname": ["string","block&name=default"],
                                                              "user": ["string","block&name=default"],
                                                              "password": ["string","block&name=default"],
                                                              "updateHistory":null
                                                          }
                                                      }
                                                  },
                                                  "user":{
                                                      "#parent":"drycart/site/#user",
                                                      "box":{
                                                          "#class": "\\drycore\\core\\user\\UserBox"
                                                      }
                                                  },
                                                  "#sitePage": {
                                                      "#parent": "drycart/cms/#sitePage",
                                                      "box":{
                                                          "where": [{"0": "`type` != :type","type": "adminPage"}]
                                                      }
                                                  },
                                              }
                                              


                                              Здесь описано пять разных моделек (#parent — имя родительского типа или массив родителей, бокс это грубо говоря таблица, #class это пхп-класс, и все наследуются от #default).
                                              Я знаю что правило updateHistory создает связь на одноименную таблицу, и при сохранении модельки сохраняет историю ее изменений. Знаю что timeCreate это таймштамп создания, timestamp это правило наследующееся от целого и основное назначение которого выводить в админке контрол времени, а при выводе красивую дату (или время еслидата недавняя), block&name влияет на то в каком табе выводить данное поле если мы отображаем форму для модели… я знаю все 130 правил. Ведь я же сам их писал.
                                              Но если честно, то а) частенько путаюсь какое как называется и какой синтаксис параметров (у блока параметр нейм или блок?). Нужно открывать документацию или пример. Чтобы отследить наследование надо листать несколько файлов (или компилированный конфиг). А уж взаимодействия полсотни моделек так вообще нереально увидеть в тексте.
                                              Многие доработки я откладываю до того времени когда у меня дойдут руки сделать визуальный редактор.
                                              Уже не могу без него. Я и в тему зашел в надежде что будет просто это утащить себе. Но похоже не судьба. Оно будет удобно для языка запросов. У 1С очень приятный конструктор запросов, думаю с этим можно сделать что-то похожее.
                                                0
                                                Я и в тему зашел в надежде что будет просто это утащить себе. Но похоже не судьба.

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

                                                    Почти что угодно можно представить в виде связи:
                                                    image

                                                    Появилась идея сделать на базе Вашего редактора графов конструктор для правил, чтобы можно было делать цепочки действий и т.п. но сыро.

                                                    Подскажите, пожалуйста, что именно сыро?

                                                    В общем статья интересная, но дальше…

                                                    Не пойму, о чём вы говорите. Поясните, пожалуйста.

                                                      0
                                                      Сыро не у Вас, сыро у меня).
                                                      Мне скорее нужен инструмент по написанию своей грамматики а не по написанию с помощью уже готовой грамматики. А для готовой грамматики да, прикольно выглядит.
                                                        0
                                                        Вроде такого http://www.eclipse.org/Xtext/?
                                                          0
                                                          Нет, не совсем.
                                                          Вот типичный юзкейс:
                                                          Мы хотим на сайте сделать опрос клиентов.
                                                          Для этого нужно вывести форму с каким-то набором полей и неким стандартным поведением. Допустим у нас уже есть абстрактная модель #опрос
                                                          Админу нужно отнаследоваться от нее (тут просто — мы или из списка выбираем родителя или он фиксированный) и добавить к ней полей.
                                                          Допустим моделька уже умеет разбираться с дополнительными полями. Или сериализирует в жсон, или EAV использует, не суть.
                                                          Нам нужно дать пользователю красивенько добавить поля. Есть кнопка добавления полей, есть кнопочки добавления правил к этим полям. Допустим это будет опрос «ваш любимый мультик».
                                                          Мы хотим добавить поле «Ваш любимый мультик». К этому полю мы добавим правило «связь с таблицей Мультики, поле связи — id_мультика». К нему мы добавим правило «выбор из выпадающего списка», и еще правило «если вариант не выбран, то по умолчанию — Щенячий патруль».
                                                          Потом мы добавляем поле «Ваш возраст». К нему добавляем правило «целое», к нему добавляем «минимум 5», и правило «максимум 80». Также добавляем правило «если не заполнено, то по умолчанию берем возраст из такого-то поля текущего пользователя».
                                                          Ну и раз уж инструмент универсальный то у нас должны быть видны поля из родителя, например связь по ИД текущего пользователя, время создания, айпи опрошенного и т.п.
                                                          Ну и соответственно например если мы захотим сделать совсем анонимный опрос, то мы переопределим поле «ид пользователя» на «по умолчанию NULL» (грязный хак, не SOLID, но сходу более удачный пример не приходит в голову).

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

                                            Можно же делать целые компоненты с интерфейсами, а подробности реализации скрывать в подсхемах/текстовой реализации

                                              0

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

                                                0
                                                Для этого уже есть пользовательские функции. Но возможно, есть смысл их сделать «анонимными», чтоб прям на схеме выбрал группу компонентов и схлопнул в функцию, которую потом по даблклику редактируешь. Но там очень много вопросов всё равно возникает, с отображением проводов, и дальнейшей возможностью редактировать изолированно в новом окне.
                                            +1
                                            и как же теперь выглядят запросы на 150 строк?
                                              0
                                              Вообще интересно, напоминает тот же визуальный редактор SQL-запросов в Microsoft Acces.

                                              А в обратную сторону SQL-запросы он нормально по узлам раскидывает?

                                              З.Ы. под спойлером пример визуального программирования в вебе — мойлюбимыйкорезоид

                                              Картинка
                                              image
                                                0
                                                А в обратную сторону SQL-запросы он нормально по узлам раскидывает?

                                                VAX вообще ничего не знает про SQL, он просто работает со схемой доменной области, которую вы ему скормите. И на выходе даёт граф либо деревья, сериализованные в JSON. Это уже backend нашего проекта превратил их в SQL.
                                                Но естественно, можно в VAX загружать графы, т.е. если вы придумаете как разбить ваш SQL на узлы из вашей схемы, то можно смело рендерить такой граф. Но, вряд ли, такая задача кому нужна.
                                                0
                                                Спасибо огромное, собирался в своем проекте делать такую штуку для веб (по пути Blueprint в UE4), но вы сделали это раньше и теперь я могу сэкономить уйму времени.
                                                0
                                                спасибо
                                                  0
                                                  Какая-то непонятная сеть из нитей и блоков. Нетехнаря не надо заставлять писать такие запросы, как в примере. SQL-щику приятнее и понятнее обычный SQL.
                                                    0
                                                    SQL-щику приятнее и понятнее обычный SQL.

                                                    С этим никто не спорит, но суть статьи не про это.
                                                    –1
                                                    Визуальный тул для обработки данных из БД ??? Это же ETL!
                                                      0
                                                      Отличная работа. Класс!
                                                        0
                                                        Кстати, ещё LabVIEW можете посмотреть как источник идей для визуального программирования.
                                                        Ну вот, к примеру, пара первых упражнений из «Проекта Эйлера»:


                                                        Цветом кодируется тип данных на линии — синие — целочисленные данные, зелёный пунктир — булевы.
                                                          +1
                                                          Бесспорно, в любом редакторе, заточенном на определённую предметную область, будет всё проще и нагляднее.
                                                          Но с помощью VAX, вот что можно получить:
                                                          image
                                                            0
                                                            Это на самом деле здорово, то что вы сделали, когда графический подход позволяет решать в том числе задачи «общего назначения».
                                                            Одна из самых больших проблем в графическом программировании — это использование места на экране и постоянно разрастающаяся диаграмма. При работе в той же LabVIEW одно из основных правил — любая диаграмма должна занимать не более одного экрана (и этого вполне можно достичь, грамотно разбивая программу на подпрограммы). Но я это к тому, что вы можете немного сэкономить место — сравните ваш «Equals 0?» с похожим LabVIEW элементом — в общем-то нет необходимости указывать тип Integer/Boolean на каждом коннекторе.
                                                            На самом деле LabVIEW не заточена под определённую предметную область (да, там есть специфические элементы для сбора данных с железок NI, но это всё на уровне библиотек), а так там совершенно «классические» базовые конструкции и типы данных, присутствующие практически в любом языке, и позволяющие писать вполне себе нормальные десктопные приложения. Я вообще придерживаюсь мнения, что через много много лет (несколько десятилетий, вероятно) классический текстовый подход к написанию программ постепенно заменится на графическое программирование на уровне диаграмм и в этом смысле вы двигаетесь в правильном направлении.
                                                              0
                                                              При работе в той же LabVIEW одно из основных правил — любая диаграмма должна занимать не более одного экрана (и этого вполне можно достичь, грамотно разбивая программу на подпрограммы). Но я это к тому, что вы можете немного сэкономить место — сравните ваш «Equals 0?» с похожим LabVIEW элементом — в общем-то нет необходимости указывать тип Integer/Boolean на каждом коннекторе.

                                                              Да верно подметили, это большая проблема. Среди задач на будущее есть возможность кастомизировать отображение узлов, чтобы их делать более компактными и/или информативными, возможность зумировать.

                                                              ...LabVIEW элементом — в общем-то нет необходимости указывать тип Integer/Boolean на каждом коннекторе.

                                                              Хорошая идея, спасибо. Можно их в принципе показывать только по наведению, или как-то ещё.
                                                                0
                                                                По юзабилити меня смущает немного неудобное добавление узлов. Узел появляется в произвольном месте (в демке на сайте это выше зоны просмотра), плюс надо листать список и т.п. Опять же места для комментариев в списке не очень много. Мне кажется тут было бы удобнее сделать панель с элементами из которой мы бы перетягивали мышкой.(Несколько панелей, выпадающее меню....).
                                                                Создание функций не интуитивно. Если я сходу не понял, то и юзер не поймет. Я могу прочитать документацию, а юзер нет… Ограниченное колво входов у функции (т.е. фиксированный список входов, 1,2,3?) удивляет.
                                                                Хочется больше гибкости в грамматике.
                                                                И хочется более компактного вида у узлов, да и у всей схемы.
                                                                Общее ощущение после более детального ознакомления — интересно поиграться. Интересно поучить на нем детей. Но в бою пока не вижу как использовать.
                                                                  0
                                                                  узел появляется в произвольном месте (в демке на сайте это выше зоны просмотра),

                                                                  При нажатии кнопки X он появляется в месте, где был курсор, при создании из провода, он тоже под курсором появляется. Единственное, когда его создаёшь из кнопки на меню, да он появляется где-то непонятно. Но я не думаю, что тулбаром есть смысл пользоваться.
                                                                  плюс надо листать список и т.п.

                                                                  там есть autosuggest

                                                                  1) Опять же места для комментариев в списке не очень много.
                                                                  2) Мне кажется тут было бы удобнее сделать панель с элементами из которой мы бы перетягивали мышкой.

                                                                  Да список элементов, наверное, надо очень крутым делать. Но в большинстве существующих подобных редакторов (в том же UE4) это просто список c autoSuggestом, т.к, как правило, очень много элементов.
                                                                  Создание функций не интуитивно.

                                                                  Да, это пока хромает.

                                                                  Ограниченное колво входов у функции (т.е. фиксированный список входов, 1,2,3?) удивляет.
                                                                  Не понял о чём вы. Вы всё определяете в схеме. Их там может быть сколько угодно. Если вы про пользовательские, то их там тоже может быть сколько угодно.

                                                                  Хочется больше гибкости в грамматике.

                                                                  Если есть конкретные идеи, будет круто.

                                                                  И хочется более компактного вида у узлов, да и у всей схемы.

                                                                  Да это в TODO всё.

                                                                  Но суть в том, что это всё просто недоделки редактора, которые понятно как улучшать, сама модель вряд ли претерпит изменения.

                                                                    0
                                                                    image
                                                                    Выбор из трех вариантов.
                                                                    Я так понимаю что в грамматике можно указать хоть десять, но если пользователю понадобится одиннадцать, то внезапно не получится. При этом в описании будет куча кода для шести параметров, которых в реальных кейсах ни разу не будет.
                                                                    Ну как-то так я понимаю.
                                                                      0
                                                                      Это параметризованные типы, а не количество параметров (в идеологии VAX — инпутов). Инпутов может быть сколько угодно. А типы-параметры это так называемые genericи, например в Scala:
                                                                      def map[A,B](l: List[A])(f: A=>B):List[B] = l map f
                                                                      или в Java:
                                                                      class BoxPrinter<T> { 
                                                                          private T val; 
                                                                       
                                                                          public BoxPrinter(T arg) { 
                                                                              val = arg; 
                                                                          } 
                                                                       
                                                                          public String toString() { 
                                                                              return "{" + val + "}"; 
                                                                          } 
                                                                       
                                                                          public T getValue() { 
                                                                              return val; 
                                                                          } 
                                                                      } 
                                                                      или template в C++:
                                                                      template<typename T>
                                                                      void f(T s)
                                                                      {
                                                                          std::cout << s << '\n';
                                                                      }

                                                                      И ваши функции тоже могут быть параметризованы типами, как если бы создали сами такой компонент:
                                                                      components:
                                                                         FoldArray:      
                                                                              typeParams: [T]
                                                                              in:
                                                                                  A: Array[@T]
                                                                              out:
                                                                                  O: @T

                                                                      Я не думаю, что на практике, кому-то понадобиться более 3 типов-параметров (если вообще кому-то хоть 1 тип понадобиться :))
                                                                  0
                                                                  Хорошая идея, спасибо. Можно их в принципе показывать только по наведению, или как-то ещё.

                                                                  В LabVIEW именно по наведению и сделано. Если я нажму Ctrl+H, то появится всплывающее окошко и по наведению мыши на проводник мне будет показан тип данных. Кроме того, если происходит приведение типов (ну, скажем я складываю int и double, то int будет автоматически приведён к double, о чём LabVIEW сообщит красной точкой (coercion dot) на входе. Ну как-то так это выглядит:
                                                                    0
                                                                    Круто, спасибо за идеи!
                                                            +1
                                                            Супер! Отличная работа!!!
                                                            Вот несколько ссылок на аналогичные библиотеки для работы с визуальными графами:



                                                            А вот этот проект не видели — noflojs? Чем-то похож на Ваш.
                                                              0
                                                              Картинка для привлечения внимания :)

                                                              image
                                                                0
                                                                Спасибо!

                                                                http://js.cytoscape.org
                                                                https://www.graphdracula.net
                                                                https://jsplumbtoolkit.com
                                                                http://sigmajs.org


                                                                Эти вроде (не утверждаю) все либо просто для рисования/анализа/layout графов, либо с захардкоженной доменной областью.
                                                                Сама работа с графом в моём случае не является центральной идеей.

                                                                Да, noflojs интересный и похожий инструмент. Возможно есть смысл подумать над интеграцией с форматом FBP, если кому-то будет нужно.

                                                                  0
                                                                  Да, это замена Raphaël — насколько я понял, Вы пытались связаться с автором, но безуспешно. Поэтому накидал несколько альтернатив для визуализации :)
                                                                    0
                                                                    Ну эти библиотеки именно про рисование графов. С ними бы я не справился.
                                                                    Raphael более низкоуровневая библиотека. Там можно только рисовать прямоугольники, окружности, текст и линии. Всё остальное пришлось делать самому :)
                                                                      0
                                                                      Прямым алтернативами Raphael вроде являются вещи вроде SVG.js/просто canvas/Processing.js
                                                                –1
                                                                Вроде как системы бизнес аналитики предназначены для целей создания выборок данных и отчетов пользователями без привлечения программистов.
                                                                  0
                                                                  Я не очень понимаю в чем профит, от представления короткого запроса в виде сложного графа, ну да ладно. Просто хотел описать несколько иной подход к визуальной оболочке для работы с данными.
                                                                  Вы видите сразу схему вашей базы. Если вас интересует какое-то поле — вы его вытягиваете из схемы и сразу получаете табличку которая делает group by по этому полю и считает count. Потом можно в неё кинуть другое поле как значение и оно тоже саггрегируется. Тип аггреграции — свойство колонки. Надо фильтрацию — или вписываем условие вида «поле больше x» или клацаем на нужной строке для фильтрации. Ну и так далее. Общая идея в том, чтоб работать сразу с данными, а не представлять те же абстракции в другом виде.
                                                                    0
                                                                    Вы описываете что-то вроде конструктора запросов 1с. ИМХО у них лучшая концепция построения сложных запросов мышкой. И там без графов.
                                                                    0
                                                                    aveic, есть возможность экспорта схемы-sql в готового вида запрос? (возможно пропустил комментарий с ответом на подобный вопрос, простите заранее)
                                                                      0
                                                                      На нашем проекте есть, именно это и происходит, но он содержит много project-specific логики, и вам вряд ли понадобиться. Да и сама грамматика больше подходит только для нашего проекта, нежели для generic sql. Сам инструмент, как бы, планировалось развивать без привязки к определённой доменной области (в данном случае SQL) и конкретному бэкэнду, в этом его суть.

                                                                      P.S. Странно, что уже комментариев 5 к этой статье я насчитал, которые явно не поняли суть инструмента.
                                                                        0
                                                                        Ничего странного. Человек внимательно читает заголовок, а текст уже в зависимости от заинтересованности.
                                                                        В заголовке сказано «или как написать SQL мышкой». Соответственно люди думают что в статье об этом написано. А по факту нет, не написано, вот и спрашивают.
                                                                      –1
                                                                      вот наверное ваш ДБА был рад. Такая фигня производительность сервера роняет на раз.
                                                                      Я своим девелоперам руки обрываю за такие творения.

                                                                      Было бы очень интересно узнать ситуацию с производительностью до и после. Или вы такой ерундой не заморачиваетесь?
                                                                        0
                                                                        Было бы очень интересно узнать ситуацию с производительностью до и после.

                                                                        Это сугубо аналитические запросы, вынесенные за OLTP основного приложения, запускаемые поверх read-only аналитических реплик. Раз в месяц по всем клиентам, и изредка (максимум раз в день) для теста новых гипотез.
                                                                        Или вы такой ерундой не заморачиваетесь?

                                                                        Мы такой ерундой заморачиваемся.
                                                                          0
                                                                          Но и самое главное, статья и инструмент совсем не про SQL.
                                                                            0
                                                                            ну если раз в месяц, под контролем и на снапшот — тогда не страшно :).

                                                                            просто подобное действительно в основном пытаются решить для SQL, востребованно.

                                                                            Только на моей памяти в одной компании пытались решить эту проблему двумя путями:
                                                                            1) улучшениями бизнес процесса между IT и бизнесом (на что жалуется Mendel внизу). Универсализация/упрощение запросов от бизнеса.
                                                                            2) просто скопировали какую-то систему (backend only), которая создавала динамические запросы. Она в оригинале то работала с тормозами. Пришлось улучшать, благо типовой набор запросов был не бесконечным.
                                                                            +1
                                                                            У вас небось всех на ассемблере заставляют писать?
                                                                            Мышакодинг для единичных запросов на много порядков улучшает производительность.
                                                                            У меня бывали запросы в 1с которые выполнялись по 20-30 секунд. Даже с учетом их продвинутого кеширования (всякие регистры с предвычислениями сильно облегчающие групповые операции).
                                                                            Безумно много если выполнять регулярно. Но пофиг если написание запроса заняло час, и повторно выполняться он не будет никогда.
                                                                            А вот оптимизировать написание самого запроса — бесценно.
                                                                            Для относительно простых аналитических запросов больше половины времени уходит на то чтобы манагер которому нужен запрос и программист поняли друг-друга. При этом 90% запросов никто не пишет по принципу «ой, пока напишут, пока посчитают, та ну...».
                                                                            Когда мышкой потыкать и получить инфу — намного эффективнее.
                                                                              0
                                                                              завидую, вы похоже из тех немногих счастливчиков, которые не сталкивались с проблемами «единичных» запросов. Неужели, не разу даже не слышали о ситуациях когда один ПРОСТОЙ запрос роняет сервер?
                                                                              Именно по этой причине девелоперы в нормальных кампаниях не имеют доступа к боевым серверам.
                                                                              И только люди кто реально понимают как это работает, работают напрямую.

                                                                              Уж лучше пускай потратит час (к вопросу об профессионализме) на написания запроса, чем бизнес кампании зависнет на несколько минут.

                                                                              В сухом остатке: динамические запросы зло. не важно как они создаются.

                                                                              Хотите создать что-то что тыкается мышкой, спросите ДБА спеца как лучше (естественно применительно только к SQL). Универсальных решений не бывает, в каждом случае свой подход.
                                                                                0
                                                                                вообще-то dba должны настраивать приоритеты и пул ресурсов для аналитиков и их запросов.
                                                                                Именно чтобы один запрос не уронил сервер.
                                                                                  0
                                                                                  Это чисто инженерная проблема имеющая множество решений.
                                                                                  Самые простые — оптимизация базы и серверов, отдельная база для аналитики стоящая слейвом у боевой, ограничение времени исполнения запроса.
                                                                                  Ну и конечно конструктор запросов должен быть умным.
                                                                                  Возьмем самый известный среди окружающих мышепостроитель запросов — пхпмайадмин.
                                                                                  Самая важная его функция защищающая сервер от краша это — добавление лимита к селектам.
                                                                                  Вот буквально на этой неделе у меня выплыла задачка парсинга некоторых публичных баз. И у одной из них у результатов поиска нет пагинации и лимита.
                                                                                  По каждому чиху падает. Но это ведь не от сложного построителя запросов которого там просто нет, а от плохого проектирования.
                                                                                  А вот в 1С где у меня были самые толстые неоптимизированные запросы, с кучей вложенных запросов и т.п… юнион от восьми групповых запросов каждый из которых жоин на три таблицы. Причем все это по большим таблицам и подтаблицам (в языке 1С-запросов это по сути скрытые жоины). Никогда проблем не было. Да и не могло быть. Везде индексы, где статистика какая-то — регистры накопления (эдакие предвычисления по суммам и оборотам). Один запрос — один поток. На сервере 16 ядер плюс гупертрейтинг. Клиентов в базе всего человек двадцать кто мог работать с основной базой (была еще почти сотня удаленных баз в филиалах которые синхронизировались с основной, и была еще одна копия основной синхронизированная где жило большинство пользователей). Так чтобы одновременно — ну максимум человек 5. Запросы они одновременно не делали. Бывало запросы и по 5 минут считали, может и больше, но так чтобы сервер положить… не представляю что для этого нужно.
                                                                                  А уж так чтобы «работу парализовать», так вообще невозможно — остальные экземпляры базы будут живы и даже те кто имели доступ к основной базе — имели доступ к другим.
                                                                                  Единственное что — задержки в процессе синхронизации. Но это проблема архитектуры сети которую я выбрал, и исключительно потому что задержки в час были заложены как штатные, так что я не оптимизировал эту сторону. А если бы статистика была бы на дочерней базе а не на основной, то и этого бы не было.

                                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                            Самое читаемое