Управление состоянием для шаблона MVC и работы с данными объекта

05.04.20

Разработка - Работа с интерфейсом

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

Скачать файлы

Наименование Файл Версия Размер
sm1_0_0_9
.dt 4,31Mb
3
.dt 1.0.0.8 4,31Mb 3 Скачать

Оглавление

 

Интерфейс бизнес-приложения

Связанные данные и расчет зависимостей

Связи параметров выбора

Обработка события ПриИзменении

Обобщенная обработка

Граф зависимостей

Отражение состояния в интерфейсе

Условное оформление

Управление видимостью и доступностью

Группировка данных и элементов

Функции состояния

Управление состоянием

Модель управления формы

Модель объекта и программный интерфейс

Оптимизация

Зацикливание

Ошибки

Структура модулей

Параметры состояния

Связи

Слабые связи

Параметризация

Элементы и группы

Проверка заполнения при вводе (история) и при копировании

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

Сценарии

Поставка и порядок внедрения

Вывод

Полезные ссылки


 

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

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

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

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

С версии 8.2 в платформе 1С появилась возможность описывать связи параметров выбора. Этот механизм отлично подходит для декларативного задания связей реквизитов элементов формы. Однако существующие ограничения не позволяют в полной мере задействовать встроенный механизм.

Связи можно настраивать только на уровне реквизитов данных. Например, можно указать связь договора с организацией и контрагентом через связь соответствующих реквизитов справочника Договоры: Организация и Владелец. Если, например, у справочника Договоры нет соответствующих реквизитов, а связь образуется через отношение с табличной частью договора "Участники", то такую связь в платформе установить будет уже невозможно. Это ограничение можно обойти при использовании подсистемы Работа с данными выбора.

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

Единственный способ изменить поведение событийно-ориентированной системы - это найти подходящее событие и вставить в его обработчик нужный код на встроенном языке. Для расчета зависимостей подходящим событием является - "ПриИзменении". Так, для нашего примера, нам потребуется добавить код для обработчиков элементов формы Организация и Контрагент. Наш код должен будет делать следующее: проверить, соответствует ли связанный реквизит Договор с текущими значениями Организации и Контрагента. Если значение договора не соответствует условиям связей, то договор необходимо очистить и попробовать определить подходящее значение для новых условий. Если значение однозначно, то пусть система выберет его, иначе пусть возможность выбора останется за пользователем. Чтобы не дублировать код обработчиков события, вынесем его в отдельную процедуру - что-то типа "ПриИзмененииОрганизацииИлиКонтрагента", а в сами обработчики вставим её вызов.

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

Это вполне рабочее решение, однако есть решение получше. И это не мое решение, я его где-то подсмотрел. Оно заключается в том, что вместо написания множества обработчиков событий элементов формы вся обработка изменений реквизитов реализуется в одной процедуре с рекурсивным вызовом - что-то типа "ПриИзмененииРеквизита(ИмяРеквизита, ИзмененныеРеквизиты)". Это решение лучше предыдущего, ведь здесь не требуется писать отдельные обработчики, достаточно их назначить на вызов метода формы, который вызовет нашу процедуру. Здесь второй аргумент процедуры необходим для целей оптимизации расчетов.

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

  1. Вид операции->Договор->Статья
  2. Вид операции->Статья

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

Итак, наше второе решение с выделением общей функции не оптимально: ведь оно не может использовать топологический порядок! В следующем решении рассмотрим вариант алгоритма, построенного на описании графа зависимостей. Для работы с формой нам даже не придется придумывать где хранить этот граф, ведь можно воспользоваться связями параметров выбора в элементах формы. Однако такое решение будет нас ограничивать работой с формой. Для обеспечения общности определим хранение зависимостей для формы в ее реквизите, а для объекта - в переменной (можно воспользоваться структурой Дополнительные параметры). Полное описание такого решения представлено в статье Шаблон MVC для управляемого интерфейса.

Рассмотрим данные на примере реализации документа «Заявка на операцию» из действующей рабочей конфигурации. На диаграмме размер узла пропорционален количеству связей, синий цвет соответствует данным объекта, голубой – константным параметрам.

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

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

Распространенным простым решением для настройки формы является реализация общей процедуры что-то типа «УправлениеВидимостьюДоступностью(Форма)». Если у нас есть такая процедура, то для корректного отражения состояния в представлении формы достаточно добавить вызов нашей процедуры в конце обработчика «ПриИзменении», а также «ПриСозданииНаСервере».

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

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

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

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

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

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

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

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

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

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

«Управление состоянием» - это не только оптимизация архитектуры, но и оптимизация производительности. В прежних подсистемах не была реализована оптимизация клиент-серверного взаимодействия и все расчеты всегда производились только в контексте сервера (на стороне back-end - как принято говорить в web разработке). Однако теперь клиент-серверное взаимодействие оптимизировано как по количеству вызовов, так и по объему данных. Конечно подсистема сама не всегда точно может определить нужный контекст исполнения и поэтому для тонкой настройки механизма будет требоваться конкретное указание контекста путем определения признака «НаСервере» у параметров состояния и у элементов (объект описания элемента формы).

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

Описание модели формы заключается в описании её элементов и параметров состояния, от которых зависят эти элементы.

