En defensa de Visual Basic.Net y las “buenas practicas”

Primero el Disclaimer: La herramienta a la que le tengo mas cariño y con la que he sido mas productivo es Borland Delphi (ahora Embarcadero, pero la que yo conocí era de Borland), dicho esto pasemos al grano.

El titulo del post proviene a razón de la ultima sesión de Mad.Nug en la que Jorge Serrano compartió su experiencia sobre las posibles acciones a tomar cuando se tienen aplicaciones en Visual Basic 6 y existe la necesidad/presion/requerimiento de migrarlas a .Net, la sesion fue muy explicativa, recordandonos cuales son los puntos donde hay mas incompatibilidades y las posibles opciones:

– Herramienta de migración automática
– Entorno mixto (Microsoft Interop Forms Toolkit 2.1 y wrappers)
– Empezar todo desde cero.

De acuerdo a su experiencia (corrígeme si te estoy referenciando mal, Jorge) debería procurarse por la ultima opción (en ese sentido Jorge facilito un buen enfoque para acometer esos proyectos), y estar alertas ante el riesgo de que una solución puntual como un entorno mixto crezca y pierdas el control.

Si bien comparto la idea de que hay casos en que no queda otra que proceder de esa manera, creo que esa decisión tiene que ser sopesada teniendo en cuenta criterios como: cantidad de lineas de código existente, dependencia de terceros, disponibilidad de conocimiento funcional, etc… en ese sentido se sintió la falta de cubrir posibles estrategias de cuando se ha decidido ir por el camino de la migración (que igual se hace para algunas aplicaciones, dejando el resto a un rehacer desde cero).

Bueno, a lo que iba, como parte del camino de un rehacer desde 0, Jorge planteo que había que procurar migrar hacia C# en lugar de hacia VB.Net, ¿por qué? es lo que nunca me queda claro, salvo por un hecho (mencionado en la reunión) que es la mayor disponibilidad de recursos en Internet para C# que para VB.Net, pero fuera de ello el acceso hacia el Framework de .Net es básicamente el mismo (salvo excepción que contare luego), por lo que también en la conversación con los asistentes se dejo caer que con C# se es mas ordenado y se encamina hacia las buenas practicas, por lo que ya entramos a un tema de preferencias y es a donde quería llegar.

Admitamoslo, por sus propias características en Visual Basic 6 era muy muy fácil desarrollar con malas practicas y que el código spaghetti generado sea muy difícil de mantener, pero si una cosa tiene Visual Basic .Net es que significo una ruptura sin pasos intermedios con respecto a VB6 a fin de volverlo OOP y compatible con el nuevo Framework (*), y por lo tanto mucha de la laxitud inherente al viejo VB6 ya no existe, es un buen lenguaje OOP y muy valido para aprovechar los conocimientos de sintaxis propios de Basic: Dim, as, Next, End…, el problema gordo es la herencia de mala imagen que lastra el lenguaje, asi que explicar a un manager que seria menos traumatico continuar con VB.Net en vez de C#…. complicado, triste realidad.

Siendo así creo que solo hay dos razones no personales para optar por desarrollar un proyecto en C#:
– Es muy critico contar con todos los recursos de documentación disponibles para un tema en concreto, que lamentablemente en su mayoría están en C# (p.ej. hay casi tres veces mas info para Generics en C# que para Visual Basic).
– Te ha tocado acceder a una parte del Framework que expone justamente un tipo de datos existente en C# pero no en Visual Basic.Net, eso me paso con la versión 1.1, no se si lo habrán solucionado, pero … queda como alerta.

En contraparte tengo algunas razones de productividad para seguir usando VB.Net siempre que puedo:
– Detección automática de algunos errores y de su corrección, esa potencia de mostrarte un subrayado en algunos errores de sintaxis es de veras de agradecerse, y lo mismo con el hecho de que si compilas y saltan errores no tienes que recompilar para ver si has corregido bien o no, conforme vas corrigiendo tu pila de errores se reduce.
– No sensible a las mayúsculas/minúsculas, esta característica va de la mano con lo anterior, si defines bien una variable (usando Camel y Pascal case adecuadamente) y luego la invocas, el hecho de que se te auto corrijan las mayúsculas y minúsculas es una señal inmediata de que no te has equivocado al invocar el nombre de dicha variable.
– Las instrucciones (begin..end..next..) son mas claras que las llaves ({}) para poder hacerse una idea del ámbito de un bloque de código.

