Практические рекомендации по поиску user-exit-ов (пользовательских расширений) в стандартном коде

Как показывает опыт внедрения и сопровождения систем SAP ERP, почти 30-50 % всех ABAP разработок составляют расширения стандартной функциональности при помощи пользовательских расширений (user-exit).

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

Итак, в рамках данной статьи рассматриваются приёмы поиска в исходном коде user-exit-ов, а именно: customer-exit и BAdi (BusinessAdd-Ins). Новомодные технологии, такие, как Enhancements Spots, рассматривать в данной статье не будем. Их я использую, как правило, в крайнем случае, т.к. не имея рамок, накладываемых интерфейсом во всех вышеупомянутых технологиях, Enhancements Spots провоцирует бесконтрольно вмешательство в логику обработки данных, что может привести к нарушению их целостности.

Применение данной методики является альтернативой применению различных программ, выдающих для заданной программы/транзакции список user-exit-ов. Применение таких программ имеет один существенный недостаток – не даются ответы на вопросы:

  1. Какие из перечисленных user-exit-ов вызываются, начиная с интересующего нас места в программе?
  2. В какой последовательности user-exit-ы вызываются?

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

Рассмотрим предлагаемую методику на примере решения задачи: при создании в системе кредитора исключить появление двойника.

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

Технически, для реализации решения этой задачи нам нужно будет взять из данных создаваемого кредитора (табл. LFA1) значение поля «РегНалогНомер-1» (STCD1), сделать запрос к таблице данных существующих дебиторов (KNA1), попытаться найти в ней запись со значением поля STCD1 равным нашему значению и, если поиск успешен, скопировать из найденной записи поле KNA1-KUNNR в поле LFA1-KUNNR.

Последовательность действий:

1) Запускаем транзакцию (в нашем случае XK01)

2) Выполняем все действия, которые совершают пользователи до «ключевого» действия (в нашем примере - это сохранение данных кредитора)

3) Непосредственно перед нажатием на кнопку «Сохранить», набираем в строке команд «/h» и нажимаем Enter. В строке состояния (внизу окна) должно появиться сообщение «Отладка включена»

4) Нажимаем «Сохранить» и попадаем в отладчик. (рис.1)

Рис. 1

5) В меню выбираем «Точки прерывания» -> «Создание точки прерывания» (или нажимаем F9). Откроется модальное окошко. (рис.2)

Рис. 2

6) На закладке «ABAP команда» вписываем «call customer-function» (рис.3)

Рис. 3

Справка: Вызов customer-exit осуществляется оператором CALL CUSTOMER-FUNCTION.

7) На закладке «Метод» заносим «CL_EXITHANDLER» и «GET_INSTANCE» соответственно в поля «Имя класса» и «Имя метода» и нажимаем «Дальше» (кнопка ). (рис.4)

Рис. 4

Справка: По технологии BAdi, перед вызовом какого-либо метода пользовательского расширения, всегда вызывается статический метод глобального класса CL_EXITHANDLER=>GET_INSTANCE. Этот метод возвращает приложению ссылку на инстанцию класса пользовательского расширения (если расширение реализовано). Этот метод, как правило, вызывается непосредственно перед вызовом методов BAdi.

8) В меню выбираем «Отладчик» -> «Дальше» (или нажимаем F8).

Теперь мы будем последовательно останавливаться отладчиком на всех вызовах customer-exit-ов и методов BAdi. Задача сводится к анализу этих вызовов и выборе наиболее подходящего для нашей задачи user-exit .

Первой остановкой будет, в нашем случае, следующая точка (рис.5):

Рис. 5

Это первый исполняемый оператор метода GET_INSTANCE

Примечание: При автоматизированном расставлении точек прерывания при вызове метода класса, равно как и для вызова функционального модуля, точка прерывания ставится на первом выполняемом операторе метода/функции.

Выбираем пункт меню «Отладчик» -> «Возврат» (или нажимаем F7) чтобы попасть на оператор, следующий непосредственно за вызовом метода CALL METHOD CL_EXITHANDLER=>GET_INSTANCE (рис.6)

Рис. 6

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

Проанализировав интерфейс метода, мы приходим к выводу, что это BAdi нам не подходит.

Кстати, в интерфейсе вызова CALL METHOD CL_EXITHANDLER=>GET_INSTANCE в формальном параметре exit_name передается имя BAdi. В данном случае это будет 'ADDRESS_CHECK'. Используя транзакцию SE18, можно подробно познакомиться с этим BAdi, посмотреть его методы, почитать документацию. И даже посмотреть примеры исходного кода методов (Внимание! Примеры есть не для всех BAdi).

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

Пропустив неподходящее нам BAdi 'ADDR_TXJCD_CHECK', мы остановимся на операторе вызова customer-exit: CALL CUSTOMER-FUNCTION '001' (рис.7)

Рис. 7

Справка: Имя функционального модуля (ФМ), реализующего данный customer-exit, можно узнать по следующему правилу: Имя ФМ = «EXIT_» + имя главной вызывающей программы + трехзначный номер в операторе CALL CUSTOMER-FUNCTION. В нашем случае имя программы будет ‘SAPMF02K’ (видно в отладчике в левом верхнем углу), а трехзначный номер – ‘001’. Значит, имя реализующего ФМ будет ‘EXIT_SAPMF02K_001’.

Для того чтобы найти имя расширения (для использования в проекте SAP-расширения) надо в транзакции SMOD вызвать список допустимых значений (F4) к полю «Расширение» и расширив список критериев выбора кнопкой ввести имя ФМ в поле «Имя компонента» (рис.8).

Рис. 8

Далее, остается только реализовать пользовательское расширение. Но реализация расширений выходит за рамки данной статьи.

Итак, наша цель достигнута – найден подходящий user-exit.

Возможно, что найденный user-exit после реализации не оправдает Ваших надежд и не позволит достичь намеченного результата. Тогда пробуйте перебирать user-exit-ы дальше. Как правило, подходящий user-exit находится. Если ничего подобрать не удалось (такое бывает, хотя и крайне редко), придется использовать альтернативные варианты: BTE, Enhancements Spots, Z-инклуды или, в самом крайнем случае, делать собственную разработку.

Источник:http://sapland.ru

Комментарии