На примере элементов СуммаВзаиморасчетов и ВалютаВзаиморасчетов из прилагаемой демо-базы рассмотрим их настройку. Здесь реализуется следующее поведение. Если валюта документа совпадает с валютой расчетов, то сумма взаиморасчетов должна быть скрыта, т.к. значение этой суммы равно значению суммы документа и при таком условии элемент суммы взаиморасчетов будет дублировать ввод. Это же поведение дублируется для элемента табличной части ДвиженияОперацииСуммаВзаиморасчетов. Валюта взаиморасчетов при совпадении валют должна показывать заголовок, в противном случае её заголовок должен быть скрыт. В первом случае достаточно заголовка элемента Суммы взаиморасчетов, а во втором, когда элемент суммы скрыт, уже требуется заголовок элемента Валюты расчетов.

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

Настройка элементов СуммаВзаиморасчетов и ВалютаВзаиморасчетов:

    РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.СуммаВзаиморасчетов, "ВалютаВзаиморасчетов,ВалютаДокумента");
    РаботаСФормойКлиентСервер.Элемент(ЭтотОбъект, Модель, Элементы.ВалютаВзаиморасчетов, "ВалютаВзаиморасчетов,ВалютаДокумента,ДоговорКонтрагента");

Функции состояния элементов, обеспечивающие заданное поведение:

Функция СвойстваСуммаВзаиморасчетов(Свойства, Параметры) Экспорт
    Свойства.Вставить("Видимость", НЕ Параметры.ВалютаВзаиморасчетов = Параметры.ВалютаДокумента);
    Возврат Истина;
КонецФункции

Функция СвойстваВалютаВзаиморасчетов(Свойства, Параметры) Экспорт
    Если Параметры.ВалютаВзаиморасчетов = Параметры.ВалютаДокумента Тогда
        Свойства.Вставить("ПоложениеЗаголовка", ПоложениеЗаголовкаЭлементаФормы.Авто);
    Иначе
        Свойства.Вставить("ПоложениеЗаголовка", ПоложениеЗаголовкаЭлементаФормы.Нет);
    КонецЕсли;
    Свойства.Вставить("ТолькоПросмотр", ЗначениеЗаполнено(Параметры.ДоговорКонтрагента));
    Возврат Истина;
КонецФункции

Полное описание модели формы в обработчике ПриСозданииНаСервере:

 

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

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

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

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

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

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

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

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

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

В процессе расчета зависимостей есть несколько потенциальных точек отказа:

  • функция значения (параметр состояния);
  • обработчик события «ПриИзменении» (параметр состояния);
  • функция состояния (элемент формы)

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

Подсистема предполагает реализацию функции Модель в модуле менеджера объекта. Кроме описания самой настройки модели необходимо описание функций состояния, значения и обработки событий ПриИзменении. Эти функции должны располагаться в общем модуле доступном для контекста клиента и сервера. При этом функции, которые требуют для своего исполнения контекста только сервера, должны быть заключены в блоке препроцессора #Если Сервер Тогда … #КонецЕсли

Структура модуля формы

Структура модели

См. описание РаботаСМодельюКлиентСервер.Модель.

Пример создания модели в демо базе модуль менеджера Документ.ЗаявкаНаОперацию.Модель.

См. описание РаботаСМодельюКлиентСервер.Параметр

В большинстве случаев создавать отдельно параметр состояния не требуется. Параметры состояния создаются в модели неявным образом при добавлении новых связей. Однако если настройка параметра состояния по умолчанию вас не устраивает, то ее можно изменить непосредственно, обратившись к параметру через структуру модели Модель[ИмяПараметра] или безопасным образом через функцию РаботаСМодельюКлиентСервер.Параметр[ИмяПараметра].

См. описание РаботаСМодельюКлиентСервер.Связь

В описании модели связи решают все! Формально модель - это параметры состояния и их связи (для формы добавлены элементы), однако описывать параметры состояния отдельно в большинстве случаев не нужно: достаточно добавить описания связей. Система сама, на основе анализа контекста, определит описания параметров. Такой подход имеет одно ограничение: имена реквизитов объекта и формы не должны пересекаться (не относится к реквизитам табличных частей).

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

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

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

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

В следующем обработчике анализируется направление слабой связи, которое зависит от типа операции. Для внешней операции это Валюта документа->Счет контрагента, а для внутренней (конвертация валюты) – Валюта взаиморасчетов->Счет контрагента. И конечно же, если среди рассчитанных реквизитов уже есть валюта, то никакой обратной связи не требуется!

Процедура ПриИзмененииСчетКонтрагента(Контекст, Объект, ДанныеСтроки, Реквизит, ИзмененныеРеквизиты, РассчитанныеРеквизиты) Экспорт
  Если Объект.ТипОперацииБюджетирование = Перечисления.ТипыОперацийБюжетирование.КонвертацияВалюты Тогда
    ИмяРеквизитаВалюты = "ВалютаВзаиморасчетов";
  Иначе
    ИмяРеквизитаВалюты = "ВалютаДокумента";
  КонецЕсли;
  Если РассчитанныеРеквизиты[ИмяРеквизитаВалюты] = Истина ИЛИ НЕ ЗначениеЗаполнено(Объект.СчетКонтрагента) Тогда
    Возврат;
  КонецЕсли;
  РаботаСМодельюКлиентСервер.УстановитьЗначение(Контекст, ИмяРеквизитаВалюты, , ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.СчетКонтрагента , "Валюта"), ИзмененныеРеквизиты);