Dicho esto, como desarrollador he venido a conocer ambos lenguajes, pero lo fundamental es el Framework, siendo que el saber C# me ha facilitado acceder a ciertos recursos no existentes para VB.Net, pero que luego a la hora de implementar no he vacilado en aplicarlos sobre proyectos en VB.Net, así que es bueno saber ambos, pero uno no debería de inhibirse y proponer el uso de VB.Net en los proyectos.

Pero algo se me quedo dando vueltas ya desde la sesión a propósito de eso de que C# te ayuda a ser mas ordenado (o algo así), y a esto se sumo el comentario de uno de los asistentes comento que ellos tenían una aplicación grande en VB6, basada en COM+/MTS, hecha según las recomendaciones que daba Microsoft por entonces para el desarrollo en COM, lo cual me hizo retroceder a la época en que este diagrama salia en toda presentación de arquitectura y diseño de aplicaciones alla por el final de los 90s:

Pongámonos en contexto, para el lanzamiento de Visual Basic 6, ya había un gran parque de aplicaciones en VB4 y VB5, pero la fama del “DLL Hell” ya era muy fuerte, así que Microsoft emprendió una campaña muy intensiva para explicar el concepto de desarrollo de aplicaciones distribuidas, las ventajas del multicapas en la mantenibilidad de las aplicaciones, etc etc… conceptos que ahora son el pan de cada día en los objetivos de los diversos proyectos actuales, fueron recien conocidos para muchos gracias a Microsoft, y la verdad es que en ese entonces Microsoft se preocupo mucho en hacer pedagogía de las buenas practicas, tan así que en los cursos de certificación se hacia énfasis en lo que hay detras de la instanciación de objetos en COM para de esa manera impulsar formas mas ordenadas de programar, y lo bueno de todo es que esa pedagogía era de manera no agresiva, planteándola como una evolución de las aplicaciones que habia en desarrollo entonces, a fin de que los programadores mejoraran sus practicas frente a la fama de caos, o sea se pugnaba (por entonces) un cambio evolutivo en las formas de hacer las cosas apoyándose en lo que los desarrolladores ya conocían, lo cual condujo a que los partners serios si que hicieran aplicaciones buenas y solidas usando VB6.

Para bien o para mal todo cambia con la introducción de .Net, que como ya hemos indicado en este y otros posts vino a ser un ruptura muy fuerte, en la que sobrevivía el que tenia mejor las bases de OOP y/o Windows DNA. Claro, ya lo peor paso (salvo las app VB6 que se resisten a morir) y la cosa esta mas o menos estabilizada, salvo por la nueva tendencia del famoso patron SOLID, sobre el cual ya comente que tenia mis dudas sobre si facilitaban la mantenibilidad de las aplicaciones, pero que en todo caso hay que entenderlas y saber como y cuando aplicarlas, siempre sin dogmatismos.

Y es justamente que ahora los dogmatismos se hacen presentes, pues en lugar de introducirnos progresivamente a las nuevas “buenas practicas” se nos pide que ya no usemos ni Windows Forms (aunque si, podríamos pasar a WPF) ni Windows Forms, diciendonos que “no es testeable” “no permite xxx principio” de buenas a primeras sin mostrar evolutivamente como mejorar el código que estamos desarrollando, de ahi a lo que dije en un twitt reciente: Si nos explicasen las pruebas unitarias con ejemplos basados en multicontroles, eventos y mantenimientos, igual las adoptariamos #digonomas (o este otro), digo eso porque la mayoría de las aplicaciones corporativas de uso interno (no portales de contenido) terminan siendo eso y no los clásicos ejemplos de calculadoras o números perfectos, así que seria bueno que los planteamientos de difusión sobre TDD o SOLID partan de un enfoque evolutivo y no rupturista (dando cobertura tanto a VB.Net como C#) a fin de lograr una mejor adopción.

A ver si no llega alguien por aquí diciendo que he “perdido el punto”… xD

