Tutorial ABAP-Estilo Programacion
Tutorial ABAP-Estilo Programacion
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.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.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.
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
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.
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
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.
Verificación ATC
Verificación ATC ampliada
Code Inspector
CITA CÉLEBRE
”Si hubiera preguntado a mis clientes, me habrían pedido un caballo más
rápido”
Henry Ford
1.2.9
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!
CITA CÉLEBRE
”La optimización prematura es el origen de todos los males”
Donald Knuth, autor de “The Art of Computer Programming”
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.
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).
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.
* --- 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
IF <lfs_stb>-idnrk IS NOT INITIAL.
…
ENDIF.
ENDLOOP.
DESPUÉS:
LOOP AT li_stb ASSIGNING <lfs_stb> where
idnrk IS NOT INITIAL.
ENDLOOP.
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.
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.
IF NOT v_stop IS INITIAL
IF v_stop IS NOT INITIAL
IF sy-subrc <> 0.
ELSE
ENDIF.
IF sy-subrc = 0.
ENDIF.
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.
NOMENCLATURA_ABAP
NOMENCLATURA_PROGRAMAS
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’