КонецПроцедуры

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

В предыдущей версии подсистемы существовала возможность перестроения графа зависимостей, однако в новой подсистеме это достигается путем параметризации. Так для первой связи можно указать, что свойство «Использование» определяется параметром ЭтоВнешняяОперация, а для второй – ЭтоВнутренняяОперация. Аналогично свойство «Использование» определяется и для реквизита Контрагент.

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

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

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

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

В основе адаптивности ввода лежит платформенный механизм истории выбора значений при вводе. У него есть свои ограничения. Так, если выбор значения переопределен в модуле менеджера (ОбработкаПолученияДанныхВыбора), то платформенный механизм не будет учитывать новые критерии выбора. Второе ограничение связано с тем, что платформенный механизм ориентируется на неизменность данных: т.е., например, если для данной организации и контрагента выбран договор один раз, то и в следующий раз для тех же организации и контрагента можно выбрать тот же договор, однако если в самих данных для договора поменять значение контрагента, то платформенный механизм никак это не учтет и позволит сделать уже неверный выбор. Можно рассмотреть пример и попроще. Пусть в параметрах выбора определено значение пометки удаления Ложь (отбор только не помеченных на удаление элементов), тогда если элемент пометить, то платформа не только позволит сделать выбор из истории, но и никак не предупредит, что выбранный элемент помечен на удаление!

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

Механизм проверки введенного значения активизируется для всех полей ввода с установленным свойством элемента формы ИсторияВыбораПриВводе равным Авто. Такая проверка может привести к нежелательному поведению системы. Например, мы хотим ввести в поле Сумма расчетов свое значение, тогда при проверке система рассчитает значение через кросс-курс от суммы документа и заменит им наше. Чтобы такого не происходило, необходимо для полей с числовыми данными отключать историю выбора через установку значения НеИспользовать.

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

Следующий код демонстрирует проверку данных нового объекта через метод ОбновитьДанные.

Процедура ПриКопировании(ОбъектКопирования)
  Дата = ТекущаяДата();// дата требуется для расчета кросс-курса
  РаботаСМоделью.Инициализировать(ЭтотОбъект);//  конструируется модель объекта
  РаботаСМоделью.РассчитатьПроизводныеПараметры(ЭтотОбъект);//  расчет не сохраняемых параметров
  РаботаСМоделью.ОбновитьДанные(ЭтотОбъект);//  проверка сохраняемых данных на соответствие модели
КонецПроцедуры

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

Например, при проведении документа меняется его состояние, значения которого хранится в регистре. После проведения документа требуется заново определить значение параметра «Состояние».

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

Расчет Зависимости от договора

Сценарий к разделу Модель управления формы.

Используемые зависимости модели объекта:

...
  //  Связи параметров выбора для договора
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "ДоговорКонтрагента", "Организация", "Отбор.Организация");
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "ДоговорКонтрагента", "Контрагент", "Отбор.Контрагент");
  //  Связь валюты расчетов от договора по параметру ДоговорКонтрагента. На связь наложено условие использования: для внешней операции (Оплата поставщику)
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "ВалютаВзаиморасчетов", "ДоговорКонтрагента",,, Новый Структура("Использование", "ЭтоВнешняяОперация"));
  //  Следующие связи определяют расчет суммы взаиморасчетов от суммы документа, кросс-курса
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "СуммаВзаиморасчетов", "СуммаДокумента");
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "СуммаВзаиморасчетов", "КроссКурс");
  //  Аналогичные связи для табличного реквизита сумма взаиморасчетов
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "ДвиженияОперации.СуммаВзаиморасчетов", "ДвиженияОперации.Сумма");
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "ДвиженияОперации.СуммаВзаиморасчетов", "КроссКурс");
  //  Связи, определяющие расчет кросс-курса от даты и валюты документа, валюты расчетов
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "КроссКурс", "Дата");
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "КроссКурс", "ВалютаДокумента");
  РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "КроссКурс", "ВалютаВзаиморасчетов");
...

 

Название:

Заполнение договора контрагента

Описание:

После выбора договора система заполняет валюту и сумму расчетов. Элемент формы Валюта расчетов становится недоступным для редактирования.

Предусловия:

В документе заполнены: операция Оплата поставщику, Организация, Контрагент, значение Валюты документа равна Валюте расчетов рубли. Договор контрагента не заполнен.

Основной поток:

  1. Пользователь вводит значение договора в USD
  2. Модель по данным зависимостей производит заполнение валюты расчетов
  3. Модель рассчитывает кросс-курс валюта документа -> валюта расчетов
  4. Модель заполняет сумму расчетов по рассчитанному кросс-курсу и сумме документа
  5. Модель заполняет сумму расчетов для строк табличной части аналогично 4
  6. Модель определяет список измененных элементов формы по зависимостям от измененных реквизитов
  7. Форма отображает элемент суммы расчетов, скрывает заголовок элемента валюта расчетов, отображает колонку Сумма расчетов и формирует её заголовок по шаблону: Сумма, [валюта расчетов]

 

