0% encontró este documento útil (0 votos)
23 vistas

Tutorial ABAP-Estilo Programacion

Este documento trata sobre cómo escribir mejor código ABAP enfocándose en la legibilidad y mantenibilidad del código. Recomienda principios como usar nombres de variables autoexplicativas, mantener el código simple, dividir el código en módulos y evitar la duplicación de código. También recomienda comentar el código para explicar las decisiones tomadas y consultar a los usuarios durante el diseño.

Cargado por

SAP IT CSS
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
23 vistas

Tutorial ABAP-Estilo Programacion

Este documento trata sobre cómo escribir mejor código ABAP enfocándose en la legibilidad y mantenibilidad del código. Recomienda principios como usar nombres de variables autoexplicativas, mantener el código simple, dividir el código en módulos y evitar la duplicación de código. También recomienda comentar el código para explicar las decisiones tomadas y consultar a los usuarios durante el diseño.

Cargado por

SAP IT CSS
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 26

Tutorial ABAP (en español) – 

Estilo
Este documento intenta responder a ¿qué hago para escribir mejor código?

Y no, casi nunca tiene que ver con cuántas líneas eres capaz de escribir en
un día o si tus programas son un milisegundo más rápidos que los de otro
programador. El código en realidad no se escribe para que lo lean las
máquinas, sino los humanos.

1         LEGIBILIDAD DEL CÓDIGO


El mayor reto programando no es conseguir que algo funcione, sino que
siga funcionando 20 años después a pesar de que otras personas hayan
realizado modificaciones posteriores y se hayan añadido nuevos
requerimientos y funcionalidades.

1.1       MANIFIESTO
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!
 

1.2       PRINCIPIOS DE DISEÑO


1.2.1      VARIABLES AUTOEXPLICATIVAS
Los comentarios tienden a quedarse obsoletos al realizarse múltiples
modificaciones posteriores. Por eso es mejor, en la medida de lo posible,
que los nombres de las variables sean autoexplicativas, metiendo así los
comentarios dentro del propio código. El código nunca queda obsoleto o
desincronizado.

Extracto de “The Clean Code” de Robert C. Martin:


 

1.2.2      KISS
El principio KISS (del inglés Keep It Simple, Stupid!:1 «¡Hazlo sencillo,
tonto!») es un acrónimo usado como principio de diseño.
El principio KISS establece que la mayoría de sistemas funcionan mejor si
se mantienen simples que si se hacen complejos; por ello,
la simplicidad debe ser mantenida como un objetivo clave del diseño, y
cualquier complejidad innecesaria debe ser evitada.
Cuanto más complejo es un diseño, más propenso es a contener bugs y a
provocar fallos de los usuarios.

1.2.3      DIVIDE Y VENCERÁS


¡Trocea el código! Pocas cosas hay peores que encontrarse un tocho de
código de 3000 líneas seguidas sin modularizar. Un código así es
extremadamente difícil de mantener, ya sea por otras personas o por el
propio autor años después.
Es mucho más sencillo comprender el código y detectar errores si el código
está dividido en fragmentos. Como regla general, lo primero que debería
quedar visible es el primer nivel de abstracción, los grandes bloques que
componen el programa. Estos a su vez pueden dividirse en otros etc.
Idealmente el código de un programa estará compuesto únicamente por
llamadas a subrutinas/funciones/métodos de objetos y es allí donde estará la
mayor parte del código, troceado.

Como regla general, una subrutina no debería tener más de 120 líneas, y si
se emplea orientación a objetos, un método no debería tener más de 30.

Un buen truco suele ser sacar la lógica relacionado con ALVs a un include
y la definición de datos a un Top-Include si esta es muy extensa. Así nada
más entrar al programa se ven las secciones SELECTION-SCREEN y
START-OF-SELECTION que a su prácticamente solo deberían contener
llamadas a piezas de código.
También ayuda romper visualmente el código en bloques fácilmente
diferenciables empleando comentarios incluso dentro de una única
subrutina.

CITA CÉLEBRE
”Una función o subrutina debería hacer una cosa, sólo una cosa y
hacerla bien”
Curly’s law

La mejor forma de modularizar es si cada subbloque de código solo es


responsable de hacer una única tarea. La modularización se complica
cuando una función está intentando realizar muchas cosas a la vez. Además
de dificultar la comprensión en realidad hace que sea menos reutilizable (y
no más) ya que para usarla deben darse todas sus condiciones de
contorno/parámetros. En su lugar es mejor anidar funciones dentro de otras
funciones y llamar así solo el fragmento de código exacto que se necesita.

1.2.4      DRY/WET
El principio No te repitas (en inglés Don’t Repeat Yourself o DRY,
también conocido como Una vez y sólo una) es una filosofía de definición
de procesos que promueve la reducción de la duplicación especialmente
en computación. Según este principio toda “pieza de información” nunca
debería ser duplicada debido a que la duplicación incrementa la dificultad
en los cambios y evolución posterior, puede perjudicar la claridad y crear
un espacio para posibles inconsistencias. Los términos “pieza de
información” son usados en un sentido amplio, abarcando:
Datos almacenados en una base de datos;
Código fuente de un programa de software;
Información textual o documentación.
Cuando el principio DRY se aplica de forma eficiente los cambios en
cualquier parte del proceso requieren cambios en un único lugar. Por el
contrario, si algunas partes del proceso están repetidas por varios sitios, los
cambios pueden provocar fallos con mayor facilidad si todos los sitios en
los que aparece no se encuentran sincronizados.
 

En caso de existir un error en el código, resulta mucho más sencillo


corregirlo en un único lugar que en muchos ya que siempre te puedes
olvidar uno. Además mejora enormemente la legibilidad del código.

1.2.5      COMENTARIOS/DOCUMENTACIÓN
CITA CÉLEBRE
”3 Years ago, god and me knew what this code does. Now only god
knows”
Anónimo

La recomendación suele ser documentar y comentar el código como si la


persona que fuese a continuar tu trabajo fuese un psicópata homicida que
sabe dónde vives. Pero es aún peor, esa persona podrías ser tú dentro de 3
años.

Por lo general, cuanto más pegada esté la documentación al propio código,


mejor. La documentación tiende a quedarse obsoleta ya que al realizarse
modificaciones posteriores, rara vez se acuerda uno de modificar la
documentación también.

La recomendación es no escribir comentarios redundantes sobre cosas


obvias, pero en general se deben escribir comentarios siempre que el código
no sea obvio. Lo más importante no es explicar qué hace el código, sino por
qué lo hace. Las decisiones tomadas en el código son consecuencia a 
menudo de las decisiones tomadas en el diseño y estas de los
requerimientos. Esa es la clase de información que tiende a perderse con el
tiempo.

Los comentarios con (*) son adecuados para explicar bloques de código.
Para comentar casos dentro de IF’s es mejor con (“) ya que siguen la
indentación y así los asteriscos ayudan a trocear visualmente el código
como bloques ya que describen a todo un bloque.

1.2.6       CODE INSPECTOR – TRANSACCIÓN SLIN


SAP proporciona una transacción que facilita enormemente mejorar el
estilo del código y evitar algunos bugs. También se puede acceder desde la
SE80 en la barra de la izquierda haciendo click derecho en el nombre del
programa, seleccionando verificación y nos da 3 opciones:

 Verificación ATC
 Verificación ATC ampliada
 Code Inspector
 

La verificación ATC no debe contener errores (hay excepciones) ya que


este tipo de errores son graves y corporación no nos pasará a productivo los
transportes que no la pasen.

La verificación ATC ampliada  es similar pero muestra muchos más errores

El Code Inspector es la opción más completa y nos permite decidir que


chequeos queremos hacer sobre el código. Nos ayuda a detectar no solo
errores, sino incumplimientos de la normativa de nomenclatura, detectar
variables no utilizadas, subrutinas que nunca son llamadas etc.

1.2.7      CÓDIGO DESACTIVADO/COMENTADO


En ocasiones se comentan largas fracciones de código que ya no se usan en
lugar de borrarlas. Es preferible borrarlas ya que si fuese necesario
recuperarlas, el control de versiones integrado en la SE80 nos puede
permitir recuperar versiones anteriores del código. Se crea una nueva
versión del código con cada transporte.

Si mantenemos mucho código comentado se dificulta la lectura y además


tiende a acumularse porque el siguiente programador desconocerá por qué
un fragmento de código está comentado y si en algún momento necesitará
ser reactivado. Como tendrá miedo a borrarlo al no saber por qué está ahí,
se acumulará para siempre

Personalmente, soy contrario a dejar comentarios indicando los trozos de


código que se modifican junto con un número de ticket o a dejar el código
previo además del nuevo. Esto hay quien lo hace para en caso de que lo
nuevo dé problemas sea muy fácil de identificar y revertir al estado
anterior. No obstante, si no da problemas se acumula para siempre y no
aporta realmente nada.

1.2.8      USER-CENTRED DESIGN – PREGUNTANDO A LOS


USUARIOS
 

Lectura recomendada “User Centred Design” de David Travis:


https://www.userfocus.co.uk/pdf/fable.pdf
Se puede resumir en que involucrar a los futuros usuarios de la aplicación
en su diseño y test no solo es necesario, sino imprescindible.

CITA CÉLEBRE
”Si hubiera preguntado a mis clientes, me habrían pedido un caballo más
rápido”
Henry Ford

A pesar de lo expuesto anteriormente, los usuarios a menudo desconocen


las posibilidades que existen y por ello es mucho mejor no dejarles aportar
la solución al problema inicialmente, sino pedirles que definen el proceso o
problema a resolver al margen de la herramienta, entonces elaborar un
prototipo y entonces juntarse otra vez con ellos, mucho antes de acabar el
desarrollo.

Evitar booleanos como parámetros de entrada a funciones (DO ONLY 1


THING)

8. Mantener el mismo nivel de abstracción en cada bloque


 

10. Reutilizar el código interno, no las pantallas ni los parámetros de


selección. Emplear templating

1.2.9

1.2.10  COMPROMISOS Y EQUILIBRIOS


 
Flexibilidad ßàComplejidad
Existe siempre un compromiso entre flexibilidad y complejidad. Si tenemos
unos requerimientos muy concretos y llenos de certezas podremos diseñar
una aplicación muy simple de utilizar e intuitiva ya que conocemos de
antemano cómo se va a utilizar la herramienta.

Una queja habitual es que SAP no es nada intuitivo. Un ejemplo sería mirar
el maestro de materiales ¿cuántos campos hay ahí que nadie ha utilizado
nunca? El problema de SAP es que eligieron desarrollar un software
extremadamente flexible ya que debía poderlo utilizarlo cualquier empresa
del mundo. ¡A pesar de que cada empresa hace las cosas de un modo muy
diferente!

Esta necesidad de cubrir los requisitos de muchos procesos distintos a la


vez ha llevado a que SAP sea extremadamente complejo. No se debe a que
los programadores hicieran mal su trabajo, SAP es complejo porque fue
diseñado para serlo, fue diseñado para ser flexible.

CITA CÉLEBRE
”La optimización prematura es el origen de todos los males”
Donald Knuth, autor de “The Art of Computer Programming”

Evita la optimización prematura


 

¿Necesito preocuparme excesivamente por el rendimiento del código si es


una transacción sencilla que saca muy pocas líneas de información?

¿Necesito preocuparme por un posible caso futuro que no sé si llegará a


darse nunca?

¿Cómo de flexible necesito ser, realmente?


 

La flexibilidad se paga con complejidad y la complejidad afecta a la


sencillez de uso y a la mantenibilidad de las aplicaciones. Un rasgo habitual
entre los buenos programadores es que escriben menos líneas de código, ya
que al haber diseñado conceptualmente la aplicación bien, el resultado es
sencillo. No obstante, a veces no queda más remedio que ser flexible.

1.2.11  ¡SÁLTATE LAS NORMAS!


Debes poder sentirte libre se saltarte todas las normas de estilo si sientes
que al hacerlo el resultado va a ser más legible para el código concreto que
estás escribiendo. Todas las reglas no son más que recomendaciones que
funcionan bien en la mayoría de los casos y la mayoría de las veces. Tu
criterio manda.

1.2.12  EVITAR LA DEUDA TÉCNICA

El mal código funciona de forma similar a una hipoteca, puedes conseguir


un préstamo que te dará dinero ya, a cambio de tener que pagar intereses
adicionales durante mucho tiempo. A la larga habrás acabado pagando una
suma mucho mayor.

Con el código sucede algo muy parecido. Si se escribe mal código (poco
universal), con lógica duplicada, difícil de leer… aunque escribirlo haya
costado algo menos, mantener ese código a largo plazo será mucho más
costoso. ¡Ojo! A veces es necesario e incluso adecuado aceptar soluciones
subóptimas por necesidades del negocio, pero en general conviene mirar a
largo plazo.

 
 

1.3       EJEMPLOS DE MEJORAS EN CÓDIGO


1.3.1      NIVELES DE ANIDACIÓN
Un código con excesivos niveles de indentación resulta difícil de leer. ¿Qué
parte del código está dentro de qué bucle?

CITA CÉLEBRE
”Un código bien planteado nunca debería tener más de 3 niveles de
anidación”
(Linus Torvalds, creador de Linux).

Lo que no se debe hacer:


          ELSE.

            IF <lfs_lines>-mrp_element_ind <> 'LB
'.

              IF <lfs_lines>-mrp_element_ind <> '
FH'.

                IF <lfs_lines>-avail_date <= p_fe
cha.

                  lv_avail = <lfs_lines>-
avail_qty1.

                  IF <lfs_lines>-mrp_element_ind 
= 'BA' AND p_sol IS NOT INITIAL.
                    lv_sol = lv_sol + <lfs_lines>
-rec_reqd_qty.

                  ELSE.

                    IF <lfs_lines>-storage_loc = 
'0002'.

                      IF <lfs_lines>-plus_minus = 
'+'.

                        lv_sfab = lv_sfab - <lfs_
lines>-rec_reqd_qty.

                      ELSEIF <lfs_lines>-
plus_minus = '-'.

                        lv_sfab = lv_sfab + <lfs_
lines>-rec_reqd_qty.

                      ENDIF.

                    ENDIF.

                  ENDIF.

                ENDIF.

                lv_availtot = <lfs_lines>-
avail_qty1.
                IF <lfs_lines>-mrp_element_ind = 
'BA' AND p_sol IS NOT INITIAL.

                  lv_soltot = lv_soltot + <lfs_li
nes>-rec_reqd_qty.

                ELSE.

                  IF <lfs_lines>-storage_loc = '0
002'.

                    IF <lfs_lines>-plus_minus = '
+'.

                      lv_sfabtot = lv_sfabtot - <
lfs_lines>-rec_reqd_qty.

                    ELSEIF <lfs_lines>-plus_minus 
= '-'.

                      lv_sfabtot = lv_sfabtot + <
lfs_lines>-rec_reqd_qty.

                    ENDIF.

                  ENDIF.

                ENDIF.

              ENDIF.

            ENDIF.

          ENDIF.
        ENDLOOP.

Opciones para mejorarlo:


 

Estrategia 1: cuando la indentación se debe a que continuamente se


comprueba que no haya surgido un error se puede intentar dividir el código
en bloques y aplicar una condición de stop. De este modo se colapsan todos
los IF’s sucesivos en uno único en el nivel más exterior.
 

* --- CREAR VISTAS DE CENTRO/ORG.VENTAS ---

  IF v_stop IS INITIAL.

    CALL FUNCTION 'ZMM_CREAR_VISTAS'

      EXPORTING

        pi_matnr   = v_matnr

        pi_werks   = p_werks

        pi_vkorg   = p_vkorg

        pi_sernp   = c_sernp

        pi_fotov   = p_fotov

      CHANGING

        po_errores = i_error_messages.
    DELETE i_error_messages WHERE type <> 'E'.

    IF i_error_messages IS NOT INITIAL.

      w_log-icon = icon_red_light.

      w_log-matnr = v_matnr.

      WRITE text-014 TO v_texto.

      w_log-message = v_texto.

      APPEND w_log TO i_log.

      LOOP AT i_error_messages INTO w_error_messa
ges.

        w_log-icon = icon_yellow_light.

        w_log-message = w_error_messages-message.

        APPEND w_log TO i_log.

      ENDLOOP.

      v_stop = 'X'.

    ENDIF.
  ENDIF.

IF v_stop IS INITIAL

Estrategia 2: alternar IFs y CASE, empleando CASE…WHEN…


ENDCASE para las condiciones más generales (algo asimilable a distintos
“casos”, “escenarios” o “funciones”).
 

Estrategia 3: sustituir los SELECTS con FOR ALL ENTRIES por


SELECTS con rangos + Loop en la tabla resultante, ya que si la tabla queda
vacía el loop no entra y no hay problema.
 

Estrategia 4: meter condiciones en el loop cuando haya un IF exterior que


lo cubra todo y sin ELSE.
ANTES:
        LOOP AT li_stb ASSIGNING <lfs_stb>.

          IF <lfs_stb>-idnrk IS NOT INITIAL.


          ENDIF.

        ENDLOOP.

DESPUÉS:
        LOOP AT li_stb ASSIGNING <lfs_stb> where
idnrk IS NOT INITIAL.

        ENDLOOP.

1.3.2      Evitar duplicar SELECTS


 

Motivo: al evitar duplicar el select es mucho más fácil optimizar y corregir


errores ya que solo se debe hacer en un lugar y no en 2. El código además
es más fácil de leer.
 

Estrategia: precargar condicionalmente rangos con las restricciones


ANTES:
    IF p_subcon IS INITIAL.

      SELECT ms~werks ms~matnr ms~bukrs mk~mblnr 
mk~mjahr ms~zeile mk~budat
             mk~bldat ms~lgort ms~sobkz ms~shkzg 
ms~dmbtr ms~menge ms~salk3 ms~bwart ms~smbln ms~sm
blp

             INTO TABLE li_docmat

             FROM mkpf AS mk

             INNER JOIN mseg AS ms

             ON mk~mblnr = ms~mblnr AND

                mk~mjahr = ms~mjahr

             WHERE ms~bwart IN s_bwart AND

                   ms~matnr IN r_matnr AND

                   ms~werks IN s_werks AND

                   ms~lgort IN s_lgort AND

                   ms~sobkz <> 'O'     AND

                   ms~bukrs = p_bukrs  AND

                   mk~budat IN s_budat.

    ELSE.

      SELECT ms~werks ms~matnr ms~bukrs mk~mblnr 
mk~mjahr ms~zeile mk~budat
             mk~bldat ms~lgort ms~sobkz ms~shkzg 
ms~dmbtr ms~menge ms~salk3 ms~bwart ms~smbln ms~sm
blp

             INTO TABLE li_docmat

             FROM mkpf AS mk

             INNER JOIN mseg AS ms

             ON mk~mblnr = ms~mblnr AND

                mk~mjahr = ms~mjahr

             WHERE ms~bwart IN s_bwart AND

                   ms~matnr IN r_matnr AND

                   ms~werks IN s_werks AND

                   ms~bukrs = p_bukrs  AND

                   mk~budat IN s_budat.

    ENDIF.

DESPUÉS:
TYPES: ty_r_sobkz TYPE RANGE OF sobkz,

      ty_l_sobkz TYPE LINE OF ty_r_sobkz.
  DATA: lw_sobkz TYPE ty_l_sobkz,

       lr_sobkz TYPE ty_r_sobkz.

IF r_matnr IS NOT INITIAL.

    IF p_subcon IS INITIAL. 

"Si se marca stock de subcontratación, se añaden m
ás restricciones

      "Stock de subcontratación

      lw_sobkz-low = 'O'.

      lw_sobkz-option = 'EQ'.

      lw_sobkz-sign = 'E'.

      APPEND lw_sobkz TO lr_sobkz.

      "Almacenes

      lr_lgort = s_lgort[].

    ENDIF.
    SELECT
ms~werks ms~matnr ms~bukrs ms~mblnr ms~mjahr ms~ze
ile

           ms~lgort ms~sobkz ms~shkzg ms~dmbtr ms
~menge ms~salk3       ms~bwart ms~smbln ms~smblp

           INTO CORRESPONDING FIELDS OF TABLE li_
docmat

           FROM mseg AS ms

           WHERE ms~matnr IN r_matnr

             AND ms~werks IN s_werks

             AND ms~lgort IN lr_lgort

             AND ms~bwart IN s_bwart

             AND ms~sobkz IN lr_sobkz.

Cuando no hacerlo: cuando en función de los parámetros suministrados se


deba acceder por índices completamente diferentes y no hubiese forma de
garantizar que los parámetros imprescindibles serán suministrados. En
general indicaría que el código intenta hacer varias cosas diferentes a la vez
y el diseño no era adecuado en primer lugar.
 
1.3.3      DESIGN PATTERN: TABLA INTERNA POR ETAPAS
Los Design Patterns son ‘plantillas’ que solucionan un problema de diseño
y que son reutilizables en problemas similares. Expresado de otra forma, si
una determinada forma de estructurar un programa resultó efectiva para
resolver un problema, podrá emplearse para resolver problemas similares.

Estrategia: definir desde el principio la tabla final a mostrar en el ALV y


en cada operación rellenar incrementalmente más información. Resulta útil
para estructurar el código cuando deben cruzarse muchas tablas ya que de
un vistazo rápido se observan las dependencias y en qué momento se
obtiene qué información.
  PERFORM f_formatear_albaranes CHANGING i_r_alba
ran.

  PERFORM f_obtener_compras USING i_r_albaran

                                  i_r_bwart

                                  i_r_werks

                                  i_r_matnr

                                  i_r_budat

                                  i_r_bukrs

                         CHANGING i_alv.

  PERFORM f_obtener_ventas CHANGING i_alv.

  PERFORM f_obtener_entregas USING p_rb_te p_rb_m
ix CHANGING i_alv.
  PERFORM f_obtener_facturas CHANGING i_alv.
 
Para que sea especialmente efectivo, cada bloque debería hacer únicamente
lo que su nombre indique para desde fuera de los performs no se pierda
nunca la visión global de lo que hace el programa.

En general, lo ideal es no hacer subrutinas de más de 120 líneas y el


contenido de la subrutina debe hacer una cosa y solo una que además sea
obvia leyendo su nombre.

1.3.4      ENUNCIAR LAS CONDICIONES LÓGICAS EN POSITIVO.


¿De estas 2 sentencias cuál es más fácil de leer?

IF NOT v_stop IS INITIAL

IF v_stop IS NOT INITIAL

¿Y entre estos fragmentos?

IF sy-subrc <> 0.

ELSE

      PERFORM visualizar_alv USING i_alv.

ENDIF.
 

IF sy-subrc = 0.

      PERFORM visualizar_alv USING i_alv.

ENDIF.

Además, las clausulas WHERE de los SELECTS que incluyen condiciones


en negativa suelen ser bastante más lentas porque impiden emplear los
índices.

1.4       NOMENCLATURA
Para que sea más sencillo entender la base de código de la empresa, desde
corporación se han definido unas normas sobre cómo se deben llamar las
variables, programas, funciones, tablas etc. Esto permite que sea más fácil
entender código que no haya sido escrito por nosotros.

Existen 2 archivos que son de obligado cumplimiento:

NOMENCLATURA_ABAP

NOMENCLATURA_PROGRAMAS

Y que están disponibles para descargar en la intranet de corporación.

A grandes rasgos, las variables empiezan por v, las estructuras por w y las
tablas por i:
 v_ebeln –> Sé que es una variable sin mirar su tipo
 w_ebeln –> Estructura
 i_ebeln –> Tabla
 c_ebeln –> Constante
 ty_ebeln –> Tipo
 tyt_ebeln –> Tipo de tabla
 

Si son locales (dentro de una subrutina por ejemplo) llevan una l delante de
todo lo demás:

lv_ebeln = ‘5200016351’

Los parámetros de entrada de subrutinas y funciones se pueden comenzar


por con pi_
… y los de salida con po_
FORM f_ejemplo USING pi_ebeln TYPE ebeln

            CHANGING po_ebelp TYPE ebelp.

También podría gustarte