PiensoPienso: Cual es la salida de estos programas.

Problema: Listar los clientes que tienen Saldo 0

Tabla Clientes
*ClienteId
ClienteNombre
ClienteSaldo 

La tabla tiene los valores
ClienteIdClienteNombreClienteSaldo
1Gill Bates0
2Jeeve Stobs10
3Jicolas Nodal20

Hay 2 versiones del programa que son procedure GeneXus (main y command line) con el código:

//==== Version 1 ============
for each  order ClienteNombre
    If ClienteSaldo = 0
 Msg(Format('Cliente %1 %2 Saldo: %3 ',ClienteId, ClienteNombre, ClienteSaldo),status )
  endif
endfor

// ==== Version 2 usando rutinas ====
for each order ClienteNombre
      do 'Mensaje'
endfor

Sub 'Mensaje'
If ClienteSaldo =0
       Msg(Format('Cliente %1 %2 Saldo: %3',ClienteId, ClienteNombre, ClienteSaldo),status )
Endif
endSub

Cual es la salida de ambos programas?

Comentarios

  1. No estoy como para probarlo, pero pienso que la salida puede ser esta:

    // == Version 1 ==
    Cliente 1 Gill Bates Saldo: 0

    // == Version 2 ==
    Cliente 0 Gill Bates Saldo: 0
    Cliente 0 Jeeve Stobs Saldo: 0
    Cliente 0 Jicolas Nodal Saldo: 0

    Porque en la versión 2 el único atributo que participa del For Each es ClienteNombre y por lo tanto es el único que tiene valores.

    ResponderBorrar
  2. Yo creo que es:

    // == Version 1 ==
    Cliente 1 Gill Bates Saldo: 0

    // == Version 2 ==
    Cliente 1 Gill Bates Saldo: 0
    Cliente 2 Jeeve Stobs Saldo: 0
    Cliente 3 Jicolas Nodal Saldo: 0

    Porque el for each carga ClienteNombre por estar en el order y ClienteId por ser clave, pero no ClienteSaldo...

    Igual, ¿a quién se le ocurre programar así? :)

    Lo mejor sería hacer:

    for each
    order ClienteNombre
    where ClienteSaldo = 0

    Msg(Format('Cliente %1 %2 Saldo: %3 ',ClienteId, ClienteNombre, ClienteSaldo),status )
    endfor

    para que se resuelva en el servidor...

    ResponderBorrar
  3. Alejandro: :)

    Pablo:
    Tu respuesta es correcta.
    A mi me gustaria que GeneXus avisara toda vez que se accede a un atributo en el codigo fuera de un for each, pues la mayoria de las veces pasa inardvertido y es fuente de errores, como en el este ejemplo.

    Por un error de interpretacion, quedan todos los registros como con saldo 0 y no es la respuesta correcta.
    Si por algun motivo se hubiese accedido a un ClienteSaldo con un valor <> 0 listaria todos los clientes con ese valor.

    Es bastante peligroso!.

    Gracias por los comentarios.

    ResponderBorrar
  4. Marcos:
    Es ciero lo que decis. Queda mejor programado como vos lo planteas, pero lo que queria mostrar es lo dificil que queda leer el codigo cuando se accede a atributos fuera de for eachs. Hay errores que quedan muy escondidos y seria bueno contar con ayuda de GX para detectarlos.

    Gracias

    ResponderBorrar
  5. No es la primera vez que ponés un Pienso Pienso de este estilo.

    La verdad nunca programo así, en ningún caso utilizo en una subrutina atributos de otro For Each, siempre los cargo en variables o lo paso a un procedimiento.

    Pero tampoco evita problemas, ya que es muy común olvidarse de cargar alguna de esas variables.

    100% de acuerdo con qué GX debería avisar, o al menos permitir configurarlo para avisar en estas situaciones.

    ResponderBorrar
  6. Pablo:
    Nadie programa asi de entrada.
    Este tipo de problemas, viene cuando se hace algun refactoring de la aplicacion para mejorar el codigo y se introducen este tipo de errores.

    Los problemas que planteo, son cosas que me encuentro en el desarrollo diario. Se que ya hice un problema parecido, pero creo que esta bueno tener bien presente este tipo de problemas. A mi plantearlo de forma bien sencilla me ayuda a conceptualizarlo mejor. A lo mejor podemos lograr que proyectos como el Genoma incorporen alguna forma de deteccion de este tipo de defectos.

    ResponderBorrar
  7. Muy bueno!!
    Recuerdo ese caso, en algún momento me tocó corregir algunos programas con ese problema.

    Y la navegación que te muestra?

    Me hizo acordar a los casos de "Los atributos perdidos" que infieren navegaciones" (atributos que están en Printblocks, pantallas o código que hacen navegar con tabla base.. por descuido de alguien.. suele suceder con los saveas, o copy paste.. detectarlos en programas grandes después es un parto).

    ResponderBorrar
  8. David: La navegacion no muestra nada anormal, solo que no muestra que accede al atributo ClienteSaldo. Estaria bueno que mostrara un warning..

    ResponderBorrar
  9. Lo interesante entonces está en que le falta inferir información desde las subrutinas.

    Así como infiere información de los "Print", debería de poder hacerlo de los DO.

    Y claro, si una subrutina llama a otra, debería también inferir navegaciones hasta lograr todo el árbol de llamadas.

    De todas formas.. yo soy "contra" las inferencias automáticas, para mí todo tiene que ser visualmente inferido (alguien que se pone a leer el código fuente tiene que poder conocer qué está haciendo).

    Me encantaría en un futuro que GeneXus a medida que programamos tenga información de especificación en línea y que "autodocumente" con comentarios las navegaciones.

    Hoy eso lo hago a mano (Buena Práctica), lo que hago es documentar accesos e inclusive indicar en los comentarios el índice utilizado (el que GeneXus dice que va a usar, ya que es importante para tener la información en modo lectura).

    Habría que ver si es posible hacerse de una extensión que pueda autodocumentar esa información infiriendo de las navegaciones obtenidas de la spec :)

    Y estaría también ver de poder indicar de alguna forma o crear una extensión en donde no se permita usar algunas técnicas de inferencia o lo que algunos ven como malas prácticas (como el caso que mencionas en este post).

    ResponderBorrar
  10. Yo pienso, pienso, vuelvo a pensar y descubro algo que ustedes no vieron.
    Nunca GeneXus va a advertir si en los datos de prueba el que debe más es Jicolás Nodal, jeje.
    Arturo de Puerto Sauce

    ResponderBorrar

Publicar un comentario

1) Lee el post
2) Poné tu opinión sobre el mismo.
Todos los comentarios serán leidos y la mayoría son publicados.

Entradas más populares de este blog

Aplicación monolítica o distribuida?

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Funcionalidades de GeneXus que vale la pena conocer: DATE Constants.