martes, marzo 25, 2014

Nueva versión v1.19.18 de FoxBin2Prg (arreglos)

Por: Fernando D. Bozzo

Está liberada la versión v.1.19.18 de FoxBin2Prg con los siguientes cambios:

  • Arreglo bug scx/scx: Los controles imagen con imagenes estrechadas, se redimensionan a su tamaño original (Arturo Ramos). Si, por ejemplo, se usa un control imagen con una imagen de 32x32 pixels y se redimensiona a 16x16, al regenerar el binario se pierde la nueva dimensión y se restablece a la original. Regenerando el binario desde el vc2/sc2 existente se soluciona el problema.
  • Arreglo bug vcx/scx: Los comentarios a nivel de librería no se mantienen (Ryan Harris). Si se usan comentarios a nivel de librería (hasta donde sé, solo desde el Class Browser se pueden modificar), estos no se exportan al vc2/sc2 y por lo tanto tampoco al binario al regenerarlo. Ya se exportan estos comentarios

Como actualizar el FoxBin2Prg existente:
Con descargar el zip y reemplazar los archivos en el sitio que los hayan puesto antes es suficiente.


Link  de descarga:
https://vfpx.codeplex.com/releases/view/116407


 Saludos!

martes, marzo 18, 2014

PlasticSCM: ¿Qué es el Merge?

27/09/2014 - Actualizadas algunas partes de "Qué son los conflictos de un merge"
16/09/2014 - Actualizado con explicación de "Qué son los conflictos de un merge"
02/04/2014 - Actualizado con explicación de la opción "Proteger los cambios a otra rama..."

Por: Fernando D. Bozzo

El Merge es la operación que permite "mezclar" el código correspondiente a dos modificaciones simultáneas hechas en paralelo a un mismo programa.

Para quienes vienen de usar SourceSafe con FoxPro, esto es algo casi desconocido, porque con SourceSafe se usaba el scctext.prg que venía de serie y que sólo permitía hacer Diff. Algunos más aventurados puede que hayan intentado usar TwoFox para generar vistas XML de las clases e intentar hacer un merge manual, pero quienes lo hayan usado sabrán el cuidado que había que tener con no tocar ningún tag XML que nada tenía que ver con la programación y que dificultaba bastante entender lo que se estaba tocando.

La vida con SourceSafe era: o toco yo, o toca él, pero los dos no! La única excepción eran los PRG, que al ser texto sí que permitían más libertad, pero para todo lo demás, los checkout eran exclusivos, lo que significa que si un desarrollador bloqueaba una librería, nadie más podía modificarla hasta que ese desarrollador finalizara sus cambios, ¡y qué problemas se generaban si se enfermaba o se iba de vacaciones y la dejaba así! Claro que siempre se podía recurrir al truco de quitar el atributo de read only del archivo y modificarlo, pero subir los cambios al proyecto era imposible, y esto a muchos proyectos los bloqueaba literalmente, o como mínimo los retrasaba.


Volviendo al presente, las cosas cambiaron en FoxPro, y ahora con FoxBin2Prg un mismo programa, como clases, forms, menús, etc, puede ser modificado por varios desarrolladores de forma simultánea, cada uno en su equipo, y al momento de subir esas modificaciones al control de código se puede hacer el merge, en algunos casos de forma automática (para el primero en llegar: ¡siempre es automático!:) y en otros casos de forma manual.


[27/09/2014 - 16/09/2014 - Actualizado >>]

¿Qué son los conflictos de un Merge?


Cuando se hacen modificaciones sobre un mismo componente pero en distintas ramas, al tener que mezclar los cambios es probable que haya que resolver (seleccionar/mezclar) las diferencias entre 2 modificaciones realizadas al mismo form, clase, etc, de forma que tanto los cambios de una rama como de la otra queden incluidos.

Las ramas a mezclar pueden ser, por ejemplo, distintas características hechas por uno o más desarrolladores trabajando en paralelo, como una rama para cambiar el aspecto visual y otra rama para cambiar la funcionalidad de un botón de comando, lo que permite que al final se pueda seleccionar la característica o funcionalidad que se quiere incorporar individualmente y mezclarlas para obtener el resultado completo final.

Al trabajar en funcionalidades en ramas paralelas, es probable que se modifique algo en común, como una propiedad o un método, lo que provocará un conflicto al hacer el merge, que podrá ser automático o manual dependiendo de la calidad del algoritmo de la herramienta y de las características del código (si está bien estructurado, encapsulado y normalizado, será más fácil)

La idea de generar código estilo PRG con FoxBin2Prg, es justamente para que a la hora de hacer un merge sea casi tán fácil como hacerlo con un PRG de verdad, y dado que conocemos el lenguaje, ver el código de esta forma nos facilita la tarea lo más posible, ya que no hay que lidiar con códigos o símbolos extraños, sino sólo con el PRG y con los metadatos que se muestran como comentarios, donde suele ser muy poco lo que debe hacerse.

Obviamente, es necesario entender qué hace el código antes de realizar esta operación, y en eso ayuda bastante usar la nomenclatura de objetos y variables que dan una idea conceptual de para qué sirve cada cosa y qué tipo de dato maneja.
[<<]