Требования: Платформа 8.3.14 и выше для работы в тонком и веб клиенте.

Подсистема

Метаданные

Назначение

 

Общий модуль:

 

БСП.БазоваяПодсистема

 

 

УправлениеСостоянием

Общий

 

 

ОбщийКлиентСервер

 

 

РаботаСДаннымиВыбора

Обеспечивает нестандартную обработку выбора

 

РаботаСоСхемойЗапроса

Используется для описания запроса в подсистеме работы с данными выбора

 

РаботаСМоделью

 

 

РаботаСМодельюКлиентСервер

 

 

РаботаСФормой

 

 

РаботаСФормойКлиентСервер

 

Демо

Документ.ЗаявкаНаОперацию

 

 

МодельЗаявкаНаОперацию

Описание модели документа ЗаявкаНаОперацию

 

Справочники: Контрагенты, ДоговорыКонтрагентов, Организации

 

Порядок внедрения:

  1. Выгрузить конфигурацию из демо-базы
  2. Объединить с целевой конфигурацией с отбором по подсистеме УправлениеСостоянием

Подсистема "Управление состоянием" расширяет возможности определять поведение объекта и его интерфейса на основе декларативного описания параметров состояния и связей. Единая подсистема решает задачу шаблона MVC, а также позволяет описывать сложное поведение интерфейса, задавать правила проверки заполнения и очистки данных.

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

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

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

 

Проект в формате EDT опубликован на gihub.

Лучшее объяснение идеи MVC:

Другие материалы по теме в статьях Infostart.ru:

Смотрите также разбор примера.

 

Интерфейс MVC Управление формой

См. также

Богатый редактор картинок, хранимых в базе, с возможностью РИСОВАНИЯ. Редактор внешних файлов картинок. Объект, расширяющий возможности работы с картинками из встроенного языка (Три в одном) + Обработка «Стандартизация картинок»

Работа с интерфейсом Рабочее место Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Обработка предназначена для редактирования картинок в режиме «Предприятие», с возможностью РИСОВАТЬ на них. Поддерживается работа как в обычных формах (толстый клиент) так и на управляемых формах (тонкий клиент). Обработка позволяет редактировать как картинки, хранимые в базе, так и графические файлы с диска на файловой системе. Помимо базовых функций (изменение размеров, преобразование формата, обрезание картинки, повороты и т.п.) – редактор имеет богатый набор инструментов для рисования. Доступна функция вставки изображения из буфера обмена. Также обработка может быть использована из встроенного языка как объект для редактирования картинок. Объект может быть использован: на стороне клиента, на стороне сервера, из внешнего соединения. Данная обработка будет особенно полезна тем, кто вносит картинки в базу (изображения номенклатуры, фотографии физических лиц и т.п.). Функционал реализуется с использованием JavaScript и бесплатного ПО ImageMagick (без использования внешних компонент).

6000 руб.

16.01.2015    61795    43    59    

80

[Расширения] Динамическое управление видимостью и доступностью элементов форм (УФ) (8.3.6+)

Работа с интерфейсом Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Механизм «Динамическое управление доступом к элементам форм объектов 1С8» предназначен для обеспечения возможности оперативного управления видимостью и доступностью элементов форм документов и справочников продуктов фирмы «1С» «1С:Предприятие 8». Решение универсальное, встраивается в любую конфигурацию с минимальными доработками, что позволяет без проблем обновлять типовые решения.

5000 руб.

14.01.2016    54402    16    21    

42

Управление дашбордами

Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Обработка предназначена для создания и управления дашбордами.

2400 руб.

29.06.2020    16697    21    4    

35

Новогоднее оформление для 1С

Работа с интерфейсом Платформа 1С v8.3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 Бесплатно (free)

Добавьте новогоднего настроения! Расширение создает декорацию в виде гирлянды на некоторых формах объектов.

27.12.2023    10736    750    elcoan    45    

106

Конструктор HTML, CSS и javascript

Инструментарий разработчика Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

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

2 стартмани

10.04.2023    9612    151    acces969    31    

118

Модель состояния для MVC

Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

"MVC плохо применима в 1С" - познакомьтесь с моделью состояния и, возможно, ваше мнение поменяется! Представленное решение является эволюционным развитием идеи реализации MVC для 1С. В новой версии добавлены DSL для описания модели состояния, а также параметризация свойств параметров и элементов формы.

1 стартмани

05.07.2022    3665    kalyaka    2    

27

Табло очереди заказов на экран телевизора

WEB-интеграция Работа с интерфейсом Платформа 1С v8.3 1С:Розница 2 Платные (руб)

Связка из веб-приложения и расширения для 1С: Розница 2.3.

3600 руб.

29.04.2022    12080    1    5    

10
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. pm74 199 18.03.20 18:00 Сейчас в теме
интересная статья
у любой модели(системы) управления сложной логикой поведения ( в т.ч. КА ) , помимо очевидных плюсов, есть и один минус - ее очень трудно понимать без поддерживающей (графической или табличной) нотации
как в вашей подсистеме с этим обстоят дела ?
2. kalyaka 1053 18.03.20 18:55 Сейчас в теме
(1) спасибо за Ваш интерес
Я предполагаю, что к этой системе должен прилагаться конструктор. В таком конструкторе можно было бы визуально настраивать связи и генерировать код модулей формы и модели. Другое назначение конструктора: конвертация существующих форм в модель УС.