(*) Y si, sigo creyendo que muchos traumas se hubieran evitado si al hacer .Net (y C#) se hubiera mirado lo que tenia VB6 a fin de hacer la ruptura menos dolorosa.

Pensando en estrategias de migración de VB6 a VB.Net

Casi a hilo de lo que comentaba en el anterior post, hace poco Jorge Serrano publico Cada vez que migras una línea de código de VB6 a .NET se muere un gatito en el mundo, interesantisimo post que vale la pena leer pues resume muy bien los dilemas, actitudes,creencias erróneas y decisiones que se acometen cuando se tienen aplicaciones en Visual Basic 6 y se piensa el migrar a .Net como una opción a considerar.

Me detendré poco en el tema de la discusión de si migrar si o migrar no, pero en mi modesta opinión creo que los criterios de discusión deberían girar alrededor de (entre otras) estas preguntas:
– ¿Qué tan diferente son los procesos de negocio de la organización de como eran cuando la aplicación fue construida?
– ¿Son los algoritmos técnicos de las aplicaciones aun validos para los procesos de datos?
– ¿El esfuerzo de “entender” la aplicación actual y documentar la especificación de la nueva es mayor que el de la “simple” migración? (Cuando no queda nadie del equipo original)

Llegados a nuestro escenario “pues si, necesitamos migrar esa aplicación pues ya cada vez es mas difícil mantenerla y vamos a migrar de plataforma….. ” hay que plantearse las cosas de como acometerla, no tanto desde el punto de vista técnico, que para eso hay suficiente información en Internet, sino mas bien de cuales serian los pasos razonables para lograr el objetivo de una migración exitosa.

Con esas miras puestas, la experiencia que he tenido recientemente me llevan a plantear dos pequeñas metas antes de la migración en si:
– Reducir todo lo que se pueda la cantidad de lineas a migrar.
– Reducir y aislar los comportamientos críticos no migrables.

Cuando hablo de reducir la cantidad de lineas a migrar, parto del hecho de que es mas que probable que la aplicación a migrar hay sufrido modificaciones durante su tiempo de vida, lo cual haya ocasionado que métodos o clases que antes eran invocados se hayan convertido en código muerto, y reducir ese código muerto antes de la migración deberá ser uno de los principales objetivos que debamos de plantearnos, puesto que es preferible saber de antemano que código ya no es invocado (y eliminarlo/comentarlo) que matarnos en hacer que funcione para luego saber que … sorpresa.. sorpresa… era código muerto.

El tema de los comportamientos de lenguaje no migrables (“As any”, redimensionamiento de arrays …) es complicado, por lo que creo que es conveniente, en la medida de lo posible tomar las acciones para reducirlos antes de la migración y si eso no es posible marcar dicho código como problemático.

Ahora bien, estos son objetivos loables, pero lamentablemente difíciles de conseguir con las herramientas de Microsoft “out of the box”, que si que el Code Analysis de VS .Net nos facilitara el encontrar las referencias “muertas”, pero lamentablemente el tener una información completa de este tipo solo sera posible cuando el código migrado compile sin errores, pero claro… volvemos a lo mismo podemos pasarnoslas divertidos corrigiendo código para luego descubrir que ese código no era invocado en ningún lugar.

Entonces queda claro que el análisis de dependencias es critico, y lamentablemente no queda sino recurrir a herramientas de terceros, concretamente he estado probando Project Analyzer con resultados muy interesantes pues ademas de encontrarme con la opción de encontrar todo el código muerto, me detecto todos las porciones de código que requerían migración manual.

Así pues, creo que el contar con una herramienta de ese estilo (he mencionado Project Analyzer, pero igual podría ser alguna otra) cobra un importancia muy especial en esta clase de proyectos, ya que permite cubrir los dos primeros objetivos señalados y llevando de rebote una ventaja adicional: darnos cuenta, mediante el análisis de dependencias de que porciones de código no compatible como llamadas a la API de Windows, podrían ser reemplazadas por código .Net.

Ese análisis e identificación de codigo critico seria un primer paso, de ahí vendrían los siguientes:
– Refactorización, si, se puede, y nos ayudara a tener nuestro código heredado mas legible.
– Preconversión de código no migrable a código migrable, donde sea posible y se sepa que se seguirá usando luego de la migración.
– Migración en si, ya sea usando Visual Studio o una herramienta de terceros, y de ahí las sucesivas iteraciones para estabilizar el producto hasta el nivel deseado (reemplazo de ADO por ADO.Net, eliminación de los Interop….)

Es obvio que este proceso iterativo por lo que no conviene dar un paso nuevo hasta que no se sepa que la nueva versión sigue haciendo lo que hacia antes, de ahí la importancia de tratar de acometer la mayoría de los cambios posibles antes de la migración en si.