Para los que les toque hacerlo de forma manual, los SCM traen herramientas para realizar la tarea, que suele mostrar las dos versiones del programa a unificar en dos paneles izquierdo-derecho. En la siguiente imagen se puede ver un ejemplo de WinMerge, un programa para Windows gratuito que permite ver diferencias entre archivos:



Este tipo de vista es muy útil cuando comparamos dos momentos de la historia del mismo archivo, como la versión de ayer y las modificaciones de hoy, pero no sirve cuando se quieren comparar 3 archivos, donde uno es la base, o sea, de donde partieron los otros dos archivos, el segundo es el mismo archivo base, pero modificado por un desarrollador y el tercero es el mismo archivo base, pero modificado por otro desarrollador.

En esta situación se requiere un visualizador de 3 vías, que muestre la base y los 2 cambios, y el programa que incorpora Plastic para esta tarea es increíble:


En la imagen puede verse en el panel izquierdo (Source, u Origen) los cambios que hizo Dev-2, que agregó Los métodos pagCalculos.Activate y cmdCalcular.Click (abajo se ve el nombre entero), pero resulta que mientras él estaba programando este cambio, Dev-1 terminó el suyo antes y lo mergeó primero (panel derecho, que es Destination o Destino) donde se ve que agregó en el mismo form el método pagDatos.Activate, seguramente con un merge automático en el que no tuvo que hacer nada.

En el panel central se ve el código original (Base) antes de que ambos hicieran sus cambios, que si bien en este caso no muestra cambios en sí mismo, cuando los muestra lo hace coloreado en amarillo.


En la cabecera de los tres paneles, los títulos coloreados Source, Base y Destination, además son selectores de cambios:



donde al clickearlos sus cambios se activan o desactivan en el panel inferior que muestra el resultado. En este caso están habilitados los cambios de ambos desarrolladores en el panel izquierdo de Dev-2 y en el derecho de Dev-1, por lo que aquí se muestra cómo quedaría la mezcla de los mismos:


Algo que también se puede ver, aunque no resulte evidente, es que esta mezcla se muestra bien y con lógica coherente porque la nomenclatura usada le permite a los algoritmos internos de la herramienta diferenciar ambos cambios y gracias a eso no es necesario modificar nada a mano.

Esto último lo comento porque puede darse el caso de que, incluso con una buena nomenclatura, dada la complejidad de los cambios puedan presentarse varias diferencias que puedan no ser coherentes para quien las esté mirando, y que requieran modificar o mover manualmente líneas o bloques de código para terminar de ajustar el merge, que también consiste en eso. Este panel inferior permite hacer dichas modificaciones manuales.

Por ejemplo, uno de los casos que puede requerir modificación manual, es cuando se trabaja con un pageframe y mientras otro desarrollador agrega una página y hace checkin, nosotros modificamos algo en la actual y hacemos checkin. Como nosotros teníamos una página de menos, podría ser necesario actualizar el PageCount manualmente.
Quice hacer esta prueba para hacerles una captura, pero resulta que Plastic me hizo este cambio de forma automática y me dejó sin nada que hacer ;-)

Igualmente hago la captura para que lo vean: La zona horizontal del medio es donde está el PageCount, el panel izquierdo tiene mis cambios, que en esta parte del código no tengo, en el medio está el origen del que partí y donde se vé que había 2 páginas, y el de la derecha es el destino, o sea, donde estoy intentando hacer el merge, y automáticamente desactivó los cambios 1 (Origen) y 2 (Base) y seleccionó el del panel 3 (Destino), además se puede observar en la parte superior izquierda el título:

"Tipo de conflicto: Automático. No es necesaria la intervención del usuario"... =D


También puede verse en la cabecera, que de los 10 cambios detectados, solo 1 no es automático!, o sea que los otros 9 los resolvió automáticamente por los algoritmos internos, y yo debo resolver el restante, que en este caso es este:


Observen que el selector de cambios (izquierda) y el selector de cambios no automáticos (derecha) tienen botones de navegación independientes, lo que permite navegar por todos los cambios o solo por los cambios no automáticos (1 en este caso). Revisar todos los cambios es buena idea, aunque sea para asegurarse de que la parte automática fue bien resuelta.

Solo para que vean como resolví este cambio manual, desactivé los cambios del lado izquierdo, ya que pueden verse que un poco más arriba (imagen de abajo), aunque en este caso daba igual, porque con el lado izquierdo activo ya los marcaba tachados antes, lo que significa que no se iban a incluir esas líneas, pero que igualmente requería nuestro visto bueno.

El caso anterior se podía resolver de dos formas:
  1. Desmarcando el Origen y dejando solamente la Base y el Destino (fue como lo hice)
  2. Eligiendo el botón superior que en la captura anterior decía "Marcar como resuelto", ya que las líneas tachadas iban a excluirse de todas formas
Nota: Es importante comprobar siempre todos los cambios, y si la activación o desactivación de los paneles superiores no ofrece el resultado esperado, siempre se puede recurrir al 4 panel (el inferior, de resultado) donde se puede modificar manualmente.


Así quedó la resolución del conflicto anterior, donde desmarqué el origen:


Finalmente, se guardan los cambios de este merge con el botón superior izquierdo, lo que cerrará esta ventana y puede que muestre otros merges para hacer.