А визуализировать графически можно любыми инструментами, данные из системы можно получить из одной структуры: Модель. Графы на скриншотах в статье я делал так: в отладчике выгружал структуру во внутренний формат 1С, далее переносил в ИР (исполнитель кода) и там по структуре генерировал текстовый файл в формате dot для отображения программой graphiz.
3. pm74 199 18.03.20 19:12 Сейчас в теме
(2) да я и имел в виду конструктор
(2)
настраивать связи и генерировать код модулей формы и модели

или же просто создавать формальное описание модели которое может быть связано с представлением средствами вашей подсистемы
правда не до конца представляю как такая модель должна выглядеть
6. kalyaka 1053 18.03.20 22:48 Сейчас в теме
(3) может сделать возможность загружать описание модели из форматов json или yaml?
Второй формат может быть удобным для написания человеком. Тогда можно было бы из конструктора сохранять модель в json для вставки в код, а загружать из подготовленного человеком или другой системой файл yaml.

В коде на выбор можно было бы описывать модель через программный интерфейс - удобно в отладке и в алгоритмах или просто вставлять json для жесткой модели.
4. Vladimir Litvinenko 2869 18.03.20 19:48 Сейчас в теме
Чтобы система работала необходимо соблюдать одно условие – граф зависимостей должен быть однонаправленным и ациклическим.

Обеспечение этого требования ложится на плечи разработчика, или в подсистему встроена диагностика? (выбрасываются исключения например)


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

Вот например взять функцию Модель() из модуля менеджера ЗаявкаНаОперацию и подробно её разобрать или на Гитхабе код сдобрить комментариями. Или описать стек вызовов - как код доходит до ВыполнитьВыражениеЗначения например.


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

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

Ещё интересно как это решение заходит при командной разработке. Ведь по идее при совместном применении такого решения (и ранее опубликованных решений) нужна какая-то техническая документация. Что-то типа "делай раз - делай два - делай три - вот результат".
serge_focus; CyberCerber; +2 Ответить
7. kalyaka 1053 18.03.20 23:29 Сейчас в теме
(4)
Обеспечение этого требования ложится на плечи разработчика, или в подсистему встроена диагностика?
Я думал над этим, у меня даже такой раздел есть - "Ошибки". Подробная регистрация ошибок в такой системе очень важна, ведь код - декларативный и понять, где ошибка, можно только по описанию состояния, при котором произошла ошибка. Эту тему я буду развивать в подсистеме в сторону повышения информативности и логирования в журнале. И дело даже не просто в ошибке алгоритма, а в том, что ошибка расчета зависимостей может привести к неконсистентному состоянию объекта и это уже будет ошибка в данных.
В статье перечислены критичные точки отказа. Проверка же графа зависимостей - это такая точка отказа, которую ни с чем не спутаешь - программа вылетит с переполнением стека при попытке выполнить топологическую сортировку параметров состояния. Я сперва хотел поставить здесь проверку на зацикливание, однако алгоритм сортировки мне так понравился своей простотой и оптимальностью, что испортить его дополнительным кодом проверки у меня не поднялась рука :) Тем более, что я еще хочу сделать конструктор модели, и вот там эта проверка должна быть обязательно.
Эх, пример бы ещё кода более объемный с комментариями к коду
Проект выложен на gihub, до конца года хочу его довести до уровня полноценной рабочей эксплуатации на проде. Перед выводом на прод я планирую в демо конфигурации добавлять все больше рабочих сценариев и, конечно, же писать комментарии. Еще буду писать сценарии. Еще хочу написать конструктор. Демо, сценарии тестирования, конструктор - все это должно снизить порог понимания подсистемы.
Видимо схемы самому рисовать придётся, чтобы разобраться
С удовольствием помогу разобраться, ведь в эту систему я вложил душу :)
как это решение заходит при командной разработке
Это интересная мысль. Например есть некоторый функционал, который реализуется обработкой, представляющей АРМ. Этот АРМ реализует очень сложное поведение. Его форма разбита на отдельные фреймы, каждый из которых реализует независимую функциональность и имеет свою модель. Или пример попроще, есть сложный документ и его доработка ведется разными разработчиками. При традиционном подходе им придется решать конфликты кода, а при декларативном - делить элементы и параметры состояния.
Что-то типа "делай раз - делай два - делай три - вот результат
Это подход для быстрой разработки и моя система способствует такому подходу и дает возможность получить выгоды. То что такая инструкция необходима - согласен.
Vladimir Litvinenko; +1 Ответить
8. Vladimir Litvinenko 2869 18.03.20 23:56 Сейчас в теме
(7) Спасибо за столь серёзный подход! Если сам не смогу разобраться - задам вопросы. Но думаю что всё же посидеть в отладчике будет более правильным решением ))

