22 August

Реализация MVVM в ABAP

ERP-systems
Sandbox
После окончания университета я несколько лет работал программистом C#. Я разрабатывал приложения на WPF с использованием шаблона проектирования MVVM. Затем перешел на ABAP. К большому удивлению обнаружил что ABAP является скорее процедурным языком чем объектно-ориентированным, хотя SAP прилагает большие усилия для продвижения ОО-парадигмы. Для разделения бизнес-логики от GUI как правило используют архитектурный шаблон MVC. Пытаясь реализовать MVC шаблон я каждый раз сталкивался с определенными сложностями, которые делают поддержку программы еще более сложной чем если бы она была написана на процедурах. Не смотря на то, что реализация MVC подробно и с примерами описана в книге Design Patterns in ABAP Objects и на специализированных ресурсах (sapland.ru, blogs.sap.com и др.), проблемы с разделением логики остаются. В реализации MVC на ABAP независимой частью остается Model, а View и Controller тесно связаны между собой. Сильное сопряжение между View и Controller затрудняет поддержку и масштабируемость. Ниже описано почему так происходит и что с этим делать.

Шаблоны MVC и MVVM


Подробно описывать принцип работы шаблонов MVC и MVVM в данной статье я не буду. Приведу лишь основные моменты, которые понадобятся нам в дальнейшем.

Основное отличие MVC от MVVM в том, что в первой Controller знает как View, так и Model, также допускается что View будет знать о Model.

image

В MVVM шаблоне связь между слоями более слабая. View знает только ViewModel, а ViewModel только Model. View получает данные от ViewModel через ссылку на DataContex.

image

Шаблон MVVM предназначен для разработки в WPF на языке C#. Но его идею можно применять и в ABAP.

Проблемы MVC в ABAP


При реализации MVC, как правило, классы Model выносят в глобальное определение, а классы View и Controller в локальное. Использование локальных классов обусловлено необходимостью взаимодействия с GUI элементами. Дело в том, что на ABAP-классах нельзя построить полноценный GUI. В классах View можно использовать функционал для формирования GUI (CL_SALV_TABLE, REUSE_ALV_GRID_DISPLAY и т.п.), но этого не достаточно. Создать GUI-статусы, заголовки, экраны, PBO, PAI в классе невозможно.

Локальные View и Controller, имеют ряд недостатков:

  1. View и Controller имеют доступ ко всем глобальным переменным и параметрам экрана выбора.
  2. Обработка PBO и PAI в Controller требует получения состояния View (например получение выделенных строк ALV) или обновление View (например обновление таблицы ALV). В качестве решения данной проблемы нередко можно увидеть публичные атрибуты View, на которые воздействует Controller, или когда View имеет ссылку на Controller. Оба решения плохие, т.к. в первом случае нарушается инкапсуляция, а во втором Low Coupling.

MVVM в ABAP или MVA


Желая использовать преимущества MVVM в ABAP и сделать слои более независимыми я определил для себя следующий шаблон разработки.

image

Так как в чистом виде MVVM реализовать на ABAP нельзя, то ViewModel использовать не совсем корректно. Поэтому вместо ViewModel и Controller я использую Application.

Принцип разделения логики аналогичен принципу MVVM. View передает команды пользователя в Application, а Application воздействует на модель. Обратная связь при этом отсутствует.
Особенностью ABAP приложений является то, то представление может обновиться только после действий пользователя. Даже если какой-нибудь асинхронный процесс поменяет модель, то инициировать обновление представление он не сможет. Данная особенность позволяет ослабить связь модель-представление и делегировать функцию обновления представления самому представлению. Иными словами, представление само должно решать, когда надо обновить себя, а когда нет.

Концепция MVA


Реализация MVA основана на объектно-ориентированном подходе, где на каждый слой архитектуры будет реализован один или несколько классов. Каждый из слоев обладает рядом свойств.

Представление (View и IView):

  • MVA работает с абстракцией представления IView. Все классы View должны содержать реализацию IView.
  • IView содержит события, которые требуют взаимодействия с моделью
  • IView содержит контекст — ссылка на данные модели, которые необходимо отобразить пользователю
  • View может содержать бизнес-логику, которая не требует взаимодействия с моделью. Например, если требуется реализовать из ALV проваливание в карточку контрагента, то данная логика будет относиться к представлению.
  • View содержит GUI элементы в группе функций, которая связана с классом View.

Приложение (Application):

  • Выполняет роль связки представления и модели и является точкой входа в приложение.
  • Имеет критерии запуска — набор параметров, которые определяют с какими параметрами необходимо запустить приложение. Обычно это параметры селекционного экрана.
  • Критерии приложения состоят из критериев модели и представления. Например, если на селекционном экране требуется ввести дату проводки и указать флаг вывода отчета PDF или ALV, то дата проводки будет относиться к критериям модели, а флаг PDF и ALV к критериям представления.
  • В конструктор приложения передаются критерии запуска. Приложение создает модель и представление, подписывается на события представления, связывает контекст представления с моделью.

Модель (Model):

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

Реализация MVA


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

Диаграмма классов будет выглядеть следующим образом.



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







IView. Интерфейс представления содержит методы установки контекста, отображения представления, события и определение типов контекста.







IView содержит в себе описание структуры контекста, причем поля структуры должны быть ссылочными



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

Реализация класса View в ALV представлении



В данной реализации нам необходимо определение GUI статуса, для этого создадим ФМ и свяжем его с экземпляром CL_SALV_TABLE



Важно что все UI события принимает View (в данном случае через ON_USER_COMMAND) и при необходимости View делает RAISE EVENT для Application. Этот подход делает View и Application более независимыми.

Application. Конструктор приложения принимает на вход критерии приложения (параметры экрана выбора) и создает экземпляры Model и View, подписывается на события View и связывает контекст View с Model. Конструктор — это единственное место где приложение знает о View. Application содержит метод RUN, который запускает программу. Запуск приложения можно сравнить с запуском транзакции с заранее определенными параметрами экрана. Это позволяет использовать ее из других программ без SUBMIT.



Запуск Application. Теперь делаем программу, которая будет запускать приложение.



Все, приложение готово. Можно смотреть результат.



Бизнес-логика на стороне View. Обработку событий, которые не требуют обращения к модели и контроллеру, можно делать в самой View.

Например, если требуется реализовать открытие MM03 при двойном клике на MATNR, то обработку данной логики можно сделать на стороне View.



На уровень View данная логика вынесена исходя из соображений: к модели не требуется обращаться за дополнительными данными; логика относится только к ALV, т.е. если бы была реализация View в виде Excel или PDF, то данное событие невозможно было бы обработать.

Литература

Design Patterns in ABAP Objects
Паттерны для новичков: MVC vs MVP vs MVVM
Архитектурные шаблоны в ABAP: MVC, MVP, MVVM, MVA
Tags:SAPABAPMVCMVVMMVA
Hubs: ERP-systems
+6
2.3k 17
Comments 19
Popular right now
Консультант SAP ABAP / Разработчик ABAP
from 200,000 ₽Алкогольная Сибирская группаRemote job
Консультант SAP
from 45,000 to 90,000 ₽Строительный ДворТюмень
Android Developer
to 200,000 ₽CrypteriumRemote job
Руководитель проектов 1С (ERP)
from 200,000 ₽HandysoftRemote job
Finance Senior/Principal Consultant JDEdwards E1
from 160,000 to 220,000 ₽Kertios ConsultingМоскваRemote job