domingo, febrero 23, 2014

FoxBin2Prg: Control de código fuente con PlasticSCM

[Actualizaciones]
01/03/2014 - Agregado apartado sobre las herramientas de productividad incluidas (scripts .vbs)
26/02/2014 - Agregada aclaración sobre el merge del minuto 00:29:48 del video
--------------------------

Por: Fernando D. Bozzo

En esta nota voy a comentar cómo sería el trabajo con control de código fuente y FoxBin2Prg. Aunque el ejemplo es con PlasticSCM, la operativa general en el desarrollo se aplica a cualquier SCM.


Primero una breve mención a SourceSafe


Para quienes lo sigan usando, les recomiendo pasarse cuanto antes a cualquier otra herramienta SCM. El motivo principal es que Microsoft ya no soporta este producto, cuya última versión es de 2005 (Visual SourceSafe 2005, versión que muchos desconocen) y una gran mayoría de los que lo usan siguen con la que salió en Visual Studio 6, que es del año 1998 más o menos!
Tiene, además un gran problema de escalabilidad y para mantener el histórico de los archivos, cosa que en un SCM es algo crucial. Simplemente es demasiado fácil borrar archivos del historial sin querer o por problemas internos, y no son recuperables.
Si a pesar de la advertencia no les queda otra que seguir usándolo, sepan que FoxBin2Prg se integra bién con el mismo gracias al archivo de configuración foxbin2prg.cfg y la reasignación de extensiones, de hecho, permite usarlo para hacer el merge de los binarios como nunca lo habíamos visto ;-)


Ahora sí, a lo que nos ocupa


En esta ocasión voy a comentar sobre el trabajo con PlasticSCM, una herramienta SCM de pago, pero que permite su uso gratuito a cualquier persona o grupo de hasta 15 miembros y que se use para controlar el código de cualquier tipo de aplicación comercial o de uso interno. Solo es necesario registrarse con un email válido, descargarse la última versión (sacan una cada 2 semanas o menos) y generar y descargarse el archivo de licencia de 15 usuarios que debe renovarse cada 6 meses de forma gratuita.

El programa es multiplataforma (Windows, Mac, Linux [con WINE]) e incluye el componente cliente y servidor, pudiendo instalarse ambos o uno solo, ya que por defecto utiliza Microsoft SQLCE 3.5 en Windows (hasta 4 GB por base de datos) y SQLLite en Linux. El backend es configurable, soportando SQLServer, MySQL, Postgress y otras bases de datos, lo que permite instalar el componente cliente en un PC y el componente servidor en un servidor dedicado, aunque también se pueden instalar ambos componentes en la misma PC de desarrollo (yo lo uso así).

La configuración usada ha sido la de usuario/password manejada desde el gestor de usuarios incluido, pero permite varios esquemas de autenticación, incluyendo LDAP, Directorio Activo y otros.

La configuración interna que usé para trabajar es esta:




Estas son las herramientas en Visual FoxPro preparadas para trabajar con PlasticSCM (todo lo necesario, incluyendo el ejecutable v1.19.12 de FoxBin2Prg):
https://github.com/fdbozzo/foxpro_plastic_diff_merge (el README.txt explica como configurarlas, tanto en Español como en Inglés)

FoxBin2Prg puede ser usado con la interfaz SCCAPI 1.0 (la que usa SourceSafe) o solo, pero recomiendo usarlo solo, o sea, no usar la integración de Visual FoxPro con SCCAPI, ya que limita mucho lo que se puede hacer, y sobre todo la forma de trabajar.
SCCAPI estaba pensada (o configurada) para bloquear los archivos cuando se desprotegen, lo que impide que otros desarrolladores puedan trabajar con el mismo archivo. Esto en un entorno de desarrollo local o distribuido no es escalable, ya que se depende de que quien tenga el archivo bloqueado lo libere cuando pueda o quiera, y un desarrollo no puede depender de eso.

Trabajar sin la integración FoxPro/SCCAPI tiene muchas ventajas, aunque para quienes venían trabajando de esa forma (yo incluido:) les pueda resultar algo no natural al principio, ya que implica un cambio de mentalidad, pero que con la práctica se puede comprobar que es mejor, y como ventaja adicional, los proyectos abren mucho más rápido, como ha sido siempre para los proyectos que no están bajo control de código integrado con SCCAPI.

Video del ejemplo usado en este post:



Esquema de trabajo en FoxPro con un SCM


La que voy a describir es la forma de trabajar que encontré más cómoda, pero no es la única, y se basa en el trabajo en rama por tarea, un concepto en el que ya hablaban los de Coding Horror allá por 2007. Esto quiere decir que para cada tarea se hace una rama, se trabaja en ella, y cuando se finaliza la tarea y las pruebas unitarias, se integra en la rama principal o en la de testing integrado.



En nuestro ejemplo hay dos desarrolladores, Dev_1 y Dev_2. Se comienza partiendo desde la rama principal o Trunk (/main en el ejemplo), que contiene la última versión estable del proyecto, en este caso la v1.0, se la que se crea una rama de testing integrado, llamada "TESTS" en este caso, y cada desarrollador se crea una rama particular de trabajo desde la v1.0

Si hubiera más desarrolladores, la mecánica sería la misma, cada uno se crea su propia rama partiendo de la última Release estable.

Luego se hace el desarrollo, cada uno por su lado, con la seguridad de que ninguno interferirá con el otro, en el sentido de bloquear al otro, como pasa en SourceSafe.

El video muestra como cada desarrollador tiene que hacer una serie de modificaciones en los mismos componentes (el peor caso), siendo estos un form, una librería de clases, un reporte, un report label y un menú.

Dev_1 tiene que agregar un campo de Costo en la página DATOS de un pageframe de un form:



Dev_2 tiene que agregar una nueva página CALCULOS al mismo pageframe del mismo form:



Este form usa la clase form_bus de una libreria de clases de negocio llamada test.vcx
La librería tiene un método existente, pero cada desarrollador necesita agregarle un método. Dev_1 necesita agregarle el método set_Costo_Articulo() y Dev_2 el método set_PrecioArticulo(). Cada uno hace sus pruebas por separado, y finalmente integran sus cambios en la rama TESTS para poder hacer pruebas integradas entre Dev_1 y Dev_2 antes de que suba todo a la rama principal.

Para hacer el check-in del código se deben generar las vistas de texto con FoxBin2Prg.


[Actualizado - 26/02/2014 >>]
Respecto del merge manual, cuando toca hacerlo, en la vista de Merge se muestran tanto las versiones texto como los binarios. Como en esta operación lo que "manda" son las versiones texto, ya que son las que se mezclan visualmente, hace que los binarios se deban pasar "como están" a la vista de cambios pendientes, y por eso se puede ver como en el minuto 00:29:48, una vez terminado el merge de los tx2 se seleccionan los binarios que quedan y se elige "Merge keeping workspace changes" o "Mezclar manteniendo los cambios del workspace". Esto los deja en el panel de "Pending Changes" o "Cambios Pendientes", donde se regeneran desde las versiones tx2 recién mezcladas para mantenerlos sincronizados. [<<]

Se debe tener cuidado de que las librerías, forms, etc, no estén abiertas en alguna sesión de FoxPro, porque si no será imposible para FoxBin2Prg abrir el archivo para realizar su trabajo, y mostrará un error, además de generar un .ERR para el archivo en cuestión. Por ello, recordar hacer CLEAR ALL/ CLOSE ALL antes de las conversiones.

Regenerar los binarios de esta manera tiene otra ventaja: Para quienes tengan librerías de clases o forms de varios años y con muchas modificaciones o que han pasado por muchas manos, les habrá pasado de que a veces se pueden comportar de forma extraña o dar errores, o el clásico "agrego un código en un método pero se sigue ejecutando el método viejo!", que es una de las formas más raras de corrupción de una clase o form. En estos casos, el paso a texto y posterior regeneración del binario soluciona algunos problems, y en todo caso, por lo menos se puede ver e código en claro y reparar como un PRG!

Con esta forma de trabajo además no es necesario que se pongan como ReadOnly los archivos a modificar. Solo se hace el check out de binarios y versiones texto a modificar, se hacen las modificaciones, se generan las versiones texto (las llamo TX2), se regeneran los binarios, se hacen algunas pruebas para comprobar que ha ido todo bien y se procede al check in final (binarios y texto). Lo de mantener ambos archivos es por seguridad y por performance. Por seguridad, porque donde se trabaja realmente en diseño es sobre el binario y siempre es bueno tenerlo por si acaso, ya que FoxBin2Prg sigue siendo beta hasta que tenga el suficiente tiempo en uso como para considerarlo versión final, y por performance es porque si el proyecto tiene muchos archivos y solo se guardaran las versiones texto, al hacer el ejecutable final en un servidor de integración (o a mano), habría que sumar el tiempo de regeneración de todos los binarios, lo que podría demorar un rato.

En este punto de comprobar si está todo bien, puede que se quiera hacer un ejecutable para comprobarlo, y obviamente esto provoca que se recompilen todos los binarios y que figuren como modificados ante el control de código fuente. No pasa nada, se pueden comprometer los ficheros cambiados o solo comprometer los que se les haya hecho el check-out previo y deshacer los cambios del resto.

Lo que realmente importa es que para la versión definitiva sí se debe recompilar todo, ya que FoxBin2Prg intenta hacerlo de la mejor forma, pero si se invoca la regeneración de binarios desde el explorador de archivos, FoxBin2Prg no puede saber cuál es el proyecto al que corresponde cada archivo, por lo que lo recompila desde su ubicación, y como consecuencia puede que los archivos #include o referencias a componentes a rutas relativas no se encuentren, dando errores de compilación. Por eso es que siempre se debe realizar una compilación de todo el proyecto en la fase final o de pruebas, así estos problemas desaparecen

Lo de recompilar los binarios al regenerar se hace porque si no hay propiedades o métodos que de otra forma no se ven en tiempo de diseño, aunque realmente estén ahí. Es una cosa extraña, pero sé que pasa y así es como se soluciona, aunque esa compilación provoque los errores comentados.

Si por alguna causa no ha salido todo bien y ha ocurrido algo con el binario, se puede recuperar desde los .BAK que se generan para cada extensión o desde la propia herramienta SCM. La cantidad de .BAK que se hacen por defecto es 1, pero se pueden hacer más si se requiere, indicándolo en el archivo de configuración foxbin2prg.cfg


Vámonos por las Ramas, pero no matemos al Integrador!


La rama TESTS podría no ser única y solo simboliza una rama previa a la principal donde un grupo de desarrolladores que están trabajando en un proyecto determinado hará su integración de código. Podría llamarse "integración_proyecto_X" o de cualquier otra forma, pudiendo haber una rama por cada proyecto independiente.

En el caso de múltiples proyectos que deban integrarse, se puede crear una rama de integración adicional, previa a la "TESTS" de nuestro ejemplo, de modo de repartir el trabajo de integración equitativamente entre los desarrolladores y el integrador principal (debería haber uno) que además es el encargado de verificar el código y los requisitos no funcionales.
Si hay mucha integración, este reparto de trabajo de integración es necesario para "no matar al Integrador", ya que la responsabilidad es muy grande y también lo es la posibilidad de cometer errores, y el Integrador también es humano :-)

Cualquiera que haya realizado esa tarea sabe de lo que hablo.


¿Pero entonces cada desarrollador sube lo que quiere?


No, cada uno trabaja en lo que tenga asignado. El proyecto en el que están trabajando puede haber comenzado hace meses, por ejemplo en la v0.1, pero cuando finalizan conviene que hagan su entrega de código integrándola en una rama de Integración que se crea basada en la última versión estable de Producción, ya que nadie mejor que los desarrolladores para saber qué código debe estar presente sí o sí. De esa forma cargan con una parte de la integración que corresponde a las versiones intermedias que hayan pasado y pueden comprobar que sus cambios funcionan bien antes de pedir la integración definitiva, y es en este "pedir" donde entra en acción el Integrador principal, que gracias a que le entregan el código integrado en la última rama estable los únicos cambios que verá son los realizados por ese proyecto y no tendrá que lidiar con las diferencias entre las distintas versiones, ya que esa parte fue resuelta antes, y eso le permite hacer su trabajo mejor y más rápido y no debe soportar la carga de todo.


Tenemos una librería que se modifica demasiado!


Siempre puede pasar que haya una o varias librerías que tengan un tamaño apreciable y muchos, muchísimos métodos y clases que se están cambiando todo el tiempo y que incluso con FoxBin2Prg muestran muchos cambios y es difícil de integrar: ¿Qué hacer en este caso?  Cuando ocurre eso es porque no se ha previsto su crecimiento o porque se le han hecho modificaciones por muchas manos que no se han animado a hacer lo que se debió hacer desde un principio: Refactorizar

La única solución posible que dará mayor seguridad a futuro y bajará los costes de mantenimiento que cada vez son mayores con cada nuevo cambio es refactorizar como parte del trabajo diario y no sólo cuando las cosas van mal, porque en ese momento ya es tarde y hasta podría ser imposible o demasiado costoso acometer esta tarea postergada miles de veces.


Algunos consejos


Aunque en los requisitos no funcionales se suele incluir la encapsulación y la nomenclatura de variables y objetos, lo cuál no siempre se respeta, en la integración de código esto juega un papel fundamental, ya que cuanto más se respeten estas recomendaciones más fácil será la integración.

Un ejemplo: si en un form se dejan todos los objetos con su nombre por defecto y el form usa pageframes o uno con varias páginas, cuando al momento de integrar toque hacer un merge eso será lo que se vea: pageframe1.container1.textbox1, pageframe1.container1.textbox2, etc. ¿Cómo puede el integrador hacer bien su trabajo si ni siquiera sabe para qué son esos controles cuyo nombre no indican nada respecto de su función u objetivo?

Otro: Dentro de varios "textbox1" que hay en un form, resulta que se requiere en tiempo de merge cambiar uno de sitio o de nombre, debiendo porque resulta que ambos desarrolladores han tenido que agregar uno o más controles y los dejaron con sus nombres por defecto, de modo que el integrador se encuentra con dos objetos con el mismo nombre. ¿Cuál es el bueno? Y si hay que renombrar uno, ¿cómo identificar sus métodos y no confundirlos con el otro?



Una razón más: La nomenclatura correcta permite que las diferencias sen mucho menos, y esto implica dedicar menos tiempo y tener mayor seguridad sobre lo que se está integrando.


Creo que queda claro el problema, y tanto en el video como en la captura anterior se puede ver que uno de los motivos por los que no tuve mayor problema en hacerlos rápido, incluso mezclando los mismos métodos o controles, es gracias a usar una nomenclatura correcta donde cada objeto y variable tiene su nombre con un significado de para qué sirve.


Trabajo yo solo, ¿tiene sentido usar Control de Código?


¡Por supuesto! No solo porque de paso se tiene un backup, sino porque se pueden aprovechar las herramientas relacionadas al SCM, como la herramienta de Diff y Merge. La de Merge no será mayor problema porque al trabajar solo nunca habría conflictos para resolver y todos los merge serán automáticos, pero a la de Diff es a la que mayor provecho se le sacaría, ya que permite ver las diferencias entre las distintas versiones de un programa y eso permite encontrar los errores o las modificaciones realizadas mucho más rápido. Además de todo esto está la historia: Todo lo que se guarda en control de código fuente tiene historia, con lo cuál se puede identificar si una modificación o un error es de hace un mes o de hace 10 años.


[Actualizado - 01/03/2014 >>]

Herramientas de productividad incluidas (scripts .vbs)


Conversando con distintos desarrolladores veo que no todos leen el Readme.txt y la cabecera de los scripts .vbs incluidos.

Las herramientas de FoxPro para trabajar con PlasticSCM son un conjunto de programas FoxPro 9 y scripts .vbs que están preparados para configurarse en el GUI de Plastic

Respecto de FoxBin2Prg en particular, en el artículo "FoxBin2Prg: Detalle de vistas, datos de uso, configuraciones y más", en la última parte de Palabras Finales se describe como agregar los scripts incluidos en el menú "Enviar A" para poder usarlos desde el menú contextual del explorador de archivos. [<<]


Notas finales



Seguramente me esté dejando algunas cosas fuera porque el tema es extenso, pero si fuera así no descarten que lo agregaré aquí mismo para que quede lo más completo posible.

Cualquier duda o pregunta, por favor no se corten y pregunten, ya sea en el blog, en el foro Google de FoxPro o por correo, que esto se trata de probar, equivocarse y aprender.


Hasta la próxima!


Relacionados:
Instalación de PlasticSCM paso a paso
FoxBin2Prg: Detalle de Vistas, datos de uso, configuraciones y más

No hay comentarios:

Publicar un comentario