Вот с применением на продуктиве большие вопросы. Без наличия документации применение на продуктиве запутанной (или кажущейся запутанной) библиотеки может быть неправильным по отношению к коллегам. Ни один программист не работает на проекте вечно и потом его сопровождать другим приходится. Поэтому нужна либо документация (как например у запутанной но задокументированной БСП), либо придерживаться KISS (хотя каюсь, у самого не всегда получается).
11. kalyaka 1053 23.03.20 09:13 Сейчас в теме
(8) Обновил статью, добавил примеры кода и ссылки по тексту. Дополнил разделы: Ошибки, проверка заполнения при вводе и при копировании, сценарии.
Vladimir Litvinenko; +1 Ответить
33. kalyaka 1053 08.04.20 22:38 Сейчас в теме
5. pm74 199 18.03.20 20:10 Сейчас в теме
было дело пытался сделать подобие конструктора для КА , идея была представить его в виде дерева и затем разложить в "плоскую" структуру , чтобы потом в коде можно было просто переходить от одного индекса к другому по условиям

а вообще презабавная штука , можно было бы озадачится на тему ндка, формальной верификации , моделей крипке и проч. , но тема слишком затратная по времени и надо зарабатывать на "хлеб насущный"
Прикрепленные файлы:
12. kalyaka 1053 23.03.20 09:34 Сейчас в теме
(5)
но тема слишком затратная по времени
Вот так получается, что мало придумать или даже реализовать что-то. Еще не мало усилий нужно приложить, чтобы донести идею до других :)
13. pm74 199 23.03.20 10:00 Сейчас в теме
(12) нужно дать простой инструмент желательно интерактивный (типа скд) , хотя даже это не факт что взлетит
как идея насчет таблицы правил , которую можно добавлять к форме в момент создания ?
14. kalyaka 1053 23.03.20 10:33 Сейчас в теме
(13) эту реализацию можно представить по типу платформенного механизма Условное оформление, обсуждали здесь
15. pm74 199 23.03.20 11:08 Сейчас в теме
(14) сейчас краем глаза посмотрел

Значительно проще сериализовать неподдерживаемое условное оформление формы (включая условия СКД) в реквизит формы, дав программисту в руки безконтекстную клиент/серверную функцию обновления по зависимому реквизиту или обновляемому контролу



Так вот, если эти две модели соединить (MVC и состояние формы), то в модуле формы ничего программировать вообще не нужно будет - весь код будет располагаться для модели в модуле Менеджера (например), а для состояния в функциях состояния.


я имею в виду что от кодирования модели можно избавиться в принципе ,
заменив это ее формальным представлением в виде справочника, регистра или чего то еще
16. kalyaka 1053 23.03.20 11:16 Сейчас в теме
(15) Будет табличное программирование :)
17. pm74 199 23.03.20 11:25 Сейчас в теме
(16) так оно уже и есть , та же скд например
18. kalyaka 1053 23.03.20 11:38 Сейчас в теме
(17) Тут несколько вопросов: что требует меньших трудозатрат со стороны программиста, насколько будет производительно решение, насколько читабельно.

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

А вот как быть с производительностью, когда на каждое состояние будет приходится несколько запросов СКД? И как реализовать эту работу в контексте клиента?
19. pm74 199 23.03.20 11:45 Сейчас в теме
(18) пример скд был надуманый , чтобы показать , что быстрая визуальная настройка снижает порог вохождения и делает подсистему более понятной для конечного пользователя

вопрос реализации пока остается открытым
20. pm74 199 23.03.20 11:51 Сейчас в теме
(18) кстати в обработке которую приложил как раз есть пример (ущербный конечно, но все таки) обработки по состояниям в контексте клиента
9. pm74 199 19.03.20 09:53 Сейчас в теме
"в плане дежурного бреда"))
написал утром обработку на тему декларативного описания модели
Прикрепленные файлы:
ВнешняяОбработка1.epf
10. CyberCerber 852 19.03.20 17:30 Сейчас в теме
Мне самому интересны такие темы, но в процессе прочтения статьи понял, что мне просто "тяму" не хватает все это понять.
Выше уже писали, было бы классно как-то больше разжевать эту тему, с конкретными примерами, потому что сама-то тема стоящая, но никуда пойти сейчас не может.
32. kalyaka 1053 08.04.20 22:32 Сейчас в теме
(10)
с конкретными примерами
Опубликовал подробный пример программирования формы с использованием подсистемы.
21. Makushimo 160 25.03.20 09:46 Сейчас в теме
Не смог прочитать статью. Почему все черное?
Это не круто. Это просто не читается. Из восприятия выпадает огромный кусок материала.
Жесть.
Ох уж эти любители темных тем ночных....
22. for_sale 971 29.03.20 07:14 Сейчас в теме
Пишите вы как-то заковыристо, конечно)

Это вполне рабочее решение, однако есть решение получше

Довольно сомнительно. Если я правильно понял, то первое решение - добавить обработчик события элементу и прописать оттуда вызов какого-то обобщённого обработчика. Второе - добавить обработчик элементу, вызвать оттуда один общий обработчик, внутри этого обработчика прописать через Если обработку. Я бы выбрал первое решение. Во-первых, второе решение не даёт ничего в плане изменяемости. Т.е. всё равно нужно добавлять обработчик новому (или старому) элементу, и всё равно нужно дорабатывать имеющийся код. Но при этом в первом решении всё добавленное можно действительно вынести и визуально в отдельную часть модуля, и семантически - вызывать добавленные модули. А во втором решении нужно коверкать существующий код обработчика. Во-вторых, в таком универсальном обработчике читабельность кода обратнопропорциональна количеству вызовов. Если форма большая и хотя бы двадцать элементов вызывают этот код, то там будет уже просто каша. Ещё интереснее будет, если есть пересекающиеся двойственные или тройственные связи. Тогда в этом общем обработчике начнутся такие пляски:
Если Имя = "Организация" Тогда
Если ЗначениеЗаполнено(Контрагент) Тогда
...
ИначеЕсли Имя = "договор" Тогда
Если НЕ ЗначениеЗаполнено(Контрагент) Тогда
Если ЗначениеЗаполнено(Организация) Тогда
Если ВидОперации = ... Тогда
...
ИначеЕсли Контрагент = Пустой И Имя = "ВидОперации" Тогда
... 
Показать


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

Ну и производительность, конечно, тоже страдает, пусть и не сильно. Если, чтобы добраться до нужного реквизита в этой веренице Если, придётся проверить 5-10-20-100 условий, особенно, если эти условия ещё и что-то высчитывают.
24. kalyaka 1053 29.03.20 14:06 Сейчас в теме
(22)
второе решение не даёт ничего в плане изменяемости
С одной стороны в 1-ом способе, вроде как, соблюдается принцип "разделяй и властвуй", с другой - увеличивается вероятность появления спагетти кода. Я в свое время на обычных формах был сторонник именно 1-го способа (см. Программирование интерфейсов в 1С или паттерн MVC для 1С), но с оговоркой о необходимости держать в уме, а лучше в комментариях граф зависимостей и придерживаться его при каскадных вызовах обработчиков.

С другой стороны, во 2-м способе не нужно прописывать каждый обработчик отдельно, достаточно установить общее действие для всех элементов формы в обработчике ПриСозданииНаСервере. Также не нужно подбирать нужный обработчик при изменениях зависимостей, т.к. он один - обобщенный.
в таком универсальном обработчике читабельность кода обратнопропорциональна количеству вызовов
Соглашусь! Вы прекрасно это проиллюстрировали в своем примере.
Ещё интереснее будет, если есть пересекающиеся двойственные или тройственные связи
Про это я упомянул в контексте решения задачи отображения интерфейса Группировка данных и элементов и то, что Вы упомянули это здесь, показывает, что задачи расчета модели предметной области и интерфейса очень похожи - и там, и там есть связи и расчет зависимостей.
Ну и производительность, конечно, тоже страдает, пусть и не сильно
Страдает, и главное не понятно как можно это оптимизировать. А если еще и решать задачу оптимизации клиент-серверного взаимодействия, то вообще становится все очень сложно.
придётся проверить 5-10-20-100 условий
Согласен! Сложность ведь ни куда не девается, она просто собралась в одном месте :)

На самом деле рассмотрение этих двух способов в статье - это прием, позволяющий поэтапно искать решения, сталкиваться с их ограничениями и, наконец, перейти к пониманию необходимости построения такой системы, у которой бы было внешнее описание по типу метаданных. Такой системой является предложенное решение Управление состоянием - здесь работа алгоритмов построена на данных описания Модели.
26. for_sale 971 29.03.20 15:49 Сейчас в теме
(24) Давайте проведём подробное сравнение обоих способов по параметрам:

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

2. Простота написания.
С другой стороны, во 2-м способе не нужно прописывать каждый обработчик отдельно, достаточно установить общее действие для всех элементов формы в обработчике ПриСозданииНаСервере. Также не нужно подбирать нужный обработчик при изменениях зависимостей, т.к. он один - обобщенный.

Извините, но, мягко говоря - нет, грубо говоря - чушь. По трудозатратам написать "ПриИзмененииДоговора()" и "ПриИзмененииРеквизита("Договор")" примерно то же самое. А вот найти нужное место, чтобы впихнуть обработку конкретного реквизита, в вашем огромном обработчике, нужно потратить небольшое, но время, в первом же способе нужно просто с нуля написать обработчик.

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

(24)
увеличивается вероятность появления спагетти кода

Почему? Не пишите спагетти - не будет спагетти) Более того, вы изначально осознанно создаёте эти самые спагетти во втором способе. Т.е. сознательно создаёте чан, куда заливаете всё, что можно.

Вы пишете об MVC, но вы его как раз разрушаете этим самым обработчиком. У теоретиков программирования это, по-моему, называется "Толстый тупой уродливый контроллер". Т.е. есть вью - это форма с элементами, есть модель - это БД и работа с нужными данными, и есть контроллер - это вот этот самый ваш огромный обработчик. Вместо того, чтобы он просто рассказал модели о том, что хочет вью, вы туда намешали и функциональностью вью, и функциональность модели. Например, если я поменяю имя реквизита с Договор на ДоговорКонтрагента, то мне нужно будет менять его в том числе и в вашем обработчике. Для первого же способа имя реквизита не имеет значения - мы из вью оповещаем контроллер (один из, нужный в данной ситуации, а не ТНЕ) о сути операции, и контроллер, не зная даже, что там у вью за элементы, как и модель, просто пробрасывает команду на модель. Сохраняется дух этой парадигмы - контроллер служит тоненькой прослоечкой, абстрагирующей команду представления для модели.

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

В общем, не убедили)
27. kalyaka 1053 29.03.20 22:17 Сейчас в теме
(26)
сравнение обоих способов по параметрам
Оба способа меня не устраивают и здесь я предлагаю другое решение - решение основанное на декларативном описании модели объекта и формы.
Вы пишете об MVC, но вы его как раз разрушаете этим самым обработчиком
MVC у меня упоминается только в названии статьи и в источниках про почитать об MVC. В самой статье ничего конкретно про MVC нет. Здесь MVC выступает в роли идеи выделения программных слоев. В примере раздела Модель объекта и программный интерфейс приводится фрагмент кода работы с объектом без формы, где поведение модели обеспечивается точно такое же как при работе из формы.
28. for_sale 971 30.03.20 06:21 Сейчас в теме
(27) MVC - это парадигма, которая помогает в программировании. Если во втором способе нет MVC, то это уже повод задуматься над его полезностью.


(27)
решение основанное на декларативном описании модели объекта и формы.

Да, это то самое как раз, где ничего не понятно, но очень интересно) Как-нибудь ещё попробую пройтись по этой лабораторной, может, если совсем медленно читать...
23. for_sale 971 29.03.20 07:24 Сейчас в теме
В общем, ничего не понял, но очень интересно) Интригующая суть похоронена под казённо-формалистическим языком, как будто автор писал не для аудитории, а для лабораторной работы, чтобы сдать и забыть.
25. kalyaka 1053 29.03.20 14:32 Сейчас в теме
(23) Спасибо за Ваш интерес!
Интригующая суть похоронена под казённо-формалистическим языком
А вот в другом комментарии (4) был такой отзыв:
Стиль изложения больше литературный
- это, я так понял, в первой части изложения.

В общем я осознаю, что тема интересная, а решение не достаточно раскрыто. В ближайшее время я готовлю к публикации продолжение: в нем я рассмотрю на простом примере пошаговую инструкцию (4)
Что-то типа "делай раз - делай два - делай три - вот результат"
на примере создания интерактивной формы.

Так что следите за публикациями. Я планирую продолжить раскрывать "секреты" использования подсистемы и дальше. У меня есть много кейсов, которые смогут раскрыть разные возможности подсистемы и Ваши комментарии будут служить мне ориентиром в приоритетах их рассмотрения.
29. for_sale 971 30.03.20 06:52 Сейчас в теме
(25)
А вот в другом комментарии (4) был такой отзыв:
Стиль изложения больше литературный

Боюсь даже представить, на какой литературе рос автор комментария)) Если бы литература писалась таким языком, то я бы тогда лучше посвятил детство и юность гоп-стопам и наркотикам))
30. dijee 17 30.03.20 11:28 Сейчас в теме
(29) Видимо у вас действительно так плохо с продажами =) Всем прилетает "чёпик".
31. for_sale 971 30.03.20 11:42 Сейчас в теме
(30) Ой, а ты так разобиделся, что пошёл изучать мои комментарии? Бедненький))
34. TimurD 6 05.04.21 14:23 Сейчас в теме
В обработчике ПриИзменении Вы делаете проверку РассчитанныеРеквизиты[ИмяРеквизитаВалюты] = Истина, но в соответствии РассчитанныеРеквизиты в качестве значений Структура. Т.е. такое условие всегда будет ложным. Или самому нужно из другого обработчика ставить Истину?
35. kalyaka 1053 05.04.21 21:44 Сейчас в теме
(34)
РассчитанныеРеквизиты[ИмяРеквизитаВалюты]
Действительно, нужно проверять на Неопределено
НЕ РассчитанныеРеквизиты[ИмяРеквизитаВалюты] = Неопределено
Тут обыграна ситуация замкнутого графа зависимости. Если посмотреть в модуле заявки описание связей:
	//  Для внешней операции
	РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "СчетКонтрагента", "Контрагент", "Отбор.Владелец",, Новый Структура("Использование", "ЭтоВнешняяОперация"));
	РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "СчетКонтрагента", "ВалютаДокумента", "Отбор.Валюта",, Новый Структура("Использование", "ЭтоВнешняяОперация"), Истина);
	//  Для внутренней операции
	РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "СчетКонтрагента", "Организация", "Отбор.Владелец",, Новый Структура("Использование", "ЭтоВнутренняяОперация"));
	РаботаСМодельюКлиентСервер.Связь(Контекст, Модель, "СчетКонтрагента", "ВалютаВзаиморасчетов", "Отбор.Валюта",, Новый Структура("Использование", "ЭтоВнутренняяОперация"), Истина);
, то видно, что "Счет контрагента" находится в зависимости от валюты документа для внешней операции и валюты взаиморасчетов для внутренней. Однако зависимость эта слабая, что означает возможность выбрать счет без ограничения. Если же счет выбран, то нужно установить валюту из уже выбранного счета. Если же была выбрана валюта, то счет будет рассчитан автоматически согласно зависимости.
Оставьте свое сообщение