Как варить компот

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

Вот для примера типичный код из события OpenFI BTE 1120 (замещения перед сохранением бухгалтерской проводки):
User-exit source sample
Вот такой компот, бывает что и на тысячи строк тянется эта простыня.

Почему так получается? Это скорее следствие скупости, лени, спешки плюс недостаток фантазии.

Работать – работает, больших проблем не доставляет. Открыл – всё видно. Можно даже копипастить подходы, использовать общие переменные.

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

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

Приступим к первой итерации.

Общий обёрточный класс

Чтобы сделать прототип и запрятать управление *SUBST*(особые танцы данного юзер-экзита) под капот, создадим общий обёрточный класс:

Метод RUN предназначен для вызова снаружи, выполняет обёрточные функции

Метод PROCESS следует переопределять в дочерних процессах.

Реализация дочерних классов

Класс номер один:

Класс номер два:

И осталось подёргать эти классы из общего метода:

Таким образом компот превращается просто в десяток-другой таких вызовов.

Что дальше?

Вот такая первая итерация. Первичная цель достигнута, но есть куда стремиться, есть над чем подумать.

Например:

  • Вынести проверку предпосылки в дочерний класс
  • Автоматический перебор дочерних классов / реализаций интерфейса
  • Кто сказал интерфейсы?

4 комментария

  1. Можно сделать Z-BAdi c фильтром

  2. Почему родительский класс не абстрактный? На лицо явный пример, где он должен использоваться
    Чем этот велосипед проще и понятнее BAdi?
    В любом случае все эти вызовы в одном инклюде нужно убирать, например, в конструкцию INCLUDE … IF FOUND

  3. Большое спасибо за фидбек.

    Конечно, базовый класс следует сделать абстрактным (upd), но для драфта/концепта это не существенно, так же как и оформление констант и кое-что ещё.

    Насчет INCLUDE у меня есть некотрые предубеждения. Например, у них были засады с проверками при компиляции. А сейчас такие веяния времени, что избавляться от предубеждений к INCLUDE уже поздновато, на мой субъективный взгляд. Юнит-тесты на них не напишешь и т.д.

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

  4. Простой пример разделения — с помощью ФМ с таким же интерфейсом.

Добавить комментарий

Ваш адрес email не будет опубликован.