Я расскажу о технологической платформе, пригодной для создания информационного ядра системы или приложения. Платформа содержит простой высокоуровневый конструктор модели данных и базовый интерфейс для работы с ней, поддерживает ролевую модель доступа, эмулятор запросов SQL (CRUD), API, а также дает возможность загружать произвольные рабочие места — элементы UI — и наполнять их данными.

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

Здесь вы можете собрать веб-приложение, не изучая язык программирования: мы оперируем только бизнес-терминами и формулами, не сложнее, чем в MS Excel. Безусловно, понимание принципов работы баз данных поможет вам разработать более живучий, масштабный и богатый функционалом продукт, но этот сервис не требует специфических знаний для простых решений, которые составляют, навскидку, не меньше 80% прикладной разработки (например, кустарной и всего, что сейчас работает в Экселе).

Disclaimer


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

Интеграл


Интеграл — это архитектурообразующее ядро, дающее базовый пользовательский интерфейс для задания модели данных (метаданные) и работы с данными. Базовый интерфейс использует несколько простейших команд для управления структурой данных (DDL) и 6 команд для изменения самих данных (DML). Эти команды скрыты от пользователя — он видит только поля ввода, таблицы и кнопки. Вы можете, не зная никаких команд, использовать базовый интерфейс для работы с вашими данными и быстро создать информационную систему.

Общая схема взаимодействия сервиса с внешним миром выглядит так:



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

«Программирование» Интеграла заключается в следующем:
  • задание параметров процессов — этапы, роли, свойства, структуры, форматы и т.д.;
  • создание запросов на выборку и изменение данных, включая создание и изменение самих запросов;
  • создание шаблонов пользовательского интерфейса с точками вставки для данных.

Пользователь заходит в систему, получает меню согласно своей роли, просматривает информацию, вводит данные, запускает запросы, двигая процесс по заданным этапам, получает отчеты. Всё взаимодействие с системой происходит через формы, заданные шаблонами. Очень похоже на работу CMS и, как говорит наша дизайнер, «сделано как в первой Битре».

Для работы используется базовый интерфейс, который можно дополнять и расширять под свои нужды. Формы базового интерфейса доступны на Гитхабе, можно их свободно использовать — переписать полностью с блэкджеком и дамочками или просто «натянуть» нужные стили.

Структура данных


Средства построения модели данных и работы с ней — основное преимущество подхода Интеграл. Здесь мы можем быстро создать схему объектов нашего бизнеса, способную при необходимости так же быстро перестроиться.

Изначально мы получаем базу данных, в которой описаны некоторые сущности (называемые далее объектами или типами). Об их природе и принципах работы ядро Интеграла уже знает. Их немного:
  • Пользователь;
  • Роль пользователя;
  • Объекты, входящие в Роль (все объекты Интеграла, включая Роль и Пользователя);
  • Уровень доступа к объекту;
  • Запрос (аналог SQL-запроса в реляционной базе данных);
  • Поля запроса (имена всех объектов системы, включая вновь создаваемые).

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

Структура создается в Редакторе типов, где всё это выглядит примерно так:



Перед вами иерархия объектов: Пользователю назначена Роль, в которую входят несколько Объектов, каждому из которых назначен Доступ. Также есть объект Запрос — это аналог SQL-запросов в базах данных, он содержит Поля, к которым можно применять Функции, Форматы, подсчитывать итоговые значения по ним. Здесь для наглядности связи изображены стрелками между объектами, однако в Редакторе типов объекты-прямоугольники не связаны стрелками, а иерархия обозначается только расположением детей правее от родителя с распространением списка вниз. Так сделано потому, что на небольшой схеме подчиненность объектов и так очевидна, в то время как на большой схеме стрелки не добавляют удобства, а лишь загромождают картину.

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

Помимо перечисленных выше объектов, Интеграл — это чистый лист, на котором вы можете набросать нужную вам структуру данных с их связями. Любую структуру, какую можно реализовать в реляционной базе данных. Как вы, вероятно, уже догадались, Интеграл сам собран средствами Интеграла.

Для добавления своих объектов — терминов вашего бизнеса — вы просто задаете имя и указываете базовый тип: строка, число, файл и т.д. Всего доступно 16 базовых типов, большинство из которых определяют представление данных, остальные задают поведение — например, контекстное действие.
Тип Описание
SHORT Короткая строка (до 127 символов)
CHARS Строка без ограничения длины
DATE Дата
NUMBER Целое число
SIGNED Число с десятичной точкой
BOOLEAN Логическое значение (Да/Нет)
MEMO Многострочный текст (отличается от CHARS только окном ввода)
DATETIME Дата с указанием времени
FILE Файл
HTML HTML-код (теги не экранируются при выводе в запросах)
BUTTON Кнопка для контекстного действия (отчет, запрос, ссылка)
PWD Пароль (хэш, посолен именем базы, пользователя и чем-то ещё)
GRANT Объект доступа (ссылка на любой объект системы)
CALCULATABLE Вычисляемое значение (временно упразднено)
REPORT_COLUMN Поле данных (ссылка на объект системы)
FULLTEXT Строка с поддержкой полнотекстового поиска (в следующем релизе)

