sábado, 14 de junio de 2008

No hagáis esto en casa...

Antes de empezar aclaro: la siguiente anécdota está inspirada en hechos reales que pueden haber sido distorsionados o exagerados, que ningún conocido se sienta tocado.

En un día cualquiera, en un sistema en desarrollo cualquiera basado en uno "viejo" pero productivo, necesito una función que haga X. Como uno de los requerimentos básicos es "que haga lo mismo de antes", tomo como referencia el código viejo, escrito en VB. Lo leo, intrincado y feo (todo código en VB se me ha vuelto feo desde que me acostumbré a C#, y eso que VB me ha dado de comer por mucho tiempo) pero útil, al fin y al cabo es para una funcionalidad bastante acotada.

Tal vez el hecho de que el desafío no es muy apasionante haya influído en mi decisión, que fue la de traducir el código sin reparar demasiado en la lógica general. Algunas herramientas hacen esto automáticamente, pero quería por lo menos cambiar los nombres de las variables que no me gustaban, entenderlo en detalle y dejarlo prolijo, así que decido hacerlo a mano.

En general es algo lindo de hacer si uno no tiene ganas de pensar, que era el caso. Así que me pongo los auriculares, buena música y más o menos en una hora y media tengo todo traducido y bonito.

Lo pruebo. Obviamente no va para ningún lado. Media hora más depurando errores en la traducción.

Lo vuelvo a probar y funciona ok. Pruebo un par de casos más y en algún lado algo anda mal. Vuelvo a probar y otra vez funciona. Sigo así hasta que llego a un conjunto de datos de entrada bastante reducido, en el cual algunos casos daban bien y otros mal.

Tres horas depués...

El mismo conjunto de datos. A veces anda, a veces no. Tengo ganas de tirar el monitor al suelo, de romper todo y empezar de vuelta, de irme a casa, de hacer otra cosa, de empezar otra carrera, de cambiar de rubro. Me cuesta mantenerme concentrado, miro pero no veo. Decido probar una vez más (y van...) pero esta vez sin dar absolutamente nada por supuesto, así que entro a cada función, en cada llamada, no dejo nada sin revisar.

Y lo encuentro. Mejor dicho me doy cuenta, porque estuvo ahí, delante de mis narices todo el tiempo. Vuelvo al código original. Comparo. Es eso. Corrijo y pruebo, incrédulo. Si, es eso, ahora funciona.

Ganas de matar. En general a cualquiera, pero especialmente a alguien en particular. Porque cuando me encuentro con cosas así no puedo evitar ir al control de código fuente para saber quién fue el retorcido que escribió eso.

Voy a intentar una explicación. Recordemos que hice la traducción a mano, y que en general el proceso es bastante simple. Está encapsulado en una sola clase en la que se establecen un par de propiedades y se llama a un método que devuelve un resultado, y nada más. Adentro de esa clase decía:

Public Class RetorcidaVB Private Dim miVariable1 As Integer ...(etc)... Public Function Resultado() as Integer ...(etc)... If Me.SumaDeAlgo()=xxx And Me.SumaDeOtraCosa()=yyy And Me.SumaDeAlgoMas()=zzz Then ...(etc)... End Function End Class

y yo en C# escribí:

public class Retorcida { private int _miVariable1; ...(etc)... public int Resultado() { ...(etc)... if( this.SumaDeAlgo()==xxx && this.SumaDeOtraCosa()==yyy && this.SumaDeAlgoMas()==zzz ) ...(etc)... } }

Esto era lo que yo veía. ¿Dónde puede estar la diferencia? Hagamos una cosa. Esta historia continuará. Si alguien quiere enviar un comentario indicando cuál es la diferencia, bienvenido. Como están moderados, prometo liberarlos junto con la segunda parte, para no aguar el acertijo.

Actualización: Ya saqué la segunda parte, que puede leerse aquí.

2 comentarios:

Juan dijo...

Así a "golpe de pájaro" (puede ser un avestruz) "And" <> "&&"

Sebastián Streiger dijo...

La diferencia es que en VB,
If Me.SumaDeAlgo()=xxx And Me.SumaDeOtraCosa()=yyy And Me.SumaDeAlgoMas()=zzz
Siempre evalúa SumaDeAlgo, SumaDeOtraCosa, SumaDeAlgoMas, independientemente de si la las anteriores resultaron falsas.
En cambio en C# la evaluación se realiza solo si es necesario.
Si el resultado de alguno de los términos booleanos permite obtener el resultado de toda la expresión el resto de la expresión no se evalúa.
Esto solo presenta problemas o diferencias de performance entre los 2 lenguajes, siempre y cuando las funciones no tengan efectos colaterales, que seguramente es lo que sucedía en el caso tuyo.
Lindo post!!!