Hay 3 cosas importantes que se deben conocer y recordar en esta etapa:

  1. Que si se necesita dejar esto para luego, se puede cerrar la ventana de merge "sin guardar cambios". Si hubiera muchos archivos por resolver, al cerrar la ventana se puede ver brevemente el botón "Cancelar" en la principal, al que hay que darle rápido antes de que aparezca una nueva ventana de merge. Parece un juego, pero es algo que deberían mejorar en la interfaz :D
  2. Que una vez guardados los cambios del merge, quedarán todavía los binarios de FoxPro, los cuales se deben seleccionar e ignorar, ya que luego deberán regenerarse en la siguiente ventana de Cambios Pendientes, ya que el merge en Plastic tiene 2 etapas: Procesar Merge, donde se resuelven los conflictos, y Regeneración de binarios y Checkin en la ventana de Cambios Pendientes.
  3. Que una vez se esté en la ventana de Cambios Pendientes, se debe recordar que por haber hecho un Merge con las versiones texto ¡los binarios que hay allí no sirven y hay que regenerarlos!

Comento un poco más estas opciones, ya que cuando hagan merge será vuestro día a día.

En el ejemplo anterior yo cancelé el merge porque solo quería mostrarles la pantalla, así que "cerré sin guardar cambios" (o sea, hice el paso 1)

El paso 2 implica seleccionar todos los binarios que se muestran en esta ventana de Merge y descartarlos, lo que significa dejar los que ya existen en el workspace (también llamado Destino), ya que han quedado desactualizados porque los cambios reales del Merge los hicimos en las versiones texto, como vemos en la siguiente imagen:


Nota: Si hubiera confirmado los cambios del merge, esta ventana no mostaría ahora las versiones de texto de los archivos, ya que hubieran pasado a la ventana de Cambios Pendientes.

El paso 3 ya se realiza en la ventana de Cambios Pendientes, pero a diferencia de lo que venimos haciendo cuando modificamos un binario en el IDE de FoxPro (generar texto y luego binario), en este caso solo debemos regenerar el binario, ya que es el texto el que estuvimos modificando. Si no lo hacemos así, perderemos todos los cambios del merge y nos estaremos quedando con los archivos binarios del workspace y en el peor caso también con las versiones texto mezcladas que ya no corresponderán a esos binarios!

Lo repito para remarcar: Luego de un Merge, mandan siempre las versiones texto, ya que es con lo que se ha trabajado en esta operación, por lo que sólo se deben regenerar los binarios usando el script de "Cambios Pendientes: Regenerar Binarios".

Y luego se hace el checkin para guardar todo.

Les dejo un video de ejemplo con explicación incluida:
http://youtu.be/ytMpWP69YMo


[02/04/2014 - Actualizado >>]
Respecto al checkin hay una opción que debemos conocer, y que es "Proteger los cambios a otra rama...", y la verdad es que es una opción muy útil que me ha tocado usar más de una vez.

Imaginemos que abrimos FoxPro en el workspace y comenzamos a trabajar, hacemos algunos cambios, algunas pruebas y vamos a Plastic para guardar los cambios, pero nos encontramos con que, sin quererlo, estábamos trabajando en la rama principal (esa en la que no se deben hacer cambios directamente, sino solo merge :-) y nos olvidamos de crear una rama nueva para trabajar. ¡Por Dios! ¿qué hacemos ahora? Fácil: usamos esta opción y creamos el changeset en una nueva rama, todo en un mismo paso:


Se nos pregunta el nombre de la rama y al confirmar nuestros cambios irán directamente a ella, dejando la rama principal como estaba.

En esta pantalla donde nombramos la nueva rama además tenemos otra opción interesante, que es un checkbox que nos permite pasar los cambios a la nueva rama, pero sin hacer checkin (por defecto hace checkin), lo que viene muy bien si solo queremos pasar nuestros cambios aún sin terminar a la nueva rama para hacer más tarde el checkin nosotros cuando realmente hayamos acabado los cambios:



[<<]


Como nota final, es interesante saber que este programa de merge se puede usar por separado, o sea, viene con Plastic y está un su directorio de instalación, pero se puede ejecutar por separado. Se llama "mergetool.exe" y tiene una opción dedicada en le menú de Windows, dentro del menú "Client Tools" de Plastic.

Nada más por hoy.

Hasta la próxima entrada! :D




lunes, marzo 17, 2014

PlasticSCM: ¿Qué es el Diff?

[03/04/2014 - Actualizado con la opción de Diff modificable si se hace checkout del archivo]

Por: Fernando D. Bozzo

El Diff es una operación para obtener las diferencias entre dos archivos, o entre dos versiones del mismo archivo, y se usa para poder ver de un vistazo qué ha cambiado.

En general todas las herramientas de control de código fuente incorporan alguna herramienta de Diff, e incluso existen herramientas externas que permiten comparar diferencias entre archivos o incluso entre directorios, como el WinMerge (gratuito) o el EditPlus (de pago).


En Plastic hay varias formas de invocar un Diff, se puede desde la vista de Cambios Pendientes, desde la de Items, desde la vista del Explorador de ramas, etc, y se pueden comparar dos momentos cualquiera de la historia de un archivo o de un changeset (conjunto de archivos y/o directorios), por lo que no solo se pueden ver los cambios hechos en un archivo, sino también los cambios hechos de un changeset a otro, donde por ejemplo, se puede ver si se agregó, modificó o eliminó un archivo o directorio.


En la siguiente imagen se puede ver una parte de la historia de FoxBin2Prg comprendida etre la versión v1.16 y la v1.17, donde se desarrolló el soporte para trabajar en modo Batch y además se solucionaron algunas incidencias reportadas del soporte de menús de la versión anterior.

Los dos changesets que tienen los círculos verdes (etiquetas de versión) corresponden a la rama principal, y los dos changesets de más abajo corresponden a la rama de desarrollo que comenzó en la v1.16


Si queremos ver las diferencias entre estos dos changesets, marcamos (click) el de la derecha, y luego marcamos (ctrl+click) el de la izquierda, veremos como se iluminan o aclaran al seleccionarlos.

Acto seguido hacemos click-derecho sobre cualquiera de los dos y elegimos "Mostrar diferencias entre changesets seleccionados", lo que enviará la información de estos dos changesets a la herramienta interna de Diff para que los compare. En la imagen de abajo se puede ver el Diff resultante (click en la imagen para ampliar):




En la parte superior de la imagen se puede ver la información del changeset: nombre de usuario (fernando), número de changeset (cs:128), fecha/hora y comentarios sobre el desarrollo y las modificaciones realizadas.



Bajo esa sección hay una barra con controles para navegar entre los archivos que se muestran en el panel de debajo, un botón de estadísticas y a la derecha de todo un filtro que permite ubicar rápidamente uno o varios archivos escribiendo parte del nombre.




Luego está el panel de archivos, donde se puede ver:   Cambiados: 5 elementos
con los 5 archivos modificados, y luego se ve:   Añadidos: 12 elementos
con los 12 archivos que fueron agregados, de los que solo se ve el primero



Bajo este panel hay una barra de controles para navegar por las diferencias, un contador de diferencias, un menú de Opciones donde se pueden configurar varios aspectos sobre cómo ver las diferencias, si se deben ignorar fines de línea y espacios en blanco, codificación de caracteres, etc, y una opción de búsqueda para ubicar algo rápidamente.



Finalmente está el panel de diferencias, donde en la parte superior de cada uno, a modo de cabecera, se muestra que changeset se está viendo, de qué rama y qué usuario lo creó. En este ejemplo se está comparando el changeset cs:125 contra el cs:128, y debajo está el código, donde el antiguo está del lado izquierdo y el más nuevo del derecho.



Entre ambos paneles de código hay una serie áreas grises que suelen mostrar los bloques de código coincidentes que se han modificado, agregado o quitado, y unas áreas violeta que muestran los bloques movidos de un sitio a otro (en este caso, en el menú de opciones superior tengo habilitada la detección de bloques movidos)

[03/04/2014 - Actualizado >>]
Hay una opción muy interesante en el Diff, que solo se habilita si de los archivos que comparamos, al del workspace le hacemos previamente checkout, y lo que se habilita permite seguir editando el archivo del workspace desde la ventana del merge, no solo como un editor de código manual, sino también permitiendo pasar bloques de modificaciones del panel izquierdo (versión histórica del archivo) al panel derecho (archivo del workspace) o incluso permitiendo desactivar grupos de cambios con una "x" que aparece en el bloque cuando corresponda. Los 3 tipos de edición se pueden apreciar en esta imagen:


Una vez realizados los cambios, se pueden confirmar con el botón "Save" o descartar con "Discard".
[<<]


Aprender a usar bien esta herramienta y conocer y probar sus opciones nos permitirá poder hacer las comparaciones de forma óptima, ahorrando un montón de tiempo.


Hasta la próxima!

domingo, marzo 16, 2014

Nueva versión v2.4.11 de las herramientas FoxPro 9 para PlasticSCM (contiene FoxBin2Prg v1.19.17)

Por: Fernando D. Bozzo

Está liberada la versión v2.4.11 de las herramientas Visual FoxPro 9 para PlasticSCM, con los siguientes cambios:

- Actualizada la versión de FoxBin2Prg a la versión v1.19.17


Estas herramientas son un grupo de scripts vbs y programas Visual FoxPro 9 que se configuran dentro de PlasticSCM para poder invocar a FoxBin2Prg (incluye solo el EXE) desde dentro de la interfaz de Plastic.

El README.txt explica como se configura en Inglés y Español.


Como actualizar las existentes:
Con descargarlas y reemplazar los archivos en el sitio que los hayan puesto antes es suficiente.


Link de descarga:
https://github.com/fdbozzo/foxpro_plastic_diff_merge


Saludos!

Nueva versión v1.19.17 de FoxBin2Prg (arreglos)

Por: Fernando D. Bozzo

Está liberada la versión v.1.19.17 de FoxBin2Prg con los siguientes cambios:

  • Arreglo bug frx/lbx: Las expresiones con comillas corrompen el fx2/lb2 (Ryan Harris). Si dentro de una campo, por ejemplo Comment, Tooltip u otro, contiene expresiones combinadas con cadenas entrecomilladas (ej: "este dato" + " este otro"), el archivo fx2/lb2 generado es inválido. Regenerando el fr2/lb2 se corrige
  • Arreglo bug frx/lbx: La propiedad Comment se pierde si es multilínea (Ryan Harris). En los reportes hay una parte de las propiedades del generador que permite escribir comentarios y tooltips multilínea. Normalmente no se usan, pero si se usan y además se escribe alguna línea con <CR>, el archivo fr2/lb2 generado es inválido. Regenerando el fr2/lb2 se corrige
  • Arreglo bug frx/lbx: Si la condición de impresión de un campo contiene una expresión con <CR>, se corrompe el archivo fr2 y luego el binario. Los reportes y etiquetas permiten indicar una condición para imprimir, o no, según devuelva True o False. Si de alguna forma se logra saltear la validación del editor de expresiones para poner un <CR>, el archivo fr2/lb2 generado es inválido. Regenerando el fr2/lb2 se corrige
  • Mejora de tag2 en frx/lbx para que muestre el valor real y no el codificado b64. El campo tag2 de los frx/lb2 puede contener información en texto limpio, como los tooltips, o información binaria y por eso siempre los codifiqué en base 64. Desde esta versión distingo si el campo se usa para tooltips o no, y si contiene texto plano no lo codifico para que se pueda leer en claro. Regenerando el fr2/lb2 se codificará como se indicó. Están afectados los archivos fr2/lb2 anteriores que usen tooltips y siguen codificados en b64
  • Arreglo bug mnx: Los comentarios multilínea en los Bars/Pads corrompen el MN2 y el MNX regenerado (Ryan Harris). Mismo problema que lo comentado para los frx/lbx, y aplicable solo si se han usado comentarios multilínea. Regenerando el mn2 se corrige
  • Arreglo bug mnx: Algunos procedimientos no se generan correctamente (Ryan Harris). Esto realmente tiene que ver con condiciones mal formadas o hacks raros en los archivos MNX, pero igualmente algunos valían la pena prevenirlos para evitar errores. Regenerando el mn2 se corrige
  • Correcciones al archivo de traducción al Inglés foxbin2prg_en.h (Ryan Harris). Agradezco a Ryan el haberme enviado el archivo de traducción al inglés con las correcciones de sintaxis.
  • Arreglo bug vcx/scx: Si la propiedad Dataenvironment se guarda en minúsculas, no se calcula el valor de Reserved2. Esto tiene que ver con una de las últimas mejoras de capitalización de nombres de clase y de objetos para evitar diferencias en las herramientas SCM, pero los vcx/scx parece que funcionan igual. Regenerando el vc2/sc2 se corrige
  • Adaptaciones en algunos tests unitarios FoxUnit para permitir diferencias de capitalización en algunos campos
  • Arreglo bug mnx: Usar comillas en el prompt de una opción genera un mn2 inválido (Ryan Harris). Esto tiene que ver con hacks raros en los nombres de las opciones. Regenerando el mn2 se corrige

Como actualizar el FoxBin2Prg existente:
Con descargar el zip y reemplazar los archivos en el sitio que los hayan puesto antes es suficiente.


Link  de descarga:
https://vfpx.codeplex.com/releases/view/116407


 Saludos!

PlasticSCM: Cómo trabajar en FoxPro 9 con ramas por tarea

Por: Fernando D. Bozzo

En esta ocasión vamos ver una forma de trabajar con ramas, que sirve tanto para uno como para varios desarrolladores. Si no sabes lo que es una rama, antes de seguir te convendría leer el artículo anterior sobre este tema: PlasticSCM: Cómo crear una rama para comenzar a trabajar


La norma básica a seguir es muy simple: Jamás hacer cambios en la rama principal!. Nunca!


(Bueno, las únicas excepciones son el primer add/checkin con un archivo README.txt, que recomiendo absolutamente, y la subida del proyecto FoxPro 9, que será el segundo add/checkin)

A partir de quí, lo único que se debe hacer en la rama Principal es el merge final de las demás ramas para etiquetar la versión. Todo el trabajo se debe hacer en ramas derivadas de la principal.

Antes de continuar un aviso: Para todo lo que sigue voy a asumir que la estructura de directorios de tu proyecto está encapsulada de forma que en la raíz está el proyecto (pjx) y el programa principal, y en los subdirectorios están los componentes, y que no se referencian componentes externos a esta estructura de directorios, por ejemplo apuntando a otra aplicación o ubicación de librerías como las FFC de FoxPro. Si esto no se cumple entonces no podrás obtener todas las ventajas de trabajar con control de código por las dependencias externas que tengas y tal vez de convendría leer antes: Crear un proyecto FoxPro: ¿por dónde comenzar?


Pasos a seguir para comenzar a trabajar con un proyecto nuevo


En este caso tenemos un proyecto FoxPro 9 que se crea desde cero y que desde el mismo inicio se pone bajo control de código.






Cómo agregar un proyecto existente al control de código para trabajar


Este es el caso típico para muchos desarrolladores que tienen proyectos hechos, y que ahora deciden meterlos en control de código para continuar trabajando de esta forma.
Los pasos para agregar un proyecto FoxPro existente al control de código está explicado en este artículo.
Para comenzar a trabajar con este proyecto FoxPro ya controlado, ver el siguiente punto.


Pasos a seguir para comenzar a trabajar con un proyecto existente


En este caso tenemos un proyecto FoxPro 9 que ya estaba bajo control de código fuente previamente, por lo que los nuevos desarrolladores solo deben unirse para tener lo último, crearse sus ramas y comenzar a trabajar en ellas, por lo que deben:
  • Crear el directorio en el disco donde se alojará el proyecto FoxPro 9 (ojo, el directorio vacío!)
  • Crear el repositorio Plastic para el proyecto
  • Crear el workspace asociado al directorio para poder actualizar el repositorio
  • Sincronizar el repositorio Plastic local con el repositorio remoto (esto se bajará el proyecto con archivos y directorios)
  • Crear una rama personal de desarrollo desde el último changeset de la rama Principal
  • Ya se puede comenzar a trabajar en la rama de desarrollo

Ejemplo de la rama de desarrollo v1.19.17 de FoxBin2Prg, que se creo a partir de la última versión v1.19.16 (círculo verde) de la rama Principal /main. Al finalizar se hará merge de la v1.19.17 de desarrollo en la rama principal nuevamente y se etiquetará la nueva versión como v1.19.17



Trabajo en ramas cuando se trabaja en solitario


Este caso es el que uso para trabajar en FoxBin2Prg, y es el modo de trabajo mínimo recomendado.

Se basa en tener:
  • La rama principal (/main) donde solo se hará merge y se etiquetarán las versiones
  • La rama secundaria para desarrollar
  • Alguna rama puntual para solucionar incidencias solamente

Pantallazo de un momento del historial de FoxBin2Prg
(click en la imagen para agrandarlo):


Como puede verse en la captura anterior, en la versión v1.15 de la rama principal hice una rama secundaria de desarrollo para trabajar en el soporte de los menús (MNX) que llamé "Soporte_MNX" (la tarea a realizar) y que luego se convertiría en la versión v1.16.

Mientras estaba trabajando en esta tarea descubrí un error en el soporte OLE de los forms y clases, lo que debía arreglar y promocionar cuanto antes, pero sin incluir nada del nuevo desarrollo. Y es en ese momento que abro una nueva rama desde la v1.15 para hacer el parche v1.15p1
Se puede ver gráficamente que con el arreglo hecho en ese parche (un solo changeset) luego hice un merge en la rama principal, que hizo la versión v1.15p1 pública y también hice un merge en la rama de desarrollo del Soporte_MNX, ya que de otra forma si no lo hiciera así, en la siguiente versión estaría incorporando nuevamente el error que había solucionado.

Al finalizar el trabajo en esta tarea, hice el merge final en la rama principal, que etiqueté como v1.16 pública e hice una nueva rama para comenzar a trabajar en el soporte para Proceso en modo Batch. En este punto Fidel Charny me reportó una incidencia sobre el posicionamiento del menú, pero esta vez en vez de crear una rama aparte para el parche, lo mezclé en la tarea actual, en el segundo changeset de "ProcesoEnModoBatch" y liberé todo junto al día siguiente como versión v1.17. Esto lo hice así porque tanto el desarrollo de la tarea como el parche los hice en un corto período de tiempo (1 día) y no valía la pena separarlos en versiones distintas.

Sobre la conveniencia de crear un parche y versionarla por separado solo con los arreglos o hacer los arreglos dentro de la rama de desarrollo para sacar todo junto en la siguiente versión, todo depende del tipo de desarrollo que se esté haciendo y de los tiempos que se manejen.

Para un programa como FoxBin2Prg, cualquiera de las dos formas de trabajo es válida porque es un conversor y no un aplicativo comercial, y en este caso el baremo que usé es de fechas: Si el desarrollo que estaba haciendo iba para largo y surgía algún reporte de bugs en medio, no podía dejar colgados a todos con el error hasta que termine el desarrolo actual, por lo que lo conveniente era sacar y versionar un parche por separado para luego poder seguir con el desarrollo actual. Pero si el desarrollo iba a ser rápido y surgía algún reporte de fallo, entonces sí hacía el arreglo en la rama de desarrollo actual y versionaba todo junto.

Como ahora el desarrollo de FoxBin2Prg esta terminado, está en etapa de mantenimiento, por lo que las ramas que se hacen son para corregir fallos e incorporar optimizaciones.


Trabajo en ramas cuando se trabaja en equipo


Cuando se trabaja en equipo, el desarrollo es similiar a trabajar en solitario, con la diferencia de que habrá una rama por cada desarrollador, y que en general los desarrolladores harán el merge en una rama de Integración, que en el ejemplo de la imagen de abajo es /main/TESTS, y en esa rama es donde irán integrando funcionalidades terminadas.

En esta rama de Integración no se deben subir cambios incompletos nunca, ya que esta rama debería ser lo bastante estable como para que el resto de desarrolladores puedan actualizar sus propias ramas desde la misma, con bastante seguridad en que no comenzarán a tener errores provocados por una subida inconclusa o errónea.

Convendría que se defina la figura del Integrador Principal, que sería la persona a cargo de hacer la revisión final del código que se integrará y los merge de las ramas de Integración en la rama principal una vez concluida la revisión. Esta figura es muy importante en el ciclo de desarrollo, ya que tiene la responsabilidad de integrar todos los desarrollos en la rama principal.

Durante esta revisión, el Integrador inspecciona las diferencias en el código de la rama de Integración (no en la rama de cada desarrollador!) usando la herramienta de Diff, para buscar posibles problemas o cosas mejorables y detectarlas antes de que se suban a la release definitiva en la rama Principal.


Pantallazo de un proyecto con su rama principal, su rama de Integración y dos desarrolladores Dev_1 y Dev_2:


Sobre esta forma de trabajar, ya había publicado un video.

Como puede verse en la imagen de arriba, cada desarrollador va trabajando en su rama y cuando tiene una funcionalidad terminada puede hacer una de dos opciones:

  • La integra con un merge en la rama de Integración, y acto seguido se actualiza su propia rama desde la de Integración para tener el trabajo de los demás. (Se puede ver que Dev_1 hizo esto en los dos primeros changesets)
  • O se baja primero lo de la rama de Integración en la rama propia con un merge y luego, con todo ya intgrado en su rama, hace otro merge en la rama de Integración desde la propia. (se puede ver que Dev_2 hizo esto en su segundo y tercer changeset)
Como recomendación personal, yo creo que la segunda forma de integrar es la mejor y más segura, ya que cada uno se está Integrando en la rama propia lo que hay en la rama de Integración, con lo cual si surgieran conflictos, se resolverían en la propia rama y no se afectaría a nadie si esto se hiciera mal. Además de que esto permite que una vez realizada esta actualización local se puedan probar los cambios integrados y corregir posibles errores antes de hacer el merge nuevamente en la rama de Integración, y así se tiene cierta seguridad sobre lo que se sube, ya que en el peor caso, si surgen errores en las pruebas locales (rama propia), nadie más estará afectado aunque se actualice desde la rama de Integración.

Si se hiciera al revés (merge a Integración y posterior merge a rama propia), se corre el riesgo de que se haga algo mal durante la Integración dejando esta rama inestable, y el problema es que, aunque se detecte en las pruebas posteriores, como esta rama es pública para el resto de desarrolladores, un error puede provocar que los demás que se actualicen se les propague a sus propias ramas antes de que se pueda corregir el error, lo que puede tomar un buen rato.



Trabajo en ramas con sistemas complejos y varios desarrolladores


Este escenario es similar al anterior, pero en este caso pueden haber varias ramas intermedias para distintas funcionalidades simultáneas, lo que crea un diagrama más complejo, y en el que la figura del Integrador Principal es imprescindible, ya que es quien debe conocer qué desarrollos deben integrarse en la versión actual o cuáles son para la próxima versión.

La siguiente imagen es una simulación de lo que puede ser un sistema complejo, formado por dos proyectos cortos, cada uno con dos desarrolladores, en los que se harán dos funcionalidades distintas que confluirán en la rama de Integración y de ahí a la rama principal en la versión etiquetada como v2.0, y de un proyecto a medio plazo, también con dos desarrolladores, que se va actualizando con la release principal, pero que todavía debe continuar desarrollando y por eso no hace merge en la principal.

(Click en la imagen para agrandar)


Cuando ese proyecto de mediano plazo se deba integrar, se deberá crear primero una nueva rama de Integración que salga de la última release disponible (por ej: de la v4.0), y deberá integrar sus cambios allí para poder realizar pruebas y certificar el funcionamiento, antes de que se integre en la rama Principal.



Recomendaciones finales


Como se ve, dependiendo del tipo de proyecto a realizar, el trabajo en ramas ayuda mucho si se usa adecuadamente. Dejo algunas recomendaciones para tener en cuenta, que están basadas en las buenas prácticas y en la experiencia de varios proyectos durante bastante tiempo:

  • En los componentes usar rutas relativas, nunca rutas absolutas. Esto permitirá que el proyecto sea portable e independiente de la ruta que se use para trabajar
  • Para un proyecto compartido conviene predefinir y usar el mismo directorio entre desarrolladores para evitar diferencias en el pjx, que si no a cada desarrollador le detectará un directorio distinto, el cuál aceptará y esto generará una nueva diferencia innecesaria
  • Hacer uso extensivo de las buenas prácticas de programación (encapsulación, refactorización, etc).
  • Como mínimo se debería respetar una nomenclatura de objetos, como la sugerida por la ayuda de FoxPro. Esto no solo permite que el código se auto-documente, sino que facilita los merge manuales y maximiza los automáticos que no requieren intervención
  • Usar FoxPro desde el directorio raiz del proyecto (workspace) y no cambiar la sesión a otros directorios (set default to <dir> o cd <dir>) ya que esto puede provocar problemas y bloqueos en el SCM cuando se quiera hacer un checkin o cambiar a otro changeset
  • Cerrar siempre los forms, proyectos, clases y programas abiertos, y hacer CLEAR ALL antes de ir al SCM a realizar alguna tarea.
  • Un bloqueo en algún archivo controlado por el SCM puede provocar un error en el checkin o que impida poder regenerar las versiones texto o binario con FoxBin2Prg y que en consecuencia se suban archivos des-sincronizados entre sí, como un binario sin su tx2 o viceversa

Hasta la próxima!


PlasticSCM: Agregando un proyecto FoxPro 9 al control de código fuente

Por: Fernando D. Bozzo

Es muy probable que tengamos proyectos que no están bajo control de código con un SCM, tanto porque sean antiguos proyectos, como porque consideramos que no ameritaban estar controlados o simplemente porque recién se está comenzando en este mundo del control de código.

Por el motivo que sea, tenemos uno o varios proyectos que queremos controlar con el SCM, así que vamos a ver un ejemplo de los pasos y configuraciones desde cero para hacerlo, asumiendo que que ya tenemos Plastic instalado y configurado.

Para el ejemplo voy a usar el proyecto FoxUnit, que es uno de los proyectos Open Source de VFPX en CodePlex para hacer Unit Testing (testing automatizado de código) que suelo usar frecuentemente, y que lo tengo en el directorio c:\desa\FoxUnit:



Como se puede observar en la captura anterior, hay archivos temporales, restos de pruebas y los archivos nos están normalizados (capitalizados), por lo tanto el primer paso es hacer esa normalización, usando click-derecho en el nombre del directorio de FoxUnit, y eligiendo la opción "Enviar a" y luego "Normalize_FileNames.vbs", que es uno de los scripts incluidos en las herramientas FoxPro 9 para Plastic.




Una vez ejecutado, los archivos quedan así:


Ahora que tenemos los archivos normalizados, vamos a crear un repositorio llamado FoxUnit, con un workspace llamado igual, ya que tanto el directorio como el proyecto ya se llaman así. La creación del repositorio y workspace ya los expliqué en el artículo de Instalación de Plastic, la única diferencia es que si Plastic ya está instalado y se quiere crear un nuevo repositorio y workspace (en ese orden), se deben seleccionar las opciones del pabel izquierdo, dentro de "Repositorios & Workspaces"




Hay dos archivos de configuración para Plastic que se deben crear en todos los proyectos que se quieran controlar, y que son "filetypes.conf" e "ignore.conf"


El archivo de configuración filetypes.conf


El archivo "filetypes.conf" sirve para indicarle a Plastic el tipo (texto/binario) de ciertos archivos que por no ser estándares pueden ser reconocidos incorrectamente. Por ejemplo, todas las extensiones texto de FoxBin2Prg, el config.fpw de FoxPro y algunas otras, por defecto se suelen reconocer como binarios. El tipo de archivo se puede ver en las vistas de Items y Cambios Pendientes, en la columna "tipo".

Para FoxPro, el filetypes.conf suele tener este contenido:

# PlasticSCM custom file types.
# Syntax: <extension>:<type>
# Type can be 'txt' or 'bin'.
# Examples:
#     .cpp:txt
#     .jpg:bin
.cfg_:txt
.cfg:txt

.fpw:txt
.prg:txt
.pj2:txt
.vc2:txt
.sc2:txt
.fr2:txt
.lb2:txt
.db2:txt
.dc2:txt
.mn2:txt


Este archivo puede estar a nivel de repositorio o a nivel del sistema. Si está a nivel de repositorio, se debe poner en la raíz del workspace, y si es a nivel del sistema, suele estar en el directorio <PerfilDelUsuario>\Configuración local\Plastic5
Si se pone a nivel del repositorio (lo recomendable), también es útil ponerlo dentro del control de código, para que los desarrolladores que se unan al proyecto tengan automáticamente la misma configuración y así no deben volver a hacerla cada vez.


El archivo de configuración ignore.conf


El archivo "ignore.conf" le indica a Plastic qué archivos no queremos ver en las vistas de Items y Cambios Pendientes. Es un filtro visual, y al igual que el filetypes.conf, puede estar a nivel de repositorio o de sistema, y en las mismas ubicaciones ya comentadas.


Para FoxPro, el ignore.conf suele tener este contenido:

*.FXP
*.LNK
!/_iniciar aqui.lnk
*.SCC
*.TMP
*.BAK
*.ZIP
*.7Z
*/FXUResults.*
*/FXUPersist*.*
.plastic
.git


Es importante conocer su sintaxis, ya que permite hacer cosas muy útiles como ocultar ciertas extensiones pero mostrarlas en un directorio particular. La sintaxis permite indicar:
  • Una extensión (ej: .fxp)
  • Un archivo (ej: foxuser.dbf)
  • Un archivo en una ruta específica relativa a la raíz del workspace (ej: /forms/unarchivo.xml)
  • Un directorio (ej: .git)
  • Una negación de las reglas generales que se aplicarán a un archivo en una ruta específica (ej: !/_Iniciar aqui.lnk)

Importante: Notar que las barras de directorio no son las de Windows (\), sino el símbolo dividido (/)

Este archivo también se puede actualizar desde la GUI de Plastic, en la vista de Items y de Cambios Pendientes, haciendo click-derecho sobre un archivo y eligiendo "Añadir a la lista de cambios ocultos" donde se mostrarán 3 opciones:
  • archivo.ext
  • .ext
  • /ruta_absoluta/archivo.ext

Agregar el proyecto FoxPro a control de código


Al fin, ya tenemos todo preparado, configurado y normalizado para agregar el proyecto, por lo que regeneramos las vistas de texto, regeneramos los binarios, agregamos el README.txt y posteriormente agregamos todos los archivos relevantes, es decir, todos menos los archivos temporales o archivos de pruebas que no formen parte del proyecto:



Generación de los archivos de texto (tx2):



Agregado del README.txt:


Checkin del README.txt con un comentario:



El Explorador de ramas muestra el segundo changeset (el primero siempre es vacío):




Agregado el control de código de los archivos del proyecto y los tx2 generados:



Comentario de checkin y checkin final:



El Explorador de ramas muestra el tercer changeset (al anterior es el README.txt y el primero siempre es vacío):


Y ya está. A partir de aquí es crear ramas para comenzar a trabajar en ellas.


Hasta la próxima! =)