Абстракция шаблона, программные слои
Виды зависимостей, слабые и сильные связи
Значение по связям, обработчик заполнения
Заполнение значения из обработчика ПриИзменении
Подсистема «Управление интерфейсом»
Понятие реквизита объекта и узла. Реквизиты ссылочного и простого типа
Изменение структуры Графа зависимостей
Определение номенклатуры по виду
Изменение подчинения договора на основного контрагента
Добавление зависимости вида номенклатуры от основного вида номенклатуры
Изменение договора (неявная слабая связь)
Изменение валюты (слабая связь)
Изменение контрагента программно
Изменение вида номенклатуры программно
Введение
Современный интерфейс пользователя предполагает событийную модель работы и множество состояний интерфейса. Невозможность задать строгую последовательность взаимодействия пользователя и интерфейса порождает множество сценариев работы программы, соблюсти выполнение которых становится тем сложнее, чем больше реквизитов в форме и запутаннее связи между ними. В общем случае даже связи могут меняться в зависимости от состояния интерфейса. Добавьте к этому еще и ограничения клиент-серверного взаимодействия, и дублирование кода для обхода этих ограничений при необходимости переиспользования объекта интерфейса из других форм или при программном взаимодействии с объектом, минуя интерфейс пользователя.
Программирование интерфейса пользователя - одна из самых сложных алгоритмических задач. История борьбы со сложностью в реализации пользовательского интерфейса уже достаточно продолжительная и придумано не мало решений для её обуздания. Найденные решения описаны в шаблонах проектирования. Остается взять «правильный» шаблон, проверить условия его применимости и найти его реализацию в 1С.
Базовым шаблоном в проектировании интерфейсов является шаблон MVC. В силу особенностей языка 1С найти реализацию этого шаблона было не просто, т.к. все эти шаблоны пришли из мира ООП, а 1С все-таки не поддерживает такую парадигму.
В представленном решении данной статьи описан вариант реализации MVC на 1С через декларативное описание зависимостей. Идея заключается в использовании графа зависимостей реквизитов, на основании которого подсистема сможет вызывать соответствующие обработчики. Сами обработчики можно расположить в общих модулях - это и будет средний слой между интерфейсом и моделью.
Рассмотрим реквизиты на форме. Некоторые из них имеют одну связь, а некоторые по несколько связей. Часть связей может зависеть от некоторого состояния объекта интерфейса и меняться: одни могут добавиться, другие удалиться. К примеру, выбор договора может быть привязан к контрагенту, а в случае, когда расчеты не прямые - к основному контрагенту.
При изменении реквизита может вызываться его обработчик, далее по связям нужно определить зависимые реквизиты и проверить их значение на соответствие условиям их связей. При изменении зависимого реквизита может вызываться его обработчик и уже для этого реквизита нужно будет определить зависимые реквизиты и т.д. Алгоритм расчета зависимых реквизитов завершается после прохождения всех путей по связям зависимостей реквизитов. Если по выбранному пути зависимый реквизит не изменил своего значения, либо остался незаполненным, то дальнейший расчет от этого реквизита прекращается.
Основные требования к решению:
- Алгоритмы обработки изменения реквизитов должны располагаться так, чтобы для интерфейсного и неинтерфейсного вызова использовался бы один и тот же код
- При изменении структуры зависимостей система должна рассчитать значения реквизитов, зависимости которых были изменены
- Перед выбором значения реквизита система должна проверить полноту связей и выдать сообщение для незаполненных значений реквизитов параметров связей
- Для пустого значения реквизита, заполняемого по умолчанию, система должна определить значение одним из способов:
- заданным значением
- значением, которое получается в результате вызова обработчика значения по умолчанию
- по условиям параметров связей в случае найденного однозначного значения
- Система должна проверять каждый зависимый реквизит на соответствие условиям параметров связей и в случае несоответствия сбрасывать значение в незаполненное состояние
- Система должна вести трассировку путей расчета зависимостей. Система должна гарантировать прохождение уникальных путей.
Реализация взаимодействия формы и объекта модели хорошо описывается шаблоном MVC. Под MVC я имею в виду разделение реализации взаимодействия интерфейса и бизнес-логики на три составляющих: слой бизнес логики, слой посредника между интерфейсной частью и бизнес-логикой, слой интерфейса.
Такое разделение реализации позволяет переиспользовать отдельные части шаблона в различных комбинациях. Так с бизнес-логикой может взаимодействовать как форма пользовательского интерфейса, так и другая бизнес-логика. На практике это означает, что можно изменить реквизит объекта как в форме, так и программно, когда используется объект бизнес-логики без пользовательского интерфейса. В обоих случаях изменение реквизита должно быть обработано в одном месте - в слое посредника, и это изменение должно отразиться вначале в объекте, а потом и в пользовательском интерфейсе (если взаимодействие идет через форму).
Таким образом, ключевая идея такой реализации: необходимо выделить слой посредника, который можно было бы использовать для взаимодействия с объектом как через форму, так и программно.
Расшифровка MVC в терминологии 1С у меня получилась следующей: M - Model - Объект, V - View - Форма, C - Controller - Менеджер. Получаем MVC = ОФМ (Объект, Форма, Менеджер).
Рисунок 1. Модель шаблона MVC
В объекте содержится вся функциональность, которая не связана с работой пользовательского интерфейса. В функциональность объекта входят: сохранение/восстановление, обработка данных, взаимодействие с БД, взаимодействие с другими объектами и внешними системами.
В случае 1С объект - это еще и экземпляр сущности со своим состоянием, соответствующий объекту метаданных 1С. Понимать это важно, так как способность сохранять свое состояние нам пригодится для реализации Менеджера.
Форма - это тоже объект, реализующий логику работы интерфейсных элементов. В нашей парадигме MVC объект-форма не должен реализовывать логику работы объекта модели. Его задача отслеживать изменения в объекте модели и отображать их конечный результат в интерфейсных элементах. Также в его задачу входит передавать изменения значений из интерфейсных элементов в значения реквизитов объекта модели.
Менеджер содержит код, который передает изменения из интерфейса в значения реквизитов объекта. Он также отвечает за логику связанных изменений в состоянии объекта. Это означает, что Менеджер поддерживает транзакционность изменений в состоянии объекта модели, инициируемых интерфейсом пользователя.
В роли Менеджера можно выбрать одноименный объект метаданных 1С - менеджер объекта или даже модуль самого объекта. В этом случае нарушается принцип независимости реализации Менеджера от Объекта и это ограничивает потенциальные возможности использования шаблона MVC. Лучшим вариантом будет реализация Менеджера в Общем модуле.
В конечном счете, я остановился на следующей реализации менеджера, весьма абстрактной. В качестве объекта менеджера в соответствии с парадигмой ООП у меня выступают данные и методы. Данные сохраняются либо в реквизите формы, либо в экспортной переменной объекта модели. В обоих случаях все состояние Менеджера содержится в одной структуре данных.
На момент выхода статьи вызов подсистемы для расчета зависимостей в контексте клиента не поддерживается. Поддержка режима клиента имеет ограничения: нельзя использовать метод Выполнить на клиенте в веб-браузере и на iOS - а этот метод используется для выполнения декларативно заданных обработчиков событий при изменении и заполнения. Кроме того, расчет зависимостей для реквизитов ссылочного типа требует серверного контекста выполнения, а значит поддержка этого режима будет иметь смысл только для реквизитов с простыми типами.
Для взаимодействия Формы с Менеджером необходимо в обработчиках событий реквизитов формы НачалоВыбора, ПриИзменении вставить вызовы методов Менеджера. Для первого обработчика Менеджер осуществляет проверку полноты связей, а для второго - выполняет обработчик ПриИзменении реквизита объекта, а также рассчитывает зависимости для выполнения цепочки обработчиков зависимых реквизитов.
Итак, обозначим круг задач, которые может решать Менеджер:
- Накладывать ограничения на выбор реквизита
- Определять значения по умолчанию
- Определять полноту данных параметров связей реквизита
- Выполнять обработку изменения реквизитов
- Отслеживать зависимости реквизитов для реализации цепочек изменений зависимых реквизитов
- Перестраивать зависимости и находить дельту для расчета реквизитов, по которым изменились зависимости
- Взаимодействие Менеджера с Формой осуществляется по событиям формы:
- НачалоВыбора
- ПриИзменении
Ключевая концепция реализации шаблона MVC, предлагаемая мной, основана на описании зависимостей реквизитов объекта модели. При построении модели реализации шаблона я исходил из того, что каждый реквизит объекта модели может иметь свой обработчик ПриИзменении, а также может иметь зависимости от других реквизитов или параметров (аналогично как в метаданных можно описать СвязиПараметровВыбора и ПараметрыВыбора).
Зависимости я представил в виде графа. Полученный граф зависимостей содержит узлы и связи между ними. Каждый узел соответствует реквизиту объекта модели. Если реквизит принадлежит коллекции, то узел соответствует множеству реквизитов в соответствии с количеством строк коллекции.
Рисунок 2. Зависимости реквизитов формы, представленные в виде графа
Связи между узлами описывают зависимости. Связь хранит источник зависимости и параметр, аналогично как это делается через использование свойства реквизита формы СвязиПараметровВыбора. Если узел соответствует реквизиту коллекции, то связь между реквизитами одной коллекции распространяется в пределах одной строки коллекции.
Настройка системы MVC производится путем описания графа зависимостей реквизитов. В предыдущей статье я уже описывал, как можно представить зависимость реквизитов в виде графа. В отличие от варианта, предложенного ранее, в этом решении граф зависимости нужно описать в системе явно.
Явное описание графа зависимостей позволяет Менеджеру как вычислять значения в узловых реквизитах, так и рассчитывать последовательности изменений. Таким образом, мы можем управлять последовательностями изменений декларативно, описывая зависимости в виде графа. Такой подход имеет следующие преимущества: конфигурацию зависимостей можно менять без изменения кода обработчиков, настройка зависимостей изначально имеет однозначное графическое представление и дает возможность визуального подтверждения требований у заказчика. К тому же использование графа позволяет задействовать законы из теории графов: контролировать возникновение циклов, оптимизировать расчет зависимостей для случаев, когда распространение изменений проходит через узловые реквизиты более одного раза.
Выбор реквизита ограничивается значениями параметров его связей. Однако не все так однозначно. В классическом случае взаимозависимости рассмотрим пример: договор контрагента зависит от выбранной валюты и валюта определяется по выбранному договору. В рассмотренном примере неправильно ограничивать выбор договора установленным значением валюты или не давать перевыбрать валюту при выбранном договоре. Для такого случая используется понятие слабой связи - такая связь используется для расчета зависимостей и значений, однако не используется в качестве ограничивающей при выборе значения.
Наличие таких связей, которые не должны ограничивать выбор, но определяют значение, приводит к необходимости их как-то отличать. В предложенном варианте такие связи называются «слабыми» в отличии от связей «сильных». Первые определяют значение реквизита, но не ограничивают его выбор, тогда, как вторые не дают возможности выбрать значение, которое не удовлетворяет условиям связей.
Слабая связь также не может быть однонаправленной, иначе это может привести к нарушению условий зависимостей. Так, если связь не двухсторонняя, то возможен вариант, когда будет выбран договор, не соответствующий валюте, либо валюта, не соответствующая валюте договора.
Граф зависимостей может иметь циклы. Наличие циклов не всегда является ошибкой, однако без учета такой возможности программа «впадет» в бесконечный цикл.
Циклы могут порождаться как следствие сложной системы связей, так и наличием слабых связей.
Слабые связи двунаправленные и потому расчет зависимости в одну сторону порождает и обратный расчет.
Сложный граф зависимостей может приводить к появлению разных путей зависимостей от одного реквизита к другому. И это неотъемлемое свойство графа. Это обстоятельство приводит к появлению циклов и к повторению расчетов в узлах.
Решение - в отслеживании пройденных путей (связей реквизитов), а также бережный расчет зависимостей. В первом случае нужно не допускать повторения путей, во втором - проверять перед расчетом значения параметров связей на неизменность.
Не всегда получается выразить зависимость декларативным образом или это выражение очень сложно в реализации. Например, в рассмотренном ранее примере зависимости договора и валюты. Зависимость валюты от договора декларативно описывается как Отбор.Ссылка = ДоговорКонтрагента.ВалютаРасчетов, однако, на практике такую связь в параметрах связи указать нельзя, так как такая связь не поддерживается текущей платформой 1С.
Решений тут может быть несколько. Вот два из них:
- Можно описать зависимость как Отбор.Договор = ДоговорКонтрагента и программно обработать параметр Договор для несуществующего поля справочника Валюты.
- Реализовать определение значения валюты в обработчике при изменении реквизита ДоговорКонтрагента.
Первый вариант реализации я планирую подробно рассмотреть в отдельной статье.
Во втором случае подсистеме расчета зависимостей необходимо сообщить об изменении реквизита ДоговорКонтрагента. Таким образом, подсистема будет оповещена об изменении и вызовет обработчик ПриИзменении, где будет установлено значение для реквизита Валюта, а также указан измененный реквизит для подсистемы, чтобы она могла продолжить расчет зависимостей.
Для заполнения значения реквизита можно определить обработчик.
Заполнить значение можно и по связям. Если значение определяется однозначно, оно может быть заполнено.
Для реквизитов, которые не требуют обязательного заполнения, система не должна определять значение по умолчанию.
Значение может заполняться из обработчика ПриИзменении. Если в обработчике происходит заполнение значения зависимых реквизитов, то подсистеме необходимо сообщить об этом - так система сможет учесть изменения реквизитов для расчета зависимостей. Именно такой способ был предложен в качестве 2-го варианта для реализации связи ДоговорКонтрагента-Валюта.
Подсистема «Управление интерфейсом»
Общее описание
Рисунок 3. Диаграмма взаимодействия формы с подсистемой и менеджером
Перед началом работы подсистему нужно проинициализировать. В результате инициализации получается структура "Граф зависимостей". Эта структура хранится в реквизите формы или в экспортной переменной объекта.
Подсистема взаимодействует с объектом через его данные или вызовы обработчиков. Объект определяется из переданного в подсистему контекста. Если контекстом выступает форма, то объект доступен из основного реквизита формы. В случае когда взаимодействие с объектом осуществляется без формы, в качестве контекста используется сам объект (см. пример обработки Стенд с вызовом команд).
Точки вызова подсистемы определены для событий "Начало выбора" и "При изменении".
Инициализация
Инициализация подсистемы заключается в создании, заполнении и сохранении структуры "Граф зависимостей". Следующие функции используются для построения и сохранения структуры:
- ПолучитьСтруктуруГрафаЗависимостей
- ДобавитьУзел
- ДобавитьСвязь
- ДобавитьРеквизитФормыГрафЗависимостей
- ЗаполнитьПараметрыВыбора
Листинг 1. Инициализация
// Создание структуры
ГрафЗависимостей = РаботаСГрафомЗависимостейКлиентСервер.ПолучитьСтруктуруГрафаЗависимостей();
…
// Добавление узлов
РаботаСГрафомЗависимостейКлиентСервер.ДобавитьУзел(ГрафЗависимостей, Префикс, "Контрагент", "Контрагент", , "Стенд.ПриИзмененииКонтрагента(Контекст)");
…
// Добавление зависимостей
РаботаСГрафомЗависимостейКлиентСервер.ДобавитьСвязь(ГрафЗависимостей, Префикс, "Контрагент", "ДоговорКонтрагента" , "Отбор.Владелец");
…
// Сохранение состояния графа зависимостей
РаботаСФормой.ДобавитьРеквизитФормыГрафЗависимостей(Контекст, ГрафЗависимостей);
РаботаСФормой.ЗаполнитьПараметрыВыбора(Контекст);
Структура «ГрафЗависимостей»
Листинг 2. Сохранение состояния
// Сохранение состояния графа зависимостей
Если ТипЗнч(Контекст) = Тип("УправляемаяФорма") Тогда
РаботаСФормой.ДобавитьРеквизитФормыГрафЗависимостей(Контекст, ГрафЗависимостей);
РаботаСФормой.ЗаполнитьПараметрыВыбора(Контекст);
Иначе
Контекст.ГрафЗависимостей = ГрафЗависимостей;
КонецЕсли;
Понятие реквизита объекта и узла. Реквизиты ссылочного типа или простого
Подсистема в процессе расчета зависимостей оперирует узлами и связями. В результате расчета зависимостей получаются реквизиты. Реквизиты могут быть ссылочного типа или простого. Для второго случая для расчета значения реквизита связи не используются.
Узел указывает на реквизит в метаданных. Для реквизитов коллекции используется описание узла без указания на конкретную строку. Под реквизитом понимается путь до данных объекта. Если реквизит является частью коллекции, то к описанию пути к данным добавляется указание идентификатора строки. В последнем случае идентификатором строки могут быть как идентификатор строки на форме, так и номер строки, если в качестве контекста выступает сам объект.
Реквизит может быть ссылочного типа или простого. Параметры связей используются для ограничения выбора значения реквизитов ссылочного типа. Для реквизитов простого типа вычисление значения реквизита по связям не используется.
Узлы используются для описания графа зависимостей, а реквизиты - для расчета зависимостей.
События формы
Точками взаимодействия формы с подсистемой являются обработчики событий НачалоВыбора и ПриИзменении.
НачалоВыбора
В этом событии производится проверка полноты значений параметров связей. В случае обнаружения незаполненных значений выдается сообщение о необходимости заполнить реквизиты, а выбор не осуществляется.
Рисунок 4. Результат проверки полноты значений параметров связей для реквизита Договор контрагента.
ПриИзменении
После изменения значения реквизита производится вызов подсистемы для вызова обработчиков измененных и расчета зависимых реквизитов.
Рисунок 5.Изменённый граф зависимостей по отношению к Рисунку 2.
Рисунок 6. Переход в новое состояние графа зависимостей
При модификации графа зависимостей подсистема может рассчитать разницу и выполнить расчет только по реквизитам, у которых изменились связи.
Листинг 3. Изменение структуры зависимостей
Перем ГрафЗависимостей;// Объявление в локальной переменной целевой структуры
// Копирование в целевую структуру текущей структуры графа зависимостей для последующей модификации путем удаления/добавления связей
ГрафЗависимостей = ОбщегоНазначенияКлиентСервер.СкопироватьСтруктуру(ЭтаФорма.ГрафЗависимостей);
// Удаление связи
РаботаСГрафомЗависимостейКлиентСервер.УдалитьСвязь(ГрафЗависимостей, Префикс, "ОсновнойКонтрагент", "ДоговорКонтрагента");
// Добавление связи
РаботаСГрафомЗависимостейКлиентСервер.ДобавитьСвязь(ГрафЗависимостей, Префикс, "Контрагент", "ДоговорКонтрагента", "Отбор.Владелец");
// Заполнение параметров связи формы и расчёт зависимых реквизитов
РаботаСФормой.ЗаполнитьПараметрыВыбора(ЭтаФорма, РаботаСГрафомЗависимостей.ПрименитьГрафЗависимостей(ЭтаФорма, ГрафЗависимостей));
Сценарии работы
Определение договора
Состояние: поле договор контрагента не заполнено, валюта заполнено Рубли.
- Пользователь: вызывает команду выбора контрагента из справочника, производит выбор
- Система: Вызывает обработчик Менеджера ПриИзменении для реквизита Контрагент
- Система: Определяет зависимые реквизиты: ДоговорКонтрагента
- Система: Производит поиск однозначного значения Договора контрагента по условиям связи
- Система: Заполняет значение договора найденным однозначным значением
- Пользователь: Вызывает команду Добавить строку ТЧ
- Пользователь: Заполняет значение Вида номенклатуры
- Система: Вызывает обработчик ПриИзменении реквизита ТЧ ВидНоменклатуры
- Система: Определяет зависимые реквизиты: Номенклатура
- Система: Производит поиск однозначного значения номенклатуры по условиям
- Система: Однозначное значение не найдено, значение реквизита Номенклатура остается прежним
Состояние: значения реквизитов «Контрагент», «Основной контрагент», «Договор контрагента», «Валюта» - заполнены, признак «Расчеты с основным контрагентом» сброшен.
- Пользователь: Устанавливает признак «Расчеты с основным контрагентом»
- Система: Изменяет условия параметров связей формы
- Система: Определяет измененные реквизиты: Основной контрагент (в реальности значение не изменено, но от него система начинает расчет, т.к. в структуре зависимостей появилась новая связь с этим реквизитом)
- Система: Определяет зависимые реквизиты: ДоговорКонтрагента
- Система: Производит поиск однозначного значения Договора основного контрагента по условиям связи
- Система: Заполняет значение договора найденным однозначным значением
Состояние: табличная часть заполнена различными значениями полей Вид номенклатуры, Номенклатура, признак «Общий вид номенклатуры» сброшен.
- Пользователь: Устанавливает признак «Общий вид номенклатуры»
- Система: Изменяет условия параметров связей формы
- Система: Определяет зависимые реквизиты: Вид номенклатуры [Номер строки], где Номер строки = 1..Кол-во строк
- Система: Выбирает 1-ую строку табличной части
- Система: Заполняет значение поля Вид номенклатуры значением реквизита шапки «Вид номенклатуры» (связь по значению ссылки)
- Система: Определяет зависимые реквизиты в 1-ой строке: Номенклатура[1]
- Система: Проверяет соответствие значения поля Номенклатура условиям связей
- Система: Значение поля не соответствует условиям связи – значение приводится к пустому
- Система: Производит поиск однозначного значения
- Система: Однозначное значение не найдено, значение остается незаполненным
- Переход к шагу 4 для расчета реквизита Вид номенклатуры в следующей строке табличной части
Состояние: заполнены значения реквизитов Контрагент, Валюта
- Пользователь: Выбирает договор в валюте, отличной от заполненного значения на форме
- Система: Выполняет обработчик ПриИзменении для реквизита Договор контрагента
- Система: В обработчике значение реквизита Валюта заполняется значением из договора, в переданную в обработчик структуру ИзмененныеРеквизиты добавляется реквизит «Валюта»
- Система: Фиксирует неявно пройденный путь Договор контрагента <-> Валюта
- Система: Определяет зависимые реквизиты от измененных реквизитов «Договор контрагента», «Валюта»: «Договор контрагента», «Банковский счет». Реквизит «Договор контрагента» будет пропущен, т.к. путь Валюта –> Договор контрагента считается пройденным (неявно). При этом дважды измененный реквизит системой рассчитывается - на основании того, что через него может быть несколько путей графа зависимостей.
- Система: Проверяет соответствие значения Банковский счет условиями связей
- Система: Очищает значение реквизита Банковский счет
- Система: Производит поиск однозначного значения
- Система: Заполняет значения реквизита Банковский счет найденным однозначным значением
Состояние: заполнены договор, валюта.
- Пользователь: Выбирает валюту, отличную от значения валюты договора
- Система: Определяет зависимые реквизиты: Договор контрагента, Банковский счет
- Система: Проверяет соответствие связям значений зависимых реквизитов
- Система: Очищает значения
- Система: Производит поиск однозначных значений
- Система: Заполняет значения по умолчанию
Состояние: заполнен реквизит «Валюта». Валюта нам нужна для поиска договора по умолчанию.
- Пользователь: Вызывает команду «При изменении контрагента»
- Система: Создает Объект модели
- Система: Инициирует подсистему «Расчет зависимостей реквизитов» через вызов процедуры Менеджера
- Система: Вызывает обработку события «При изменении реквизита» Контрагент
- Система: Вызывает обработчик реквизита Объекта «Контрагент»
- Система: Определяет зависимые реквизиты: Договор контрагента
- Система: Заполняет значение договора контрагента по умолчанию
- Система: Вызывает обработчик ПриИзменении для реквизита Договор контрагента
- Система: В обработчике значение реквизита Валюта заполняется значением из договора, в переданную в обработчик структуру ИзмененныеРеквизиты добавляется реквизит «Валюта»
- Система: Фиксирует неявно пройденный путь Договор контрагента <-> Валюта
- Система: Определяет зависимые реквизиты от измененных реквизитов «Договор контрагента», «Валюта»: «Договор контрагента», «Банковский счет». Реквизит «Договор контрагента» будет пропущен, т.к. путь Валюта –> Договор контрагента считается пройденным (неявно). При этом дважды измененный реквизит системой рассчитывается - на основании того, что через него может быть несколько путей графа зависимостей.
- Система: Проверяет соответствие значения Банковский счет условиями связей
- Система: Очищает значение реквизита Банковский счет
- Система: Производит поиск однозначного значения
- Система: Заполняет значения реквизита Банковский счет найденным однозначным значением
Листинг 4. Команда «При изменении контрагента»
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Стенд.ИнициализацияГрафаЗависимостей(ОбработкаОбъект);
РаботаСГрафомЗависимостей.ПриИзмененииЗначенияРеквизита(ОбработкаОбъект, "Контрагент");
ЗначениеВРеквизитФормы(ОбработкаОбъект, "Объект");
Состояние: в табличной части заполнена 1-ая строка.
- Пользователь: Вызывает команду «При изменении вида номенклатуры»
- Система: Создает Объект модели
- Система: Инициирует подсистему «Расчет зависимостей реквизитов» через вызов процедуры Менеджера
- Система: Заполняет значение Вида номенклатуры «Мебель»
- Система: Вызывает обработку события при изменении реквизита Вид номенклатуры для 1-ой строки
- Система: Определяет зависимые реквизиты: Номенклатура[строка ведущего реквизита]. В данном случае ведущий и зависимые реквизиты принадлежат одной таблице, а, значит, зависимость распространяется по строке измененного реквизита
- Система: Проверяет значение поля Номенклатура условиям связей
- Система: Очищает значение поля Номенклатура
Исключения:
7.б. Значение поля Номенклатура удовлетворяет условиям связей (это возможно, если предыдущее значение вида номенклатура было таким же)
7.б.1. Система: Значение поля Номенклатура остается неизменным
Листинг 5. Команда «При изменении вида номенклатуры»
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Если ОбработкаОбъект.Товары.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Стенд.ИнициализацияГрафаЗависимостей(ОбработкаОбъект);
Мебель = Справочники._ДемоВидыНоменклатуры.НайтиПоНаименованию("Мебель", Истина);
ТекущаяСтрока = 0;
ОбработкаОбъект.Товары[ТекущаяСтрока].ВидНоменклатуры = Мебель;
РаботаСГрафомЗависимостей.ПриИзмененииЗначенияРеквизита(ОбработкаОбъект, "Товары.ВидНоменклатуры", ТекущаяСтрока);
ЗначениеВРеквизитФормы(ОбработкаОбъект, "Объект");
Представленная модель позволяет декларативным образом описать зависимости реквизитов объекта. Связи между реквизитами хранятся в отдельной структуре, что позволяет в большинстве случаев менять их без необходимости отражать эти изменения в алгоритмах обработчиков. Это также приводит к упрощению описания модели взаимодействия реквизитов, а также дает возможность графического представления зависимостей для верификации и согласования модели с заказчиком.
Следование шаблону MVC также позволяет переиспользовать алгоритмы обработчиков как в различных формах отображения объекта модели, так и при программном управлении объектом модели.
Более того, получившаяся модель позволяет выделять устойчивые связи реквизитов и переиспользовать их описания для различных объектов модели. Так, например, для разных видов документов можно выделить такие устойчивые связи: Контрагент-Договор-Валюта, Сумма документа-Валюта документа-Сумма расчетов-Валюта расчетов. Обработчики для таких связей можно сделать общими и это может значительно повысить качество системы: устранить дублирование кода для обслуживания однотипных зависимостей.
Решение поставляется в виде конфигурации с общим демо модулем Стенд и одноименной обработкой. Подсистема использует общие процедуры БСП.
Таблица 1 Состав поставки
Метаданные |
Наименование |
Назначение |
ОбщийМодуль |
ОбщийКлиентСервер |
Вспомогательные процедуры |
|
РаботаСГрафомЗависимостей |
Подсистема расчета зависимостей реквизитов |
|
РаботаСГрафомЗависимостейКлиентСервер |
Подсистема расчета зависимостей реквизитов |
|
РаботаСоСхемойЗапроса |
Вспомогательные процедуры |
|
РаботаСФормой |
Подсистема расчета зависимостей реквизитов формы |
|
РаботаСФормойКлиентСервер |
Подсистема расчета зависимостей реквизитов формы |
|
Стенд |
Менеджер в общем модуле |
Обработка |
Стенд |
Обработка для тестов |
- Установить Демо конфигурацию БСП (проверялось на 2.4)
- Объединить с конфигурацией поставки УправляемыйИнтерфейсДемо.cf: добавить общие модули подсистемы и модуль Стенд для демо-теста (не затрите модуль приложения и настройки основной конфигурации!).
- Установить расширение Стенд.cfe (требуется версия платформы 8.3.11)
Рабочая
- Объединить с конфигурацией поставки по подсистеме «УправлениеИнтерфейсом»
- Сандерс У., Кумаранатунг Ч. "ActionScript 3.0. Шаблоны проектирования". Глава 12. Шаблон Модель-Представление-Контроллер
- Фаулер, Мартин. Архитектура корпоративных программных приложений. Глава 14. Типовые решения, предназначенные для представления в Web
- Эрик Фримен, Элизабет Фримен, Кэтти Сьерра, Берт Бейтс — Паттерны проектирования. Глава 12. MVC как комбинация паттернов