Чтобы облегчить жизнь пользователю, мы по возможности максимально упростили базовые типы данных. Сами данные любого типа хранятся одинаково — как последовательность байтов, а базовый тип определяет формат вывода, правила сравнения и валидации и прочее, что скрыто от пользователя. Например, пользователю не нужно задумываться заранее, сколько у него будет знаков после десятичной точки в каждом реквизите. Можно вводить числа с любым количество знаков, и в подавляющем большинстве случаев (10-12 знаков до или после запятой) это будет корректно работать без лишних вопросов (по умолчанию для SIGNED выводится 2 знака после запятой). При необходимости вывода чисел в нужном формате, можно привязать эти форматы в виде дополнительных реквизитов и использовать их в созданных пользователем шаблонах, но об этом позже.

Типы названы соответствующими английскими словами, чтобы программистам было привычнее начать с ними работать. При желании можно перевести их на человеческий язык, подправив один справочник в Редакторе типов. Пока мы не наблюдали трудностей с пониманием значений типов ни у какой категории пользователей Интеграла, и есть подозрение, что они как раз появятся, если мы изобретем русскоязычные заменители. Разумеется, обучая пользователя MS Excel работе с Интегралом, мы не используем понятия сущность, реквизит и тому подобные, а оперируем более простыми понятиями, такими как таблица, поле, колонка и т.д.

Допустим, мы работаем с Клиентами, у которых есть имя, телефон, email и адрес. Все эти новые для Интеграла термины, которые также можно назвать объектами, типами или сущностями, добавляются с помощью такой простейшей формы:



Так в Интеграле задаются все термины бизнеса. Затем из них собираются все сущности, с которыми бизнес имеет дело, и они образуют структуру данных. Некоторые термины, такие как телефон, email, адрес уже есть в Интеграле, и их можно использовать в своих целях.

Реквизиты


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



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

Все созданные в редакторе типов объекты немедленно доступны для использования: можно создавать экземпляры этих типов, заполнять их реквизиты. Объекты находятся в Словаре в виде списка всех независимых сущностей, то есть тех типов, которые не являются ни чьими реквизитами. Так мы видим в списке тип Доступ, потому что одноименный реквизит Доступ у типа Объект является ссылкой на независимый справочник Доступов. А вот типы Объекты и Меню отсутствуют в списке, так как напрямую подчинены типу Роль:



Экземпляры объектов Словаря доступны в виде таблиц, к которым можно применять фильтры для поиска нужных записей (по любому реквизиту), списочное удаление, экспорт и импорт. Кликнув «Пользователь» в Словаре, можно увидеть список всех экземпляров типа Пользователь:



Для редактирования записи в таблице нужно нажать на значение в первой колонке этой таблицы, в данном случае первое поле — «Пользователь».

Примечание: Возможность удаления, редактирования, экспорта, видимость реквизитов и другие ограничения в работе с объектами задаются в Роли пользователя с точностью до отдельных реквизитов. Также можно применить маски к значениям объектов и их реквизитов для ограничения доступа по значению.

Для добавления новой записи сначала указывается значение экземпляра этого типа:



Затем заполняются реквизиты этого типа:



К реквизитам применяются простейшие правила, заданные в редакторе типов: email и Имя — обязательные для заполнения поля, Дата — автоматически вычисленное значение текущей даты.

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


Реквизит — ссылка на тип


В этом случае всё просто и привычно: можно создать тип Категория, а затем, кликнув на него, выбрать опцию «Создать ссылку»:



В редакторе типов получится два типа с именем Категория: сам тип и ссылка на его экземпляр.



В списке реквизитов их также будет две, ссылка отмечена префиксом в виде стрелки:



Добавив ссылочный реквизит, мы получим две связанные таблицы, и Интеграл выстроит их в редакторе типов согласно иерархии (ссылочные и табличные реквизиты располагаются правее своего родителя):



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



Мы можем использовать в качестве реквизита любой другой зарегистрированный тип, указывая ID его экземпляра в виде числового реквизита и подставляя этот ID в ссылку на форме редактирования или в отчете. Например, можно сделать так, что объектом охраны будут люди, автомобили, здания или авторские права.

Реквизит — подчиненная таблица


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



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



Описанные выше способы создания типов, добавления реквизитов и двух видов связей уже позволяют создать любую структуру данных, возможную в реляционной базе данных.

Запросы


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

Например, выборка всех доступов всех пользователей сервиса согласно их ролям будет сводиться к простому перечислению полей данных. В меню Словарь выбираем объект Запрос:



Задаем имя нашему запросу и нажимаем Добавить:



Заходим в реквизит Поле данных созданного запроса:



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



У созданного поля данных Пользователь есть множество реквизитов, которые нам пока не нужны (мы их обязательно рассмотрим позже в этой статье). Сохраняем запись как есть:



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

В таблице полей данных появилась строка Пользователь, а список доступных объектов сократился — теперь в нем есть только объекты, связанные с Пользователем. Выбираем Роль, которая нам нужна из постановки задачи:



Теперь в списке появились Объекты и Меню, связанные с Пользователем через Роль. Добавляем Объекты:



Наконец, добавляем описание уровня доступа, которое является реквизитом Доступа:



Всё, наш запрос готов, он включает четыре поля данных из четырех разных таблиц.



Кликнув имя запроса, мы перейдем из списка полей на форму самого запроса, где есть кнопка «Сформировать». Эта кнопка — реквизит, запускающий запрограммированное контекстное действие, в данном случае — вызов формы отчета с указанием ID этого отчета (запроса).



Запущенный запрос вернет отчет обо всех пользователях, ролях, объектах и уровнях доступа:



Мы не задумывались о связях между таблицами объектов и сделали этот отчет меньше чем за минуту. Это достаточно простой отчет, но он отражает возможности конструктора запросов. Отчет можно отфильтровать по значениям полей, а также выгрузить его в Excel.

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

В некоторых случаях вам может понадобиться указать свои правила объединения таблиц, как вы привыкли это делать при написании SQL-запросов, и Интеграл позволит вам это сделать. Об этом я расскажу далее в этой статье.

Шаблоны интерфейса пользователя


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

Обработка HTML-контента на основе шаблонов производится на сервере, и каждое действие пользователя приводит к формированию новой страницы. Изначально в интерфейсе всего 6 шаблонов форм — по одному на каждый режим работы плюс одна главная страница.

Формы имеют следующее назначение:
  • Главная страница, как правило, содержащая стили и основное меню (или несколько);
  • Редактор типов, отображающий структуру данных;
  • Словарь — список всех независимых типов;
  • Список экземпляров выбранного типа (списки пользователей, ролей, объектов, рассмотренные выше);
  • Форма редактирования экземпляра типа;
  • Отчет.

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



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

На момент написания этой статьи точки вставки, используемые в шаблонах, бывают трёх видов:
  • разметка блоков шаблона;
  • поле данных;
  • файл.

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

На рисунке ниже приведен HTML-код шаблона страницы базового интерфейса (main.html — главная страница с меню), где зеленым цветом выделены границы блоков TopMenu и File. Когда парсер будет обрабатывать этот шаблон, он обратится к базе за запросом TopMenu и получит набор записей, в которых он попытается отыскать поля данных TOP_MENU_HREF и TOP_MENU. Результат выполнения запроса — отчет — обведен на рисунке серой рамкой. Значения этих полей будут подставлены в шаблон вместо имен этих полей в фигурных скобках. Фрагмент шаблона, выделенный серым на рисунке, будет повторен столько раз, сколько записей вернет набор TopMenu. Сами теги <!— Begin:… —> и <!— End:… —> не будут включены в результат.



Далее парсер встретит конструкцию <!— File: a —>, вместо которой будет вставлено содержимое файла шаблона с именем, определенным параметром a, предварительно также обработанного парсером. В результате на странице будет отображено меню, состоящее из доступных роли пользователя пунктов, и рабочее место согласно выбранному ранее пункту меню. Кликнув нужный объект, пользователь перейдет к другому рабочему месту, точно так же собранному парсером, но с другой формой в блоке File:



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

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



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

При желании можно создать Single-Page Application, используя Интеграл и один из современных реактивных UI js фрэймворков, например Vue или React.

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

Немного глубже и подробнее о вышеописанном


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

Напомню, что пока сервис существует в достаточно примитивном виде, а некоторые моменты выглядят откровенно наивно. Мы видим это и работаем над этим. Наш Change request log сейчас содержит работ на 500+ часов для доведения его до сервиса приличного уровня.

Индексирование и целостность данных


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

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

Лирическое отступление про оптимизацию
Обычно система обрастает индексами и оптимизациями по мере появления проблем, при этом (как правило, в спешке) выделяется самое проблемное место и лечится именно оно. Менее проблемные места продолжают потреблять ресурсы, создавая нагрузку на сервер в таком большом количестве мест, что лечить их точечно достаточно дорого, и часто это таит дополнительные риски. В результате у нас есть время подумать об этом в те бесконечные секунды, когда загружается страница корпоративного портала, JIRA или крутится AJAX-spinner интернет-банка.

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

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

Такое индексирование требует больше места для хранения данных, чем выборочно индексированная база (в 2-3 раза), однако экономит силы и нервы при разработке и поддержке, что в деньгах получается несравнимо дешевле. Эти накладные расходы увеличиваются линейно, а в ряде случаев получаются меньше, чем расходы на хранение данных в базе с множеством составных индексов, в платформе 1С с её GUID и денормализацией или, тем более, в CMS вроде Битрикс с его инфоблоками.

Чтобы не разводить теоретический холивар про индексы и производительность, мы развернули тестовый стенд, где можно посмотреть и потрогать, как это работает на нескольких миллионах записей. Этот стенд подтормаживает иногда, как и любая база с миллионами записей и десятками одновременных запросов, поэтому адекватное представление о производительности там получить можно.

Интеграл обеспечивает минимальные средства поддержания целостности данных, например, не позволяя удалить справочное значение, если оно используется в качестве реквизита. То же самое относится к типам и реквизитам объектов — нельзя удалить тип или реквизит, если имеются его экземпляры или он упоминается в запросе или роли. Также есть проверка на уникальность добавляемых объектов, но только в самом простом случае: если добавляется неуникальное значение объекта, отмеченного уникальным в Редакторе типов.

Из ядра Интеграла намеренно вынесены такие вещи как триггеры, ключи, constraint’ы и многое другое. Также было скрыто всё, что было возможно скрыть от пользователя, например, системные ID записей (это бывает непривычно для программиста, но достаточно быстро усваивается). Тем не менее, при желании любой ID можно достать из системы, а в ряде случаев это просто необходимо, для общения по API, например.

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

Поля данных: подробнее
Рассмотрим в общих чертах назначение реквизитов Полей данных:
Имя в отчете — название колонки в выводимом отчете, по умолчанию — название объекта, указанного в Поле данных.
Формула задает вычисляемое выражение или псевдоним колонки. Здесь можно использовать значения других полей, произвольные операторы и функции, допустимые в языке SQL (той базы данных, на которой развернут Интеграл, в данной статье это MySQL), а также вложенные запросы. Интеграл предоставляет доступ к очень мощным и гибким средствам для различных вычислений.
Значение (от), Значение (до) — диапазон значений (для дат и чисел) или маска (для текста). Правила фильтрования и другие возможности использования этих полей подробно описаны в Руководстве пользователя Интеграл.
Функция — функция, применяемая к значению поля. Может быть агрегирующая: AVG (среднее), COUNT (количество), MAX (максимальное), MIN (минимальное), SUM (сумма), тогда группировка значений, посчитанных этой функцией, происходит по всем полям, в которых не используется агрегирование (не указана одна из перечисленных функций).
Функция (от), Функция (до) — диапазон значений (для дат и чисел) или маска (для текста), применяемые после вычисления функций, указанных в поле Функция (аналог ключа HAVING в SQL), в остальном работает аналогично реквизиту Значение.
Скрыть — если поставить галку в этом поле, то соответствующая колонка не будет отображена в отчете, хотя ее значение может использоваться для вычислений, фильтрования и сортировки отчета.
Формат — конечный формат отображения поля. Служит для приведения значения к нужному виду.
Сорт. — указатель последовательности и направления сортировки отчета. Отрицательное число здесь даст обратную сортировку (по убыванию значений).
Итог — агрегирующая функция, применяемая к значениям колонки отчета. Если указана функция хотя бы в одной колонке, то в отчете выводится итоговая строка с соответствующими значениями.
Присвоить — см. следующий раздел.
Alias — используется при ручном объединении таблиц для разделения их под разными именами.


Запросы на изменение данных


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

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

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



Изменение данных


Для начала проставим примечание «Осень 2017» для всех клиентов, с кем были заключены договоры осенью 2017 года. Для этого составим запрос, отбирающий таких клиентов, и выглядеть он будет примерно так:



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



Теперь для этих клиентов зададим новое значение реквизита Примечание (реквизит «Присвоить»), а также дадим именам колонок более симпатичные заголовки:



Запустив наш обновленный отчет, получим подсказку, какие изменения будут внесены в данные этим запросом:



В появившейся колонке «Выполнить» мы видим, как будут изменены данные, и, похоже, мы можем потерять старое значение примечания к клиенту Дмитрий М. Чтобы не допустить этого, изменим реквизит «Присвоить», применив функцию языка SQL, которая сцепит существующий текст с новым. Мы присвоим псевдоним MEMO этой колонке, и по этому псевдониму сможем подставить ее значение в функцию CONCAT(), сцепляющую фрагменты текста:



Теперь запрос сделает точно то, что мы хотим:



По нажатию «Выполнить» запрос внесет изменения в базу данных, выдав соответствующий отчет:



В Словаре, в таблице клиентов мы увидим новые данные по клиентам:



У вас может возникнуть вопрос: что будет, если какой-то объект встречается в отчете больше одного раза, и мы пытаемся его изменить. Ответ: объект будет изменен только 1 раз. Например, в следующем отчете мы добавляем Примечание клиента, который упомянут в нескольких строках отчета, и Интеграл выполнит изменение только 1 раз для каждого клиента:



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

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

Добавление записей


Теперь продемонстрируем создание новых записей. Пример: нам нужно запланировать на полдень 1 февраля 2018 года встречу со всеми клиентами в статусе «Клиент». Создадим такой запрос:



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



В Словаре во Встречах Клиентов появятся эти записи:



Удаление записей


Для удаления записей достаточно присвоить им пустые значения — "". Пример удаления записей по встречам весьма прост:



Интеграл не тратит место на пустые значения, поэтому записи будут просто удалены, со всеми своими реквизитами и подчиненными таблицами, если таковые есть:



Использование запросов к внешним источникам


Интеграл позволяет обратиться к внешним системам (сайты, API, файлы и т.д.) по протоколу http(s) во время выполнения запроса. Для этого необходимо задать шаблон URL внешнего источника в поле URL отчета (в этом примере я переименовал тип Запрос в Отчет в Редакторе типов). В шаблоне можно использовать значения полей отчета, заключив их имена в квадратные скобки.



Далее при выборе колонок отчета можно задать им имена, и значения этих колонок будут подставлены в шаблон URL:



Функция abn_URL заменит содержимое своего поля на результат выполнения запроса к полученному URL, вычисленному для каждой строки отчета. В результате выполнения, например, заданного выше запроса к API поставщика SMS-сервиса мы получим ответ сервиса с идентификатором отправленного сообщения, которое придет на заданный нами телефон [phone] получателю с именем [name]:



Результат запроса к URL можно также сохранить в базе, присвоив его значение какому-либо полю.

Пример задачи с составными типами


Напоследок хотелось бы привести пример, который почему-то сильно впечатлил нашего клиента из среды 1С — задача про составные типы. Задача была сделать отчет об операциях в разрезе разных аналитик, состав которых зависел от набора счетов в операции. Для этого отчета пришлось написать немного javascript в пользовательском интерфейсе для простоты восприятия, формы со всем этим безобразием (сверстано быстро и грязно, простите) доступны на Гитхабе: Aggregate Types.

Итак, дан план счетов с указанием набора аналитик для каждого счета (на рисунке — фрагмент плана):



План счетов был импортирован в Интеграл, а объекты аналитик — типы, имеющие набор реквизитов, были созданы в Редакторе типов, например:



Номенклатура — иерархический справочник со ссылкой на родительский элемент.

Далее в Редакторе типов мы создали тип Операция со счетами Дт и Кт, для которых в свою очередь задан допустимый набор объектов аналитики:



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

При заведении операций можно задать аналитику согласно вовлеченным счетам и её фактическим параметрам:



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



Мы не хотим заставлять конечного пользователя работать с базовым интерфейсом Интеграла даже в прототипе его приложения, поэтому сверстали для него такую форму ввода. На самом деле во время задания аналитик добавляются и удаляются записи в Поля данных Запроса «Отчет по аналитикам», и вот как это же выглядит в Словаре:



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

Результат отчета — это сумма операций для каждой комбинации аналитик:




Бизнес-ориентированность


Основная задача Интеграла для широкого пользователя: дать ему возможность ворочать своими данными напрямую, не применяя или даже не зная языков программирования и теории баз данных. Так в свое время появился язык SQL, который предлагал любому бухгалтеру самостоятельно работать с данными на человеческом языке. Мы идем тем же путем, но стараемся обойтись и вовсе без языка и теорий, поскольку любая необходимость делать нечто, не касающееся бизнеса, отталкивает человека от использования инструмента автоматизации.

Девиз Интеграла: «не сложнее, чем в Excel». Интеграл может заменить Excel более гибким и защищенным средством хранения и обработки данных. Кто-то переживает, что это SaaS? Спросите его, не пересылает ли он по почте свои эксели и не хранит ли их в гуглодоксах, то есть сервисах, которые профессионально умеют шерстить данные, выуживая из них всю нужную информацию для себя и уполномоченных служб?

В первую очередь это сервис небольшого бизнеса, в котором зачастую владельцу приходится самому вести разработку или как минимум управлять ею. IT-составляющая критически важна для компании, поскольку именно она определяет маневренность и гибкость бизнеса. Мы стараемся дать возможность начать работу сразу, не отвлекаться на непрофильные темы и смочь всё в корне переделать при необходимости. Поменялся принцип учета? Выверни всю модель наизнанку, выкинь лишнее и добавь нужное! Интеграл позволяет сделать это быстро и достаточно наглядно.

Зачем всё это нам?


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

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

Ядро Интеграла достаточно компактно, а низкоуровневая работа с данными по нашим расчетам может быть вообще выполнена в железе. Прощайте, Meltdown и Spectre; здравствуй, импортозамещение… Неожиданно? А между тем в IT уже давно не происходит ничего принципиально нового (да простят меня апологеты квантовых компьютеров, но до практического применения им еще далеко), и плох тот мечтатель, который не стремится сделать что-то эдакое на практике. Архитектура сервиса в корне отличается от существующих платформ, и, мы верим, может изменить мир IT, как изменило его, например, появление открытой архитектуры IBM PC.

Сервис активно развивается только последние пару лет, и мы видим, что при таком небольшом (и нестабильном, ведь всем нужны деньги) коллективе нам до нормального продукта работать еще декаду, а команде уже приходится жертвовать многим для продолжения проекта. При этом в самом направлении мы видим несомненные перспективы, что, в частности, побудило написать эту статью — мы хотим сотрудничать со всеми, кто готов развивать, улучшать и популяризировать подход Интеграла.

Ссылки


Руководство разработчика

Регистрация своего ознакомительного экземпляра базы на сервисе: https://tryint.ru

Комментарии (47)


  1. lair
    17.01.2018 12:31
    +2

    "еще один конструктор", еще один стандартный набор вопросов:


    1. что с использованием удобной мне системы управления версиями всех артефактов разработки?
    2. что с автоматизированным тестированием и CI/CD?
    3. что со средствами рефакторинга?

    И еще я поискал в статье, но что-то не нашел: а как же и на каком языке писать пользовательский код (например, мне надо, чтобы при смене статуса с А на Б и еще пяти условиях происходил такой-то набор действий)?


    1. lair
      17.01.2018 12:52
      +1

      … в эту же кучку типовых вопросов: а что вообще с коллективной работой и переносом решений между средами (разработческая/тестовая/боевая)?


    1. leotsarev
      17.01.2018 12:53

      Я проглядел руководство разработчика, и похоже этого просто нет.
      Можно делать все, что умеет конструктор Интеграла, плюс можно использовать HTML-шаблоны и класть на них JS, плюс по каким-то событиям можно дергать внешние УРЛы.


      1. lair
        17.01.2018 12:54

        Ну тогда до гордых званий "технологическая платформа" и "информационное ядро" еще прыгать и прыгать. Я уже давно не встречал в реальных бизнес-приложениях end-to-end-задачи, где можно было бы обойтись без пользовательского кода.


        1. leotsarev
          17.01.2018 12:58

          По руководству разработчика выглядит так.
          Нужно создать ОТЧЕТ все сущности со статусом А.
          В нем создать волшебную колонку, которая присвоит значения
          image


          1. lair
            17.01.2018 13:00

            Не решает задачу "по нажатию кнопки "выставить счет" проверить n условий, слазить во внешний сервис за налогами, создать счет, сформировать в нем строки, сгенерировать ссылку на оплату".


      1. lair
        17.01.2018 12:58

        Но подождите, написано же "разумеется, при желании вы можете вмешаться и скорректировать работу ядра в той части, которая касается бизнес-логики". И как же?


      1. UltimaSol Автор
        18.01.2018 08:28

        Еще есть экспорт и импорт структуры и данных. То есть, можно набросать модель, выгрузить её и загрузить в другой экземпляр базы.


    1. leotsarev
      17.01.2018 12:53
      +1

      Как говорится АААААА


      Основной принцип Интеграла: его программист не обязан знать язык программирования или теорию баз данных, а максимальная требуемая квалификация не превышает уровень пользователя MS Excel. Интеграл позволяет решать любую задачу, оперируя только терминами бизнеса и не неся никаких накладных расходов при постановке задачи и ее выполнении.


      1. lair
        17.01.2018 12:56

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


    1. UltimaSol Автор
      17.01.2018 14:11

      Это не конструктор из кубиков, это конструктор самих кубиков. То есть, по вашим трем пунктам: разработчик всё это может сделать сам здесь же, в удобном ему виде.
      Версии и тест-план с соответствующими скриптами можно хранить в этой базе, как в любой другой. Пульт управления придется сверстать, да, как в любой другой среде разработки.

      Как я оговариваюсь в статье (пару раз), пока сервис не предлагает наработок по визуализации всего этого, а предоставляет чистое поле, как если бы вы взяли Python, PostgreSQL и Apache, но упрощает работу с базой данных и разворачивание самой среды.

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


      1. lair
        17.01.2018 14:17

        То есть, по вашим трем пунктам: разработчик всё это может сделать сам здесь же, в удобном ему виде.

        Как я сделаю хранение версий в git? Это удобный мне вид.


        Пульт управления придется сверстать, да, как в любой другой среде разработки.

        Вот как раз "в любой другой среде разработки" это уже есть из коробки. Окей, не в любой, но в разумном большинстве.


        Пользовательский код реализуется Запросами, которые могут многое, в том числе запускать другие запросы по заданным событиям (смены статуса А на Б).

        Приведите пример "запроса", реализующего описанную выше функциональность:


        1. по нажатию кнопки "выставить счет"
        2. проверить n условий (валидность заказа)
        3. слазить во внешний сервис за налогами
        4. создать счет с учетом налогов и дисконтов и сформировать в нем строки
        5. сгенерировать ссылку на оплату
        6. отправить ссылку на email клиента

        Как я оговариваюсь в статье (пару раз), пока сервис не предлагает наработок по визуализации всего этого, а предоставляет чистое поле, как если бы вы взяли Python, PostgreSQL и Apache,

        Если бы я взял питон, у меня были бы текстовые файлы, которые я могу положить под VCS, на которых я могу гонять написанные мной же тесты, и для всего этого уже есть инструментарий. Потом я могу это же положить в пайплайн развертывания, и для этого тоже есть инструментарий.


        1. UltimaSol Автор
          17.01.2018 20:31
          -2

          Приведите пример «запроса», реализующего описанную выше функциональность:

          • по нажатию кнопки «выставить счет»
          • проверить n условий (валидность заказа)
          • слазить во внешний сервис за налогами
          • создать счет с учетом налогов и дисконтов и сформировать в нем строки
          • сгенерировать ссылку на оплату
          • отправить ссылку на email клиента


          Если вы внимательно читали статью, то видели там про возможности:
          • проверки условий против данных всех доступных таблиц (проверить n условий);
          • делать внешние запросы (слазить во внешний сервис, отправить email);
          • делать вложенные запросы, которыми в том числе можно создавать записи (создать счет с учетом налогов и дисконтов и сформировать в нем строки);
          • и, разумеется, делать вычисления (сгенерировать ссылку на оплату).


          Примеры есть в тексте статьи, и из них можно собрать тот запрос, о котором вы говорите.


          1. lair
            17.01.2018 21:00

            Примеры есть в тексте статьи, и из них можно собрать тот запрос, о котором вы говорите.

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


      1. lair
        17.01.2018 14:28

        Это не конструктор из кубиков, это конструктор самих кубиков.

        Что-то вы себе противоречите:


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


  1. dezconnect
    17.01.2018 12:52

    Переизобретение EAV. Что кстати является антипаттерном и на больших объемах данных можно поиметь немало проблем с производительностью БД.


    1. UltimaSol Автор
      18.01.2018 08:21

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


      1. lair
        18.01.2018 09:21

        Линейной, серьезно? Обычный индекс в БД дает логарифмическую, а некоторые СУБД обещают и вовсе константный доступ.


        1. UltimaSol Автор
          18.01.2018 11:34

          В идеальном мире — да, логарифмическая. В Интеграле тоже логарифмическая.
          Однако, с ростом сложности и объема системы в какой-то момент начинаются проблемы, и часто даже случается коллапс. Для привязки к конкретной метрике мы и говорим «не хуже линейной», имея в виду, что линия не будет пересечена.

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


          1. lair
            18.01.2018 11:37

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

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


  1. VolCh
    17.01.2018 13:21
    +1

    Здесь вы можете собрать веб-приложение, не изучая язык программирования: мы оперируем только бизнес-терминами и формулами, не сложнее, чем в MS Excel

    Может не очень внимательно прочитал статью, но не заметил, а сценарии, бизнес-процессы, воркфлоу как-то реализованы? Ну хотя бы такой:


    • Менеджер по продажам заполняет заявку на отпуск товара клиенту
    • Система проверяет наличие на складе
    • Если на складе товара достаточно, то создаёт резерв под заявку
    • Если товара на складе недостаточно, то отменяет заявку на отпуск
    • После создания резерва менеджером создаётся счёт на оплату с конкретным сроком оплаты
    • При неоплате в течении срока или явном отказе резерв и заявка отменяются
    • При оплате товар из резерва переходит в службу доставки
    • После доставки заявка на продажу закрывается как исполненная

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


    1. UltimaSol Автор
      18.01.2018 00:24

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


      Я помогаю сейчас знакомому рекрутеру делать стартап для массового подбора персонала.
      Там есть приличный бизнес-процесс, включающий переходы откликов кандидатов по статусам, планирование интервью, рассылку email и смс, работу с вакансиями (набор этапов, трёхуровневые специализации, скрипты, тайм-слоты встреч, права, и т.д. и т.п.) и сайтом Хэдхантер (HH). Фрейм HH написан отдельно, используется как сторонний сервис, внедренный в интерфейс, остальное — в Интеграле. Так вот, есть формы вакансии, отклика и прочие, состоящие из блоков, которые включаются/выключаются и совершают действия (вызывают запросы, запрашивают и сохраняют данные) в зависимости от статуса отклика или иного контекста. Приложение «ведет» пользователя, ограничивает, не дает спотыкаться.
      Могу показать как это работает по скайпу, со всеми запросами, исходниками и формами. В целом, всё как в обычном приложении, но без python, php, nodejs.

      Построителя workflow из кубиков пока нет. Пока нет.


      1. lair
        18.01.2018 00:28

        В целом, всё как в обычном приложении, но без python, php, nodejs.

        А как же? Накликиванием в интерфейсе? Или свой язык?


        1. UltimaSol Автор
          18.01.2018 08:03

          Нет языка.
          Интерфейс свёрстан в HTML (css, js для оформления), программирование делается запросами Интеграла.


          1. lair
            18.01.2018 09:22

            Ну то есть накликано. Что возвращает нас к вопросу версионирования, совместной разработки и переноса артефактов.


            1. UltimaSol Автор
              19.01.2018 23:23

              Статья про архитектуру и подход, если что.

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


              1. lair
                20.01.2018 00:24

                Ну так описанные мной проблемы — это как раз следствие вашего подхода, интерфейс тут ни при чем.


                А уж если говорить об архитектуре… про нее в статье минимально. Ну да, мы поняли, что у вас там РСУБД. Есть полтора слова про то, как вы данные храните (хотя и без важных деталей). Дальше, судя по комментариям, просто монолитный PHP. Это статья про архитектуру?


      1. VolCh
        18.01.2018 12:49

        Спасибо за ответ. Что приложение ведёт пользователя, это хорошо. Но есть ли механизм нотификации пользователей о действиях других пользователей? Грубо, форма "ваш заказ в обработке" автоматом меняется на форму "ваш заказ утверждён, оплатите счёт в течение трёх часов" и, крайне желательно, без опроса сервера каждую секунду. А таймауты для действий? Та же форма "оплатите счёт" меняется на "извините, ваш заказ отменён, поскольку вы его не оплатили в течении трёх часов".


        А интеграция с внешними активными сервисами, теми же платежными системами, как-то поддерживается? Когда пользователь внешней системы в её интерфейсе инициирует ту же оплату.


        1. UltimaSol Автор
          19.01.2018 23:05

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

          Нотификацию можно сделать множеством способов, например:
          а) выбирать из базы и отображать в интерфейсе (форме с меню) напоминания о подошедшем сроке запланированных событий
          б) отправлять email или СМС в момент наступления события для побуждения к дальнейшим действиям (менеджеру об оплате заказа)
          в) запустить планировщик, выбирающий и отправляющий напоминалки или вызывающий сторонний сервис раз в 1-2-5 минут

          В том стартапе, о котором я говорил, применены все эти способы для разных событий.

          Посмотреть как это сделано
          Пример для отправки СМС и показа текущих активностей

          Пульт, перезагружающийся раз в 45 секунд:



          HTML-код пульта:



          Отчет intSmsPult, использующийся в пульте:



          Колонки отчета (Поля запроса, их можно назвать в Редакторе типов как угодно):



          Присвоение пустого значения, отмеченное красным кругом, сбрасывает флажок запланированного события, чтобы СМС отправлялось 1 раз.

          Напоминалки в пользовательском интерфейсе

          Действия, срок совершения которых наступил, будут отображаться на форме (отмечено красным):



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



          1. lair
            20.01.2018 00:28
            -1

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


  1. michael_vostrikov
    17.01.2018 14:10
    +1

    В форме логина self-xss. Некритично, но показывает качество кода.


    1. UltimaSol Автор
      17.01.2018 22:18

      Спасибо! Исправим.


  1. qwert_ukg
    18.01.2018 06:28

    На чем это написано?


    1. UltimaSol Автор
      18.01.2018 07:57

      Сейчас это PHP и MySQL.


      1. qwert_ukg
        18.01.2018 09:00

        Фреймворк?


        1. UltimaSol Автор
          18.01.2018 11:28

          Интеграл сам и есть фреймворк (т.е. его концепт, прототип).

          Ядро его достаточно компактно, это всего один скрипт, начинали его писать давно, а сейчас его почти не трогаем, поэтому обходимся без фреймворка.


          1. qwert_ukg
            18.01.2018 12:08

            Очень жаль


          1. michael_vostrikov
            18.01.2018 12:36

            Судя по многочисленным точкам входа (login.html, index.php, register.html, register.php) и половине шаблонов, начинающихся с тега <html>, вы не знакомы с фреймворками и не умеете их писать.


            1. qwert_ukg
              18.01.2018 13:07

              Да вроде сразу видно что велик


  1. retran
    18.01.2018 11:50

    А чем это лучше Access, Fox Pro, OpenXava, etc?
    Не говоря уже о настоящих технологических платформах типа Axapta или 1С?


    1. UltimaSol Автор
      18.01.2018 12:31

      Это не «лучше» или «хуже», это «другое».
      Ответ также сильно зависит от целевой аудитории. Для пользователей Access и FoxPro здесь легче начать работать.
      В сравнении с Axapta и 1С для несложных задач заметно легче будет само решение. Для сложных задач — будет значительно дешевле менее трудоемко.


      1. lair
        18.01.2018 12:37

        Для сложных задач — будет значительно дешевле менее трудоемко.

        Вот для этого, конечно, хотелось бы какую-то аргументацию. С примерами.


      1. Apatic
        18.01.2018 15:06

        В сравнении с Axapta и 1С для несложных задач заметно легче будет само решение


        Насчет этого тоже не уверен.
        Тоже хотелось бы на каком-нибудь примере разобрать.


      1. retran
        19.01.2018 12:16

        Ок, вот классическая задача — склад, товары на складе, движение товаров, отчет по остаткам, время построения отчета не зависит от количества записей о движении товаров. На 1С это делается (включая UI) без кода вообще.


  1. Naf2000
    19.01.2018 22:04

    1С тоже вначале декларировала «доступно и всерьез». Каждый бухгалтер сможет запрограммировать процессы под себя. А вышло вон оно как: на все программисты 7.7 могут освоить клиент-сервер 8.3.


    1. UltimaSol Автор
      19.01.2018 23:13

      Если бы люди не пытались сделать мир лучше, несмотря на летящие в них помидоры, то было бы в мире меньше всего хорошего.

      Мы хотим попробовать, имеем право, стараемся. И будь что будет.


  1. geekmetwice
    20.01.2018 04:56

    Это очень громоздкая и бестолковая статья, написанная типичным программистом. Больше напоминает документацию по продукту со вставками пояснений, чем вводную статью. Кто вы такие? Правильно — «никто» с продуктом «Интеграл», о котором мы впервые слышим. Тогда к чему всё это размазываение про роли, таблицы?.. Столько никчемушных подробностей, будто прям щас все бросятся писать формы в вашем ЛЕГО! Увы, для того, чтобы реально заинтересовать людей, нужно не сыпать терминами и заваливать деталями, а высокоуровнево и доходчиво объяснить, ЧТО вы сделали, для кого и почему ваш стотыщный велосипед лучше других. Не лучше тем, что у вас есть «больше фич», а чем принципиально вы превосходите другие конструкторы. Ничего этого в статье не увидел — такую портянку дальше первой страницы не осилил. Материал — отстой.