martes, 30 de abril de 2013

SAP ABAP: Recursividad VS ejecución lineal

Realizando pruebas para ver si es viable el uso de la recursividad en SAP. Me encuentro con el siguiente resultado que os mostraré a continuación.

Para realizar la prueba ejecuto el siguiente programa muy sencillo y creo que fácilmente comprensible. Bien según mis experiencias anteriores sobre la ejecución de métodos recursivos frente a los que no lo son, me dice la experiencia que la recursividad gana en la mayoría de los casos. Y claro dentro de la burbuja del mundo SAP, yo creía que un sistema donde se ejecuta en máquinas "BRUTALES" la recursividad sería perfecto para no derrochar recursos. Así que comienzo a ejecutar lo siguiente:

DATA: lv_total  TYPE i VALUE 0,
      lv_aux    TYPE i,
      lv_inicio TYPE i,
      lv_fin    TYPE i,
      operador  TYPE i VALUE 1000.

PARAMETER lp_suma TYPE i DEFAULT 9999.

START-OF-SELECTION.

  lv_aux = lp_suma. "Almacenamos el valor
  GET RUN TIME FIELD lv_inicio.
* Metodo con secursividad --------------------------------------------------------

  PERFORM suma USING lp_suma lv_total.

*  -------------------------------------------------------------------------------
  GET RUN TIME FIELD lv_fin.
  lv_fin = ( lv_fin - lv_inicio ) / operador.
  WRITE: / '(RECURSIVO) tiempo de respuesta: ', lv_fin , ' milisegundos'.
* ---------------------------------------------------------------------------------
* ---------------------------------------------------------------------------------
  WRITE: /.
  WRITE: /.
* ---------------------------------------------------------------------------------
* ---------------------------------------------------------------------------------
  lp_suma = lv_aux. "cargamos su valor
  lv_aux = lv_fin.
  lv_total = 0.
  GET RUN TIME FIELD lv_inicio.
* Metodo sin secursividad --------------------------------------------------------

  WHILE lp_suma > 0.
    lv_total = lv_total + lp_suma.
    lp_suma = lp_suma - 1.
  ENDWHILE.
  WRITE: 'resultado ', lv_total.

* --------------------------------------------------------------------------------
  GET RUN TIME FIELD lv_fin.
  lv_fin = ( lv_fin - lv_inicio ) / operador.
  WRITE: / '(NO RECURSIVO) tiempo de respuesta: ', lv_fin , ' milisegundos'.

  WRITE: /.
  WRITE: /.
  IF lv_aux < lv_fin.
    WRITE: / 'La recursividad es la mejor solución'.
  ELSEIF lv_aux = lv_fin.
    WRITE: / 'EMPATE!!!!'.
  ELSE.
    WRITE: / 'El while es la mejor solución'.
  ENDIF.

FORM suma USING lv_suma TYPE i
                lv_total TYPE i.

  IF lv_suma GT 0.
    lv_total = lv_total + lv_suma.
    lv_suma = lv_suma - 1.
    PERFORM suma USING lv_suma lv_total.
  ELSE.
    WRITE: 'resultado ', lv_total.
  ENDIF.

ENDFORM.

El programa ejecuta inicialmente una función recursiva y seguido ejecuta el mismo proceso sin aplicar recursividad. Finalmente en la pantalla muestra el resultado de la operación junto con los milisegundos que ha durado ambas. Y para mi sorpresa me encuentro lo siguiente:
resultado  49.995.000
(RECURSIVO) tiempo de respuesta:          49   milisegundos


resultado  49.995.000
(NO RECURSIVO) tiempo de respuesta:          24   milisegundos


El while es la mejor solución
Bueno para mi desgracia la recursividad no es una solución.

jueves, 25 de abril de 2013

Python excepciones, profundizando mucho más

Vale muy bien, ya sabemos cómo se usan los try. Pero..... no está mal saber que clases de excepciones estándar tenemos disponibles. Os paso un diagrama en árbol de las excepciones estándar más comunes. La más genérica es exception pero si queremos realizar diferentes tratamientos no estaría mal saber algunas más.
Exception(*)
 |
 +-- SystemExit
 +-- StandardError(*)
      |
      +-- KeyboardInterrupt
      +-- ImportError
      +-- EnvironmentError(*)
      |    |
      |    +-- IOError
      |    +-- OSError(*)
      |
      +-- EOFError
      +-- RuntimeError
      |    |
      |    +-- NotImplementedError(*)
      |
      +-- NameError
      +-- AttributeError
      +-- SyntaxError
      +-- TypeError
      +-- AssertionError
      +-- LookupError(*)
      |    |
      |    +-- IndexError
      |    +-- KeyError
      |
      +-- ArithmeticError(*)
      |    |
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      |    +-- FloatingPointError
      |
      +-- ValueError
      +-- SystemError
      +-- MemoryError
Un ejemplo de su uso
parsed = False
while not parsed:
    try:
        x = int(raw_input('Mete el primer valor: '))
        y = int(raw_input('Mete el segundo valor: '))
        result= x/y
    except ValueError:
        print 'Numero introducido erroneo!!!'
    except ZeroDivisionError:
        print "dividir por CERO!! LOKO!!"
    else:
        parsed = True
        print "resultado: ", result
Si queremos provocar la ejecución de una excepción podemos usar raiser.
try:
    raise Exception()
except:
    print "ERROR: ", sys.exc_type + ":", sys.exc_value
Por último nos crearemos nuestra propia excepción.
class MyPropioError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

try:
    raise MyPropioError("Algo muy gordo a pasado")
except MyPropioError, e:
    print 'Se ha ejecutado, value:', e.value
Esto mostrará el texto "Algo muy gordo a pasado"

Python excepciones, cómo se usan

La estructura de un try en python es la siguiente:
try:
    Sentencias que podrán dar a posible error
except IdentificarError:
    Que ejecutamos cuando se produce el error
finally:
    Sentencias que se ejecutan siempre. Exista o no el error
else:
    Sentencias que ejecutamos en caso de no existir el error
Os muestro un ejemplo clásico de la división por 0
try:
   result = 10 / 0
 except ZeroDivisionError:
      print "dividir por CERO!! LOKO!!"
 else:
      print "resultado: ", result
Si quereis entrar en más detalle. Os recomiendo Python - Errors and Exceptions

ABAP CRM: funciones estándar para sacar organización, grupo... de ventas

Desde la transacción SE37 podemos buscar la lista de todas las funciones buscando por:
CRM_MAPPING*

martes, 9 de abril de 2013

micro consejos para programadores - parte9


  1. Sí no recuerdo mal (a*a*a)*(a*a*a) es mejor que a*a*a*a*a*a está última son 5 líneas en ensamblador y la otra son 3
  2. Reutilizar variables por ejemplo de un objeto en java ejecutando de nuevo user=new Usuario() y listo para usar.
  3. Al construir una sentencia SQL son más optimas si respetamos el orden de los campos.

lunes, 8 de abril de 2013

micro consejos para programadores - parte8

Hoy extra de micro consejos

  1. Usar etiquetas eTags y expires es mejor que tener que obligar a descargar el site entero y Google te premiará.
  2. Entre los algoritmos de ordenación sort y qsort este último es mucho más rápido.
  3. Sí trabajas con ficheros es mejor cargarlo en bloques en memoria y trabajar desde hay (un clásico)

micro consejos para programadores - parte7


  1. Por supuesto tenía que decir que los métodos recursivos son mejores.
  2. Cada estilo CSS mejor en una línea que escritos en bloque. Más rápido leer una línea de un golpe que 5 o más.
  3. Usar algún loadscript para Js es una buena práctica para descargar simétricamente el contenido web.