Меню

Расширения и модификации SAP. (BC425). Часть 2

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

Часть 1

Содержание

6. Классические BAdI

6.1. Классические BAdI.Расширения программ

6.2. Классические BAdI.Расширения меню

6.3. Классические BAdI.Расширения экранов

7. Enhancement Framework

8. Новые BAdI

9. Явные опции расширения

10. Неявные опции расширения

11. Модификация. User Exits. Ноты

6. Классические BAdI

Хотелось бы иметь вполне транзитивную технологию расширений, допускающую множественную имплементацию и позволяющую расширять программный код, меню и экраны. Тут сразу придется «обломать хотелки». Множественные имплементации на уровне программ это последовательное исполнение разных имплементаций одна за другой. А вот множественные имплементации на уровне представлений принципиально невозможны: ну не показывать же в одном и том же месте экрана разные подэкраны один за другим или в пункте меню то один текст, то другой!

С версии 4.6 появилась технология расширений BAdI (Business Add-In). BAdI допускает имплементацию, в том числе множественную, программных расширений и не множественную имплементацию расширений меню, а с 6-х версий еще и экранов. Эта технология вполне транзитивна по программным расширениям: можно делать свои имплементации программных расширений, создавая в них свои расширения программ, меню и экранов. Эта технология транзитивна потому, что BAdI идентифицируется именем. Повторяем первую мантру: нужно вести свои разработки в собственном диапазоне имен.

Для каждого BAdI можно создать произвольное количество имплементаций. В случае расширений меню и/или экранов создается BAdI, не допускающий множественного использования (multiple use), в случае только программного расширения обычно создается BAdI с возможностью множественно использования. Словосочетание «множественное использование» означает в данном случае, что можно одновременно активировать больше одной имплементации, в противном случае можно активировать не больше одной, хотя создать можно много имплементаций, просто остальные не будут активными.

Для классических BAdI поставщик может создать умалчиваемую имплементацию (она будет применяться при отсутствии имплементации пользователя) и шаблон имплементации (пользователь может не писать свою имплементацию «с нуля», а скопировать к себе шаблон и дальше редактировать уже готовую имплементацию)

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

6.1. Классические BAdI.Расширения программ

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

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

CALL METHOD CL_EXITHANDLER=>GET_INSTANCE

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

6.2. Классические BAdI.Расширения меню определяются разработчиком поставщика, содержат «+»-функциональный код и имя той программы, чей GUI-статус расширяется этим функциональным кодом. Один BAdI «не множественного использования» может содержать несколько функциональных кодов нескольких программ. Программы, содержащие такие расширения меню, содержат также программные расширения, позволяющие включить нужную обработку. Для диалоговых программ соответствующий вызов метода интерфейса BAdI осуществляется в одном из PAI-модулей экранной обработки, а для отчетов в блоке обработки события AT USER‑COMMAND .

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

6.3. Классические BAdI.Расширения экранов

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

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

Вот что делается при имплементации экранного расширения классического BAdI. Cоздается программа, в которой определяется имплементирующий подэкран. Технически такая программа может быть типа отчет, модульный пул или функциональная группа; на практике же используются именно функциональные группы. Такие функциональные группы могут вообще не содержать функциональных модулей. В имплементации экранного расширения указывается имя этой программы и номер подэкрана и создается имплементирующий класс. В имплементации аксессоров в сеттере устанавливаются значения инстанционных атрибутов, в геттере значения инстанционных атрибутов передается в выходные параметры. В TOP-инклюде имплементирующей программы определяются переменная типа ссылка на интерфейс, переменные для подэкрана и вычислений (если вычисления нужны), в PBO-модуле подэкрана сначала нужно получить ссылку на имплементирующий объект, это делается методом

CL_EXITHANDLER=>GET_INSTANCE_FOR_SUBSCREENS

после чего геттером получаем данные из имплементирующего объекта. Если нужно, делаем вычисления, поиски, заполняем переменные подэкрана. В PAI-модуле подэкрана

сеттером устанавливаем новые значения атрибутов имплементирующего объекта.

А теперь как это все работает.

В самом начале

(1) В расширяемой программе объявляется переменная типа ссылка на интерфейс BAdI.

До вызова PBO-логики имплементирующего подэкрана

(2) Методом CL_EXITHANDLER=>GET_INSTANCEсоздается имплементирующий объект ивозвращается ссылка на него.

(3) Сеттером устанавливаются атрибуты имплементирующего объекта.

(4) Методом CL_EXITHANDLER=>SET_INSTANCE_FOR_SUBSCREENS в класс CL_EXITHANDLER передается ссылка на имплементирующий объект.

(5) Методом CL_EXITHANDLER=>GET_PROG_AND_DYNP_FOR_SUBSCRиз описания активной имплементации выбираются имя имплементирующей программы и номер подэкрана.

(6) В логике обработке расширяемого экрана вызывается имплементирующий подэкран. После (5) уже известно, какой именно.

Исполняется имплементирующий подэкран.

(7) Исполняется PBO-логика имплементирующего подэкрана. В том числе и тот модуль, в котором геттер получает данные из имплементирующего объекта и передает их в переменные имплементирующего подэкрана.

(8) Исполняется PAI-логика имплементирующего подэкрана, а в ней тот модуль, в котором имплементирующий подэкран передает с помощью сеттера (быть может измененные) данные в имплементирующий объект. Понятно, что этот модуль должен быть последним в PAI-логика имплементирующего подэкрана.

В PAI-логике расширяемой программы после вызова PAI-логики подэкрана.

(9) Вызывается геттер, который возвращает в расширяемую программу данные с имплементирующего подэкрана.

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

7. Enhancement Framework

Все рассмотренные выше технологии и технология User Exits (о которой речь впереди) обладают недостатками. Новые технологии расширения и создавались для исправления недостатков более старых. А зачем же еще!

Технология User Exits позволяет расширять программы, но при этом нельзя воспользоваться одним User Exit одновременно для нескольких имплементаций. А ведь часто для решения какой-то одной задачи требуется воспользоваться сразу несколькими расширениями. Причем либо они все должны быть включены, либо все выключены. Технология User Exits не имеет «общего рубильника».

Технология Customer Exits имеет «общий рубильник» (транзакция CMOD), позволяет расширять программный код, экраны и меню, но эти расширения не могут иметь множественных имплементаций.

Технология Business Transaction Events имеет «общий рубильник» (транзакция FIBF), допускает множественные имплементации программных расширений, но не допускает расширений меню и экранов.

Технология Business Add-Ins имеет «общий рубильник» (транзакции SE19, SE18, SE80), допускает множественные имплементации программных расширений, допускает не множественные расширения меню и экранов.

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

Начиная с 7-й версии, появился новый набор возможностей расширения объединяемых в Enhancement Framework:

- новые BAdI (New BAdIs);

- явные точки расширения (Explicit Enhacement Points);

- секции расширения (Enhacement Sections);

- неявные возможности (Implicit Enhacement Points and Options).

Для удобства управления новые BAdI, явные точки расширения и секции расширения собираются в Enhacement Spots. Enhacement Spots могут объединяться в Composite Enhacement Spots. Соответственно и имплементации придется создавать для Enhacement Spot, а внутри уже имплементировать BAdI, явные точки расширений, секции расширений.

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

8. Новые BAdI

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

В отличие от классических BAdI, новые BAdI не являются отдельными объектами репозитария, а являются частями объектов репозитария типа Enhacement Spot. В расширяемой программе создается переменная типа ссылка на новые BAdI (а не на интерфейс BAdI, как для классических BAdI). Имплементирующий объект создается не вызовом статического метода, а командой языка ABAP: GET BADI <ссылка>. Методы программных расширений вызываются не командой CALL METHOD, а командой CALL BADI <ссылка> ‑<имя_метода> <параметры>.       
Для новых BAdI поставщик может создать не только умалчиваемую и шаблонную имплементации, но еще и предковую имплементацию, создавая свои имплементации пользователи могут наследовать предковую имплементацию, а могут копировать шаблонную.

Расширения программ и меню во многом подобны тому, как это делалось

Если хотите прочитать статью полностью и оставить свои комментарии присоединяйтесь к sapland

У вас уже есть учетная запись?

Войти

Обсуждения Количество комментариев1

Комментарий от  

Олег Точенюк

  |  08 июля 2020, 11:09

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