31 de mayo de 2006

Días comerciales entre dos fechas calendario

Esta función se llama menosd30 y la hice para calcular los días comerciales entre dos fechas.

Funciona de la siguiente manera:
? menosd30(DATE(2006,1,1), DATE(2006,12,31))
El código es el siguiente.
FUNCTION menosd30()
  PARAMETER _fi,_ff
  SET CENTURY ON
  SET DATE TO DMY
  fi=_fi
  ff=_ff
  mi=MONTH(fi)
  mf=MONTH(ff)
  di=DAY(fi)
  df=DAY(ff)
  yi=YEAR(fi)
  yf=YEAR(ff)
  xm=mf-mi
  IF di > 30 AND df > 30
    di = 30
  ENDIF
  IF df > 30
    df = 30
  ELSE
    IF MONTH(ff + 1) > MONTH(ff)
      df = 30
    ENDIF
  ENDIF
  xd=df-di+1
  xy=yf-yi
  xf=xm*30+xd+(xy*360)
  RETURN xf
ENDFUN
Nelson Cortés

30 de mayo de 2006

Fecha comercial basada en días

La función lo que hace es tomar una fecha y con base a ella calcula los días comerciales.

Esta función la llamo masd30 y funciona de la siguiente forma:
? masd30(DATE(2006,03,01),60)
El código es el siguiente :
FUNCTION masd30()
  PARAMETER _DIA,_dias
  SET CENTURY ON
  SET DATE TO DMY
  dia=_DIA
  dias=_dias
  v=30-DAY(dia)+1
  v2=dias-v
  v3=v2/30
  IF v2 = 0
    v4=30
  ELSE
    v4=MOD(v2,30)
  ENDIF
  v3=CEILING (v3)
  vf=GOMONTH(dia,v3)
  vf1=ALLTRIM(STR(v4))+"/"+PADL(ALLTRIM(STR(MONTH(vf))),2,"0")+"/"+ALLTRIM(STR(YEAR(vf)))
  vf2=CTOD(vf1)
  IF EMPTY(vf2)
    vf2="01/"+PADL(ALLTRIM(STR(MONTH(vf)+1)),2,"0")+"/"+ALLTRIM(STR(YEAR(vf)))
    vf2 = CTOD(vf2)
    vf2 = vf2 - 1
  ENDIF
  RETURN vf2
ENDFUN
Nelson Cortés

28 de mayo de 2006

Obtener una referencia a un formulario padre

Artículo original: Getting a reference to a parent form
http://weblogs.foxite.com/andykramek/archive/2005/09/04/899.aspx
Autor: Andy Kramek
Traducido por: Ana María Bisbé York

Ocurre a veces que hay dos formularios que dependen en alguna medida uno de otro. Lo más frecuente es que un formulario sea llamado desde otro requiera pasarle múltiples valores o selección de criterios, que son definidos en su "padre". Hay varias posibles soluciones para estos casos; pero veamos una solución muy sencilla, que no es muy conocida, a pesar de que existe en VFP desde la versión 3.0.

Siempre que comienza VFP, ya sea en tiempo de desarrollo o desde sus librerías en tiempo de ejecución, se crea un objeto llamado _Screen, (basado en una clase form - intente escribir ?_Screen.Class desde la ventana de comandos) Vea que no importa si VFP está visible o no. El objeto se crea de todas formas y es un componente fundamental utilizado por el propio VFP.

Una de las propiedades más importantes de _Screen es "ActiveForm". Como implica su nombre, esta propiedad guarda una referencia al formulario activo actualmente y puede ser utilizada cuando escribimos código genérico que necesite acceder a cualquier formulario que esté activo.

Por ejemplo, suponga que tiene un procedimiento que puede ser llamado desde varios formularios diferentes. En ocasiones necesita pasar solamente uno o dos parámetros. Sin embargo, si el procedimiento necesita acceder a propiedades o métodos del formulario llamado, debe entonces darle la referencia al formulario, algo como esto:
DO myproc WITH ThisForm
Y en el procedimiento necesita un parámetro que se corresponda
FUNCTION myProc( toForm)
Esto no es un problema una vez que el procedimiento es llamado desde un formulario como tal (o un objeto que es miembro del formulario). Sin embargo, hay veces cuando un procedimiento necesita acceder a cualquier formulario que esté activo en ese momento, independientemente de si es o no el que ha sido llamado por el procedimiento. Por ejemplo, cuando existen múltiples instancias de un formulario, o debido a que el procedimiento como tal cambia el formulario activo. Este es un escenario donde _Screen.ActiveForm se utiliza debido a que no se tiene que preocupar sobre la instancia del formulario que es llamado y solamente hace referencia al formulario activo:
IF TYPE( "_Screen.ActiveForm" ) = "O"
  *** OK, tenemos realmente un formulario activo
  loForm = _Screen.ActiveForm
ELSE
  *** Ooops! ¿No debía existir un formulario activo?
ENDIF
Ahora puede que se pregunte de porqué he escrito esto. La respuesta es sencilla, si aquí no hubiera formulario activo y trata de acceder a la propiedad, VFP muestra el error 1924 ("ACTIVEFORM no es un objeto"). Esto no es deseable, por tanto es muy importante verificar que existe realmente un formulario antes de tratar de establecer una referencia al mismo. A propósito, vea que esta es también una de las ocasiones cuando no podemos emplear VARTYPE() porque si no hay formulario activo, tratando de acceder a un propiedad también devuelve el error 1924. En este caso TYPE() devolverá "U".

Todo esto es muy interesante; pero escucho que usted dice, ¿Cómo esto ayuda a tomar una referencia al formulario padre? La clave es reconociendo el momento en el cual _ScreenActiveForm se actualiza cuando se instancia un formulario.

La respuesta es que cuando un formulario llama a otro, el valor de _ScreenActiveForm no cambia hasta que el formulario nuevo se ha cargado por completo, sus métodos LOAD(), INIT() y SHOW(). Esto se demuestra al escribir el nombre del formulario activo (Screen.ActiveForm.Name) fuera de un archivo de texto al llamar a un formulario desde otro - he aquí el resultado:
In Parent Form, Active Form is currently [FrmParent]
*** Call child form here ***
STARTING Child Form LOAD, Active Form is currently [FrmParent]
STARTING Child Form INIT, Active Form is currently [FrmParent]
STARTING Child Form SHOW, Active Form is currently [FrmParent]
STARTING Child Form ACTIVATE, Active Form is currently [FrmChild]
*** Release Child Form here ***
STARTING Child Form DESTROY, Active Form is currently [FrmChild]
STARTING Child Form UNLOAD, Active Form is currently [FrmChild]
STARTING Parent Form ACTIVATE, Active Form is currently [FrmParent]
Si pensamos en esto, vemos que tiene sentido. Después de todo, si Load() o Init() devuelven False el formulario hijo no se va a instanciar debido a que _Screen.ActiveForm no ha cambiado al inicio del proceso, sino hasta que Show() no se realice. Una vez que Show() se ejecuta VFP puede estar seguro de que el formulario nuevo no se va a terminar de forma no normal y que el valor de _Screen.ActiveForm podrá ser guardado satisfactoriamente.

De forma análoga, una vez que se realice el Unload() del formulario hijo, el formulario será destruido definitivamente de tal forma el formulario anterior (si existe) se activa y la propiedad se modifica adecuadamente.

Entonces, ¿que es lo que significa esto para nosotros? Bueno, una cosa es que este formulario es llamado por otro formulario, no necesitamos pasar nada para obtener la referencia a su padre. Más importante, puede ser, debido a este comportamiento, que podamos realmente acceder a las propiedades, métodos y eventos del formulario padre desde el Load() del formulario hijo, el que ocurre antes de que sea instanciado cualquier control.

Esto es importante, porque si existen criterios para los controles del formulario hijo que dependen de un valor del formulario padre (típicamente cuando los valores dependen de alguna selección que se haya hecho en el formulario padre) es mucho mejor que controlarlo antes de que el control sea instanciado. Al pasar una referencia como parámetro no permite esto porque el parámetro se recibe en el Init() del formulario, el que sólo se produce después que todos los controles han sido instanciados.

La conclusión de todo esto es, que para proporcionar una referencia a un formulario padre podemos utilizar código genérico, en el evento Load() de una clase formulario. Todo esto es necesario para agregar una propiedad de usuario a un formulario (llámela 'oParentForm') y luego, agregue el siguiente código en el evento Load():
IF TYPE( "_Screen.ActiveForm" ) = "O"
  This.oParentForm = _Screen.ActiveForm
ELSE
  This.oParentForm = NULL
ENDIF 
Cualquier método u objeto, en el formulario, puede tener ahora una referencia al formulario padre verificando simplemente que la propiedad "oParentForm" no esté vacía. Lo otro que hay que hacer (y no es requerido en realidad, pero que yo considero es una buena práctica) es limpiar la referencia en el evento Destroy() - ¡ y esto es una línea !
ThisForm.oParentForm = NULL

Muy buena la idea de Andy. He realizado un ejemplo para probar y funciona muy bien.

Lo veo muy útil para quienes siempre necesitan saber de que formulario fue llamado otro.

Aquí el código de prueba:
PUBLIC ARRAY goForm(1)
goForm(1) = CREATEOBJECT("MiForm")
goForm(1).SHOW
RETURN

DEFINE CLASS MiForm AS FORM
  oParentForm = NULL

  ADD OBJECT cmdParent AS COMMANDBUTTON WITH ;
    HEIGHT=30, TOP=10, LEFT=10, ;
    NAME="cmdParent", CAPTION="¿Padre?"
  ADD OBJECT cmdDoForm AS COMMANDBUTTON WITH ;
    HEIGHT=30, TOP=50, LEFT=10, ;
    NAME="cmdDoForm", CAPTION="Do Form..."

  PROCEDURE LOAD
    IF TYPE( "_Screen.ActiveForm" ) = "O"
      THIS.oParentForm = _SCREEN.ACTIVEFORM
    ELSE
      THIS.oParentForm = NULL
    ENDIF
  ENDPROC

  PROCEDURE INIT
    THIS.CAPTION = SYS(2015)
    IF NOT ISNULL(THISFORM.oParentForm)
      THIS.TOP = THISFORM.oParentForm.TOP + 20
      THIS.LEFT = THISFORM.oParentForm.LEFT + 20
    ENDIF
  ENDPROC

  PROCEDURE DESTROY
    THIS.oParentForm = NULL
  ENDPROC

  PROCEDURE cmdParent.CLICK
    MESSAGEBOX(IIF(ISNULL(THISFORM.oParentForm), ;
      "Formulario sin padre", ;
      "Hijo de " + THISFORM.oParentForm.CAPTION))
  ENDPROC

  PROCEDURE cmdDoForm.CLICK
    LOCAL ln
    ln = ALEN(goForm) + 1
    DIMENSION goForm(ln)
    goForm(ln) = CREATEOBJECT("MiForm")
    goForm(ln).SHOW
  ENDPROC

ENDDEFINE

Luis María Guayán

26 de mayo de 2006

FoxPro Tips: Examinador de Objetos

Artículo original: FoxPro Tips: Toolbox
http://rickschummer.com/blog/2006/03/foxpro-tips-object-browser.html
Autor: Rick Schummer
Traducido por: Ana María Bisbé York


El examinador de Objetos es una herramienta nueva en VFP 7. Expone las interfaces públicas y privadas de bibliotecas de objetos COM y controles ActiveX. Dentro de estas bibliotecas existe una valiosa información, disponible para desarrolladores, concerniente a propiedades, métodos y eventos, valores constantes y clases. Esta herramienta es muy importante para desarrolladores que escriben código de Automatización y necesitan entender las formas documentadas de emplear un objeto Automation concreto.

Determinar los valores de constantes definidos en un objeto COM

Una de las tareas realmente duras al desarrollar código de automatización es determinar las constantes utilizadas en los ejemplos. Estas constantes se pueden traducir a código #DEFINE. Antes de tener el Examinador de Objetos Visual FoxPro era necesario buscar por los archivos de Ayuda, con la esperanza de ejemplos con los valores documentados, o emplear una herramienta como el examinador de objetos encontrado en editores VBA de Microsoft Office para encontrar estos valores. Esto, sin dudas, representa un gasto de tiempo. Las herramientas como West Wind GetConstants.EXE leen estas bibliotecas y generan el código #DEFINE, el que es fácilmente compilado por Visual FoxPro.

El Examinador de objetos puede generar el código #DEFINE eficientemente y es un ahorro real de tiempo. Para lograrlo, abra un componente COM o ActiveX, despliegue el árbol TreeView para exponer el nodo Constants. Abra un editor (de programa o de procedimiento). Arrastre la rama Constant y suéltela en el editor. No solamente se escribe el código #DEFINE con la constante y el valor; sino que además, si la constante tiene descripción, se incluye la documentación para la constante, como un comentario de #DEFINE. Si arrastra la rama Constant tendrá todas las constantes en el editor. Puede además, arrastrar constantes individuales si solamente necesita algunas.

Problema: He tenido experiencias de constantes que son valores decimales redondeadas a cero (con MapPoint). Si este es el caso, recomiendo GetConstants.EXE de West Wind, que no tiene este problema.

Utilizar el Examinador de objetos para crear plantillas de clases para implementar interfaces.

Una característica poderosa en Visual FoxPro es la capacidad de escribir código en sus propias aplicaciones respondiendo a eventos de otras aplicaciones. Por ejemplo, puede escribir código para responder al usuario cerrando una hoja de cálculo o enviando un correo en Outlook o combinando correspondencia en Word. Esto se hace con la cláusula IMPLEMENTS de DEFINE CLASS así como con la función EventHandler().

El Examinador de Objetos nos ayuda a escribir el tedioso código relativo a este aspecto. Primero, abra el control ActiveX o COM en el Examinador de Objetos. Luego, despliegue el TreeView y localice el nodo Interface. Abra un editor (de programa o de procedimiento). Arrastre el nodo Interface y suéltela en el editor. La definición de clase se escribe, incluyendo el código IMPLEMENTS y la plantilla para cada uno de los métodos expuestos. Todo lo que tiene que hacer en este momento, es renombrar la clase desde MyClass a algo más descriptivo, y agregar código al método adecuado.

Localizar el nombre del archivo OCX para incluirlo en la configuración de salida de mi aplicación
El Examinador de objeto ayuda a los desarrolladores Visual FoxPro en muchos aspectos relacionados con controles ActiveX. Uno de los más sencillos, y más útiles es mostrar el nombre real para el OCX y otros detalles sobre el control.

Abra el Examinado de Objetos y seleccione un control ActiveX de la lista. Si selecciona el nodo raíz para el control existen detalles sobre el OCX mostrados en el panel inferior del Examinador de Objetos. Información del tipo nombre del archivo, archivo Ayuda, y el GUID es mostrado al desarrollador. Esto puede ser bueno cuando necesita encontrar el archivo OCX para ser incluido en el paquete y determinar donde el archivo Ayuda esté instalado en el disco duro.

24 de mayo de 2006

FoxPro Tips: EditorOptions de VFP

Artículo original: FoxPro Tips: VFP's EditorOptions
http://rickschummer.com/blog/2006/03/foxpro-tips-vfps-editoroptions.html
Autor: Rick Schummer
Traducido por: Ana María Bisbé York

Si es autor de cualquier artículo o documento con ejemplos escritos en Visual FoxPro comprenderá rápidamente la necesidad de suprimir el formato enriquecido incluido en VFP 9 al copiar al portapapeles. Al inicio, me gustó mucho esta posibilidad para mis documentos técnicos; pero al trabajar para una conferencia, plantillas de sesiones, plantillas de revistas y plantillas de publicaciones para Hentzenwerke Publishing me sentí frustrado porque rompe con los estilos de varios editores. En VFP 9 beta esta característica era parte del producto y no configurable; pero las voces de los beta testers se escucharon alto y claro. Queremos una forma de eliminar esto.

He ayudado a muchos desarrolladores a desconectar esta característica, y hoy mientras trabajaba en mi sesión sobre control de errores para GLGDW 2006, me di cuenta que lo había conectado nuevamente (es bueno, cuando comparto código en correos o en publicaciones en foros) y lo necesito desconectar mientras trabajo en mis presentaciones. Tengo un programa para realizar esta configuración. Este es el código:
* Interruptor para el formato enriquecido al portapapeles
IF 'X' $ _vfp.EditorOptions
  * Desactiva esta configuración
  _vfp.EditorOptions = STRTRAN(_vfp.EditorOptions,"X", SPACE(0))
ELSE
  * Activa esta configuración
  _vfp.EditorOptions = _vfp.EditorOptions + 'X'
ENDIF
Esto lo puede colocar en un elemento del menú del desarrollador, o barra de herramientas, o solamente ejecútelo desde la ventana de Comandos.

Bonus Tip

Al revisar el código recordé otro tip para compartir. IntelliSense tiene una característica llamada C++ Operator Expansion. Yo la utilizo todo el tiempo. Si tiene una variable como lcErrorString y desea concatenar algún texto a la cadena existente debe entrar lo siguiente en el editor de programa:
lcErrorString+=
Luego, oprima la barra espaciadora y verá:
lcErrorString = lcErrorString +  
Está listo para escribir el resto de la lógica para realizar la concatenación. Existen varios operadores C++ que trabajan con IntelliSense en VFP
lnCounter++
lnCounter--
lnCounter+=
lnCounter-=
lnCounter*=
lnCounter/=
La razón que me inspiró a escribir este bonus tip es la situación donde tengo object.Property y deseo concatenar o incrementar, como _vfp.EditorOptions. Si tiene este código en el editor de programa:
_vfp.EditorOptions+=
Y oprime la barra espaciadora, no ocurre nada. Reporté esto como un bug en una de las betas. La solución es sencilla; pero tiene que recordarlo al escribir el código. Incluya un espacio entre el nombre de la propiedad y el operador, luego oprima la barra espaciadora después del operador.
_vfp.EditorOptions +=
¡ Disfruten del fin de semana !

Nota de la traductora:

Como comentario a este post, el MVP Andy Kramek señaló que, aunque para aplicaciones VFP el espacio ES necesario; no es siempre así para propiedades de objetos, al probar el siguiente código, veremos que no hace falta.
LOCAL loX as CUSTOM
loX.Height+=
Rick Schummer agradece la corrección. En cualquier caso, la sugerencia de dejar el espacio en blanco entre propiedades de objetos y el operador funciona bien.

Gracias a ambos !!

22 de mayo de 2006

FoxPro Tips: Caja de herramientas

Artículo original: FoxPro Tips: Toolbox
http://rickschummer.com/blog/2006/03/foxpro-tips-toolbox.html
Autor: Rick Schummer
Traducido por: Ana María Bisbé York


La caja de herramientas (Toolbox) es una poderosa herramienta incorporada a VFP 8 y mejorada en VFP 9, por el simple hecho de que puede ser anclada. Muchos desarrolladores se refieren al Toolbox como la barra de herramientas de control de formularios en esteroides (lo que puede no ser políticamente correcto). Me gusta la Caja de herramientas por varias razones, pero lo que más me gusta, es trabajar con controles ActiveX.

Puede arrastrar un control ActiveX desde la Toolbox y soltarla en el Diseñador de clases o formularios. Es cómodo por sí mismo; pero no creo que ahí es donde esté su poder real. Me gusta arrastrar un control ActiveX a un programa o ventana de procedimiento. Al arrastrar un control ActiveX al editor da el código NEWOBJECT() necesario.

El siguiente código fue creado al soltar el activeX DynaZip Zip en el editor:
Olecontrol = NEWOBJECT("dzactxctrl.dzactxctrl.1", "dzactx.dll")
Ahora no tiene que estar mirando el registro de información para el control en el Registro de Windows o la documentación distribuida con el control. Puede cambiar la línea de código:
LOCAL loZip AS "dzactxctrl.dzactxctrl.1"
Ahora, en cuanto escriba loZip. en el editor tendrá IntelliSense para el control ActiveX. Esto trabaja bien y realmente incrementa la productividad cuando trabaja en código de Automatización con un control de este tipo.

17 de mayo de 2006

Escribir mejor código (Parte 3)

Artículo original: Writing better code (Part 3)
http://weblogs.foxite.com/andykramek/archive/2006/03/20/1308.aspx
Autor: Andy Kramek
Traducido por: Ana María Bisbé York

En el tercer artículo de esta serie voy a hablar sobre Procedimientos y Funciones. Visual FoxPro, como sus ancestros FoxPro y FoxBase admite dos tipos diferentes de declaración y llamada de código.

Crear un procedimiento

Un procedimiento es sencillamente un bloque de código que es llamado por un nombre. Puede; pero no se requiere, que acepte uno o más parámetros y la razón para la creación de un procedimiento, es evitar la necesidad de escribir el mismo código muchas veces. Los procedimientos son llamados empleando el comando DO, y, de forma predeterminada, todos los parámetros se pasan por referencia. Por tanto no existe la necesidad de tener valores de retorno en los procedimientos - pueden modificar cualquier valor y el código llamado que lo pasa.

He aquí un ejemplo sencillo del tipo de código que podría estar en un procedimiento. Todo lo que hace es aceptar un número de registro y Alias de tabla. Valida que el número de registro es válido en el contexto de una tabla específica y, si es así, mueve el puntero de registro. Si falla algo, o si no es válido, se genera un error:
********************************************************************
*** Nombre.....: GOSAFE
*** Autor...: Andy Kramek & Marcia Akins
*** Fecha.....: 03/20/2006
*** Aviso...: Copyright (c) 2006 Tightline Computers, Inc
*** Compilador.: Visual FoxPro 09.00.0000.3504 for Windows 
*** Función.: Si el registro especificado es válido para el alias 
*** ........: especificado va hasta el, de lo contrario genera un error
********************************************************************
PROCEDURE gosafe
  PARAMETERS tnRecNum, tcAlias
  TRY
    *********************************
    *** Comprobación de los parámetros
    *********************************
    *** Debemos recibir un número de registro!
    IF VARTYPE( tnRecNum ) # "N" OR EMPTY( tnRecNum )
      ERROR "Debe pasar un número de registro a GoSafe" 
    ENDIF
    *** Si no se ha especificado un alias, asume el alias actual
    lcAlias = IIF( VARTYPE( tcAlias ) # "C" OR EMPTY( tcAlias ), ;
      LOWER( ALIAS()), LOWER( ALLTRIM( tcAlias )) )
    IF EMPTY( lcAlias ) OR NOT USED( lcAlias )
      *** No hay tabla!
      ERROR "Debe especificar, o seleccionar una tabla " + ;
        "abierta al llamar a GoSafe"
    ENDIF
    *********************************
    *** Verifica que el número de registro es válido para el alias
    *********************************
    IF BETWEEN( tnRecNum, 1, RECCOUNT( lcAlias ) )
      *** Este está bien
      GOTO (tnRecNum) IN (lcAlias)
    ELSE
      *** No, el número de registro no es bueno
      ERROR "El registro " + TRANSFORM( tnRecNum ) + ;
        " no es válido para la tabla " + lcAlias
    ENDIF 
  CATCH TO loErr
    MESSAGEBOX( loErr.Message, 16, "GoSafe ha fallado" )
  ENDTRY
  RETURN
ENDPROC
Para llamar al procedimiento utilizamos
SET PROCEDURE TO procfile ADDITIVE
*** Guarda el puntero de registro en Account
lcOldAlias = ‘account’
lnOldRec = RECNO( lcOldAlias )
<<más código aquí>>
*** Restaura el puntero de registro
DO GoSafe WITH lnOldRec, lcOldAlias
Este procedimiento en particular no modifica nada y de hecho (como todos los métodos, funciones y procedimientos de VFP) en realidad devuelve .T. No hay necesidad, o incluso posibilidad de capturar ese valor. Vea que si desea pasar valores a un procedimiento por valor, en lugar de por referencia, entonces tenemos que pasarlos como valores reales y no como variables (Si, podríamos incluso cambiar la configuración de UDFPARMS pero no está recomendado, porque tiene otros efectos colaterales no deseados. Además, utilizar una solución global para un tema local es generalmente una mala idea). Entonces, para pasar un registro de número, "por valor" a este procedimiento podríamos utilizar:
DO GoSafe WITH INT( lnOldRec ), lcOldAlias

Crear una función

El otro método para llamar a código es crear una función. La diferencia básica entre un procedimiento y una función es que la función SIEMPRE devuelve un valor y por tanto siempre que llame a una función, ya sea una función nativa o una propia, siempre debe verificar los resultados. Las funciones se llaman finalizándolas con dos paréntesis. Como los procedimientos, las funciones pueden aceptar uno o más parámetros; pero a diferencia de los procedimientos, los parámetros pasados a las funciones son, de forma predeterminada, pasados por valor. La consecuencia es que esta funciones no modifican los valores en el código que los llama. (Si, esto es un comportamiento exactamente opuesto al comportamientos de los procedimientos). Veamos una sencilla función que devuelve el tiempo como una cadena de caracteres después de unos segundos.
********************************************************************
*** Nombre.....: GETTIMEINWORDS
*** Autor...: Andy Kramek & Marcia Akins
*** Fecha.....: 03/20/2006
*** Aviso...: Copyright (c) 2006 Tightline Computers, Inc
*** Compilador.: Visual FoxPro 09.00.0000.3504 for Windows 
*** Función.: Devolver la cantidad de Días/Horas y minutos a 
*** ........: partir de una cantidad en segundos
*** Valor devuelto.: Cadena de caracteres
********************************************************************
FUNCTION GetTimeInWords( tnElapsedSeconds, tlIncludeSeconds )
  LOCAL lcRetval, lnDays, lnHrs, lnMins
  *** Inicializa las variables
  STORE '' TO lcRetval
  STORE 0 TO lnDays, lnHrs, lnMins*** Handle the Days first
  lnDays = INT( tnElapsedSeconds / 86400 )
  IF lnDays > 0
    lcRetVal = PADL( lnDays, 3 ) + ' Days '
  ENDIF
  *** Calcula las horas
  lnHrs = INT(( tnElapsedSeconds % 86400 ) / 3600 )
  IF lnHrs > 0
    lcRetVal = lcRetVal + PADL( lnHrs, 2, '0' ) + ' Hrs '
  ENDIF
  *** Ahora los minutos
  lnMins = INT(( tnElapsedSeconds % 3600 ) / 60 )
  *** Verifica los segundos
  IF tlIncludeSeconds
    *** Si deseamos los segundos, los agrega explícitamente
    lcRetVal = lcRetVal + PADL( lnMins, 2, '0') + ' Min ' 
    lcRetVal = lcRetVal + PADL( INT( tnElapsedSeconds % 60 ), 2, '0' )+' Sec '
  ELSE
    *** Redondea por exceso los minutos UP Si >= 30 segundos
    lnMins = lnMins + IIF( INT( tnElapsedSeconds % 60 ) >= 30, 1, 0 )
    lcRetVal = lcRetVal + PADL( lnMins, 2, '0') + ' Min ' 
  ENDIF
  RETURN lcRetVal
ENDPROC

Escribir mejor código (Parte 2)

Artículo original: Writing better code (Part 2)
http://weblogs.foxite.com/andykramek/archive/2006/03/13/1283.aspx
Autor: Andy Kramek
Traducido por: Ana María Bisbé York

Como dije en mi primer artículo de esta pequeña serie, una de las grandes cosas sobre Visual FoxPro es que normalmente hay varias formas diferentes de hacer lo mismo. Desafortunadamente, es al mismo tiempo, una de sus peores cosas, al menos, si hubiera sólo una vía de hacer algo, no habría que pensar mucho sobre cómo hacerlo. Algo que he notado cuando trabajo sobre un código (mío o de otro) es lo fácil que caemos los desarrolladores en las plantillas de hacer algo. Una vez que averiguamos la forma de solucionar un tipo de operación especial, tendemos a seguirlo inquestionablemente.

He tenido ocasión, recientemente, de revisar algunos de los comandos más básicos de Visual FoxPro y examinar críticamente su rendimiento. He encontrado algunos resultados sorprendentes y como espero que usted también lo encuentre, he documentado los resultados de mi investigación.

¿Cómo se ejecutaron las pruebas?

Existen varios problemas al intentar de estimar el rendimiento relativo de comandos y funciones Visual FoxPro. La solución que he adoptado fue fijar mis pruebas como funciones individuales, y entonces utilizar un generador de número aleatorio para determinar qué método es llamado. Al ejecutar pruebas individuales muchas miles de veces, en secuencias aleatorias, los efectos de atrapar y pre-compilar son canceladas efectivamente. Utilicé la misma metodología para todas las pruebas y no me molestaré en volver a mencionarlo.

Por ejemplo, el código empleado por Macro Expansion Test #5 (InDirect EVAL() para Object Value) fue:
loObj = CREATEOBJECT( 'textbox' )
loObj.Value = "Esta es una prueba para  valor de cadena"
lcObj = "loObj"
lnSt = SECONDS()
FOR lnReps = 1 TO 10000
  luVal = EVALUATE( lcObj + '.Value' )
NEXT
lnEn = SECONDS()
(Nota: 10,000 iteraciones fue suficiente para una medición razonable - el resultado fue entonces, promediado para cada prueba). Los resultados de cada prueba se escribieron en una tabla y luego los agregué y los promedié para obtener los resultados ilustrados en este artículo.

Expresiones de nombre vs Macro sustitución

Una de las grandes fortalezas de Visual FoxPro es la capacidad de utilizar vía indirecta (indirection) en tiempo de ejecución. Ahora, todo desarrollador VFP  experiementado sabe que utilizando una expresión de nombre (por ejemplo, la función EVALUATE()) es "más rápida" que la macro sustitución (operador &) para hacer esto. Pero la cuestión es, eso importa realmente? Me parece que hay varios escenarios en los que podemos querer utilizar la vía indirecta al trabajar con datos:
  • Utilizar una referencia para obtener un valor: por ejemplo, Devolver el contenido de un campo utilizando solo su nombre
  • Utilizar una referencia para dirigirse a un objeto, por ejemplo, obtener el valor de una propiedad
  • Utilizar una referencia para encontrar algún elemento específico de un dato: por ejemplo, en un comando LOCATE
La siguiente tabla muestra los resultados de ejecutar la misma operación en tres formas diferentes. Primero, utilizando la macro sustitución tradicional de VFP, luego, utilizando la función EVALUATE indirectamente (por ejemplo EVAL(lcFieldName)) y finalmente utilizando una evaluación indirecta (por ejemplo, EVAL( FIELD( nn )).

Rendimiento relativo de macro expansión y expresiones de nombres

Nombre de la pruebaTotal de EjecucionesTiempo totalPromedio (ms)
Macro sustitución para valor de tabla10700014.82300.1385
EVAL() indirecto para valor de tabla14200011.66800.0822
EVAL directo para valor de tabla960006.49200.0676
Macro sustitución para valor de objeto109000013.78400.0126
EVAL() indirecto para valor de objeto10400008.79000.0085
EVAL directo para valor de objeto11300009.19300.0081

Macro sustitución en LOCATE
1010000
8.1700
0.0081
EVAL() indirecto en LOCATE
1140000
9.1250
0.0080
EVAL() directo en LOCATE
1140000
9.1980
0.0081

Lo primero que observo es que no hay un método intrínsicamente lento al considerar cada procedimiento por separado (lo peor en este escenario muestra una diferencia de no más de 0.05 milisegundos entre la mejor y la peor tecnología - ¡difícilmente detectable!). Sin embargo, al ejecutar repetidamente (dentro de un lazo apretado, por ejemplo), está claro que EVAL() tiene un rendimiento significativamente superior al  tratar con cualquier tabla de datos u objetos y por tanto, el decir que EVAL() es más rápido que &expansión está obviamente bien fundamentado.

Es muy interesante, que existe una diferencia detectable entre utilizar una evaluación directa e indirecta y mi preferencia personal, aunque solo sea  para mejorar la legibilidad del código, es por tanto, utilizar el método indirecto. En otras palabras, aceptaré (la pequeña) mejora de rendimiento para escribir código de esta forma:
lcField = FIELD( lnCnt )
luVal = EVALUATE( lcField )
en preferencia de la menos obvia:
luVal = EVALUATE( FIELD( lnCnt ))
La conclusión principal es, por tanto, que no existe beneficio en utilizar macro sustitución cuando está disponible EVAL() como opción. Un punto secundario para notar que es como el número de repeticiones aumenta la diferencia rápidamente se torna significativa y que EVAL() debe siempre ser utilizado al procesar repetidamente.

Escribir mejor código (Parte 1)

Artículo original: Writing better code (Part 1)
http://weblogs.foxite.com/andykramek/archive/2006/03/07/1260.aspx
Autor: Andy Kramek
Traducido por: Ana María Bisbé York

Como todos sabemos, Visual FoxPro brinda un entorno extremadamente rico y variado; pero a veces demasiadas cosas buenas nos llevan a adoptar malos hábitos. Al escribir código existen varias vías de alcanzar el mismo resultado; pero todo frecuentemente existen diferencias significativas en rendimiento y la única vía para asegurar que nuestro código está optimizado para el mejor rendimiento es comprobar, comprobar y volver a comprobar la mayor cantidad de condiciones diferentes que se puedan idear. Habiendo dicho esto, es igualmente importante reconocer que el primer requerimiento de cualquier código es ser funcionalmente correcto. Al decir de Marcia Akins (Microsoft MVP, autora y co-propietaria de Tightline Computers Inc) "... hacer algo mal lo antes posible no es realmente muy útil".

Pero, frecuentemente también, tendemos a lograr la funcionalidad correcta sólo al final de la historia, y una vez que algo está funcionando, simplemente nos movemos al siguiente problema. La realidad es que la mayoría de los desarrolladores típicamente revisan y optimizan su código al mismo tiempo que regresan a el para agregar comentarios (es decir, ¡nunca!).

Sin embargo, al aplicar algunas reglas y técnicas básicas, puede asegurarse de evitar algunos de los problemas más comunes y producir código más eficiente desde la primera vez. A medida de que lo haga con más frecuencia, será  menor el tiempo que necesite emplear en revisar y "tunear" código funcional. Esto tiene dos beneficios para todo desarrollador:

Mientras menos retoques que se haga sobre el código, una vez que está funcionando correctamente, será menor la probabilidad de introducir fallos en código funcional.

Arreglarlo inmediatamente ahorra tiempo, no tener que revisar el código, es siempre más rápido que re-hacer para mejor rendimiento o usabilidad.

El propósito de esta serie de artículos es revisar algunas de estas cosas que hacemos, cuando estamos escribiendo código para asegurar que es nuestro software es tan eficiente y tan usable como sea posible y minimizar la necesidad de revisar código que trabaja bien para optimizarlo. Comenzaremos con algo básico y luego, más adelante en esta serie, tendremos algo más avanzado.

Advierta a sus usuarios; pero no los trate como idiotas

Alguien (lo siento; pero no recuerdo quien) una vez remarcó el deseo de los usuarios finales, no desean ser mostrados como tontos delante de sus jefes al dar respuestas erróneas, y no les deben tratar como idiotas. Desafortunadamente nosotros, como desarrolladores, tendemos en concentrarnos mucho en lo primero, que nos olvidamos de lo segundo. Una de las cosas más básicas que podemos hacer en nuestras aplicaciones es intentar y crear un balance adecuado entre las advertencias relevantes y las "molestas".

Una de las cosas que más me molestan vienen del propio VFP. ¿Ha observado que cuando estamos ejecutando paso a paso desde el depurador y seleccionamos "Reparar" inmediatamente un diálogo nos pregunta "¿Cancelar programa?"? Entiendo que aquí la intención es advertirme en caso, digamos, que haya oprimido inadvertidamente la lista desplegable y seleccionado "Reparar" cuando realmente deseaba otra opción (¿realmente soy tan tonto?) Pero en este diálogo la opción "predeterminada" es "SI", la cual, por una parte no es realmente consistente con la razón de mostrar el diálogo en primer lugar (quiero decir, protección "infalible"). Aún, puede argumentar que tiene sentido porque probablemente haya querido reparar el código cuando oprimí "Reparar".

Sin embargo, si el código en cuestión es una definición de clases, al seleccionar "Reparar" no es suficiente porque tan pronto como trate de modificar en la ventana abierta recibir otro diálogo - y esta vez pregunta:

"¿Quitar la clase de la memoria?"

A ver, un momento, le hemos dicho a VFP que:
  1. Queremos reparar el código que se está ejecutando
  2. Si, realmente queremos cancelar la ejecución del programa
¿y ahora nos pregunta si queremos quitar la clase de memoria? ¿Cómo se supone que la arreglemos si NO lo hacemos? Para hacer las cosas aun peores, ¡la opción seleccionada de forma predeterminada es "Ignore"!

Entonces, si ha tratado de insertar una línea nueva presionando la tecla Intro como el primer paso de su modificación (y ¿Cuán frecuentemente no es lo primero que hacemos?) - este diálogo idiota relampaguea en su pantalla, y se va, seleccionando "ignorar" y no pasa nada. Ahora vea, después de todo, yo soy un desarrollador y seguramente si intento modificar una definición de clase ¿realmente DESEO hacerlo? ¿Que hace a VFP pensar que asume que yo no se lo que estoy haciendo? ¡Esto es realmente muy molesto, por no decir insultante!

Ahora considere ¿Con cuánta frecuencia tiene ese tipo de diálogos en sus aplicaciones? La pregunta clásica es "¿Está seguro?". He aquí un ejemplo, el usuario abre la ventana de búsqueda, encuentra algún valor y trata de encontrar un registro. Entonces tiene que seleccionar, desde las opciones del desarrollador, "Eliminar". Un diálogo diciendo: "Esto va a eliminar el registro, está seguro?" con "NO" como opción predeterminada (Es su turno de protección" infalible", amigos ...) ¿Cuán insultante es esto? Por supuesto, ellos desean eliminar el registro, gastan justamente 20 minutos buscando el registro, y ahora le pregunta si está seguro de que eso era lo que quería hacer?

Por supuesto, oigo que está diciendo, siempre existe la posibilidad de que oprima Eliminar accidentalmente. ¿Pero quién es el culpable? La respuesta, ¡DEL DESARROLLADOR! El desarrollador es el único que  hace posible que oprima "eliminar" por accidente, nadie más. Si la funcionalidad eliminar es tan sensitiva, entonces la interfaz de usuario está mal hecha que permite la casualidad. (usted pregunta "¿Está seguro?" cuando el usuario desea Agregar un registro, o Guardar cambios ...?).

¿Por qué no habilita el botón "eliminar" una posible acción de tal forma que el usuario tiene que hacer algo para iniciar el proceso y no entonces tener que lidiar con "Esto va a eliminar un registro" seguido por "¿Está seguro?", seguido por "Está realmente, realmente seguro" y así hasta el infinito. Al final de este día, el desarrollador, tiene que o ejecutar el comando eliminar o cancelar la operación - mejor que advertir, y darle la opción de cancelar, antes ellos han gastado su tiempo en el proceso.

Informe a sus usuarios; pero no comprometa el rendimiento para hacerlo.


11 de mayo de 2006

Visual FoxPro Best Practices for the Next Ten Years

Documentación completa de la conferencia "2006 Great Lakes Great Database Workshop".

El taller consistió en un track de 14 sesiones secuenciales de la noche del viernes al mediodía del lunes, cubriendo prácticamente cada aspecto importante de las mejores prácticas de desarrollo en VFP.



Titulo: Visual FoxPro Best Practices for the Next Ten Years (GLGDW 2006 Conference Proceedings)
Autores: Varios
ISBN: 1-930919-70-0
Páginas: 415
Formato: Unicamente PDF (7,2 MB)
Precio: U$S 75.00
Fecha publicación: Mayo de 2006
Código fuente: Disponible para descarga, incluye diapositivas de cada sesión y material adicional.

Tabla de contenido:
  • Session 1: Development Environment Setup
  • Session 2: Error Handling and Reporting
  • Session 3: Class Design
  • Session 4: User Interfaces
  • Session 5: Local Data Access
  • Session 6: Remote Data Access
  • Session 7: Refactoring
  • Session 8: Project Management
  • Session 9: Reporting and Output
  • Session 10: Debugging
  • Session 11: Vertical Market Applications
  • Session 12: Designing Middle Tier Components
  • Session 13: Deployment

Para mas información y compra: href="http://www.hentzenwerke.com/catalog/vfpbp10.htm

5 de mayo de 2006

Como hacer a Visual FoxPro bonito

Artículo original: "How to make Visual FoxPro cool"
http://craigbailey.blogspot.com/2006/05/vfp-how-to-make-visual-foxpro-cool.htmlComo hacer a
Autor: Craig Bailey
Traducido por: Luis María Guayán

Como hacer a Visual FoxPro bonito (*)

(*) Nota del traductor: He elegido "bonito" como traducción de "cool" ya que ésta palabra tiene varias traducciones según la zona geográfica.

Por si usted no lo hubiera notado, Visual FoxPro (VFP) no es muy bonito. En este artículo mi objetivo es cubrir 3 áreas:
  1. ¿Por qué VFP no es bonito?
  2. ¿Por qué esto importa?
  3. ¿Cómo podemos hacer a VFP bonito?
1. ¿Por qué VFP no es bonito?

De acuerdo, entonces la primera cosa en la que tenemos que convenir consiste en que VFP no es bonito. He estado charlando últimamente con algunas personas del ambiente .Net (incluso Adam Cogan y Paul Stovell) acerca de sus opiniones sobre VFP. Me he concentrado en desarrolladores que nunca han usado VFP, porque ellos pueden brindar las opiniones más útiles (a diferencia de los desarrolladores VFP/.Net que son bastante mas conscientes de lo que VFP puede hacer).

Seguidamente tenemos que reconocer que hay una ignorancia general en la comunidad .Net de lo que VFP puede hacer. Por ejemplo, ellos están verdaderamente sorprendidos de saber como VFP puede "hablar" con un SQL Server tan fácilmente. La contestación a esto no es mi orden del día, sin embargo, hubo muchas discusiones en la falta de comercialización para VFP y no tengo ningún interés en repetirlos aquí. Sin embargo volveré, separando el mensaje, más adelante en este artículo.

Mejor dicho, voy a concentrarme en áreas no técnicas. Aquí están algunos motivos por qué la gente piensa que VFP no es bonito:

Razón 1: Está "sobre la cima"

La primera cosa que VFP tiene en contra, es el hecho que ha existido por mucho tiempo. Usted piensa que esto es bueno ¿verdad?. Estable. Optimizado. Gran comunidad. NO!. Los nuevos desarrolladores de la actualidad, están más interesados en trabajar con la última tecnología. Y VFP no es nuevo.

Piense en COBOL. Cuando la gente se ríe de alguien que es programador de COBOL, no porque ellos recuerden un lenguaje deficiente, sino, principalmente ellos piensan que el lenguaje es anticuado, es decir, debe ser un poco en broma todavía usarlo.

Y lamentablemente, Visual FoxPro avanza lentamente a ese mismo lugar. Esto es a pesar de que Microsoft trabaja actualmente en la siguiente actualización de VFP y ha confirmado el soporte de este hasta 2014. ¡Pero es tan viejo! Sí, debe ser bien aprovechado a lo largo de esa fecha ... mas o menos como dice la teoría. Este en desacuerdo todo lo que quiera, pero es un hecho. Pregunte a un novel estudiante universitario lo que el piensa de VFP, y él lo mirará sin expresión. Pregunte a un desarrollador más viejo (no un desarrollador VFP) su opinión, y él preguntará si todavía existe. Infórmele de VFP y observe su reacción, -Debe estar en el depósito de chatarra seguramente ... y hacia allí va. Todos nos hemos topado con este pensamiento en el mundo que nos rodea.

Y puedo referirme a mi mismo con esto. Amo todas las cosas nuevas, así que entiendo totalmente de donde esto proviene.

Ahora, en este punto usted puede preguntar si los nuevos desarrolladores son realmente tan "superficiales". Quiero decir que seguramente ellos tendrían algún interés en comparar las herramientas y elegir la mejor para trabajar con ella. NO!. Calculo que las capacidades actuales de las herramientas comprenden aproximadamente el 5 % del proceso de decisión.

¿No me creen? Entonces considere esto: ¿Por qué hay más desarrolladores que ingresan a C# que a VB.Net? C# es bonito, es por eso. Ambos lenguajes tienen mas o menos la misma funcionalidad, y aún C# es percibido como el lenguaje que los auténticos desarrolladores avispados eligen. Sí, y VB es para la gente que encuentra C# demasiado dificultoso ... Hay, desde luego, algunos importantes (y elocuentes) defensores de VB, pero el hecho de que ellos tienen que explicar por qué VB es como el bueno, es parte de la demostración que es la hermana fea. (A propósito, creo que probablemente este último párrafo conseguirá la mayor reacción por parte de los lectores, y de ser así, entonces es porque ha perdido mi punto principal).

Punto principal => Lo bonito no es sobre la capacidad técnica, es sobre la percepción. La percepción es todo.

Razón 2: No hace Código Administrado (Managed Code)

La segunda cosa contra VFP, consiste en que esto no es parte del paquete .Net. El código de VFP no es código administrado. Y aquí está la parte interesante, pregunte a un nuevo desarrollador .Net por qué el código administrado es mejor. Usted conseguirá algunos balbuceos sobre la mejor administración de memoria, unos cuantos mencionarán garbage collection (información basura), pero en términos generales, los desarrolladores no podrán decirle que es lo bueno acerca del código administrado. Es solo mejor, Ok.

Así que, porque VFP no es código administrado, entonces, este debe ser anticuado. Por supuesto, todos ellos usan Word, Outlook, Skype, Windows Media Player y una multitud de otras aplicaciones que no son escritas en código administrado, pero este es inútil. El caso es que si usted escribe código administrado, entonces la percepción es que usted escribe el mejor código. El código administrado es bonito, VFP no lo es.

Y no me considere equivocado, no ridiculizo esta manera de pensar, realmente pienso que esto tiene un gran mérito. Mi punto es enumerar simplemente las razones de la percepción que VFP tiene.

Razón 3: La experiencia de Usuario del Desarrollador

El tercer golpe contra VFP es la apariencia y comportamiento. Ejecute VFP y usted se enfrentará con los viejos menús de Windows 2000. Ningún simpático menú Whidby (Nota del traductor: nombre de código de Visual Studio 2005), ni siquiera menús estilo Outlook 2003. Abra algunos diálogos, todos los iconos son antiguos. Nada es 3D (excepto algunos iconos del nuevo diálogo de informes); y la barra de estado es de los años 90. Esto no tiene ni un interfaz tabulada (alguien realmente tiene que hacer algo respecto de esto :-)) Por supuesto que esto no importa un bledo a la calidad de las aplicaciones que esto produce, pero en estos días, la experiencia del usuario es lo mas importante.

Razón 4: Tiene la palabra "Fox" en él

Aunque realmente la palabra Fox se haya beneficiado un poco del navegador FireFox, en general, las palabras Fox y FoxPro son en gran parte antiguas. VFP realmente necesita algún cambio de nombre para superar esto. Para muchas personas hay un estigma grande ligado a la palabra FoxPro. Ellos no pueden desvincularlo de las asquerosas aplicaciones FoxPro para DOS que ellos usaron en la compañía hace 10 años (mi atención ha girado aquí a desarrolladores más viejos). Pero los desarrolladores aún más recientes recuerdan el FoxPro que vino con el Visual Studio 6. Ellos lo vieron allí, pero realmente sólo pueden recordar el aburrido icono de 16 colores que este tenía. Otra vez, la percepción es que es viejo e irrelevante.

Y no subestime la necesidad de cambiar el nombre. Tome por ejemplo Microsoft FrontPage. El estigma atado a FrontPage desde versiones previas (donde este solía corromper su HTML) era tan malo, que Microsoft sabía que tenían que renombrarlo. Y entonces lo que en principio iba a ser FrontPage 2007, ahora se ha convertido en Microsoft Expression Web Designer Edition (compruebe el demo aquí y verá lo que quiero decir). Mismo producto, percepción diferente.

2. ¿Por qué esto importa?

¡Y qué! Si VFP no es bonito, todavía hace lo que los desarrolladores VFP necesitemos ¿Correcto?
Incorrecto. El problema más grande que enfrenta VFP hacia el futuro, es la carencia de desarrolladores. Lo mas probable es que el banco de programadores VFP disminuya. Asumo que la mayor parte de las personas estarán de acuerdo con esta afirmación.

El desafío para un negocio que desarrolla en VFP no es la tecnología, es la gente. Si usted quiere aumentar su negocio y tomar a nuevos desarrolladores, usted tiene que tener una buena fuente de ellos para seleccionar. ¿Entonces, por qué hay menos desarrolladores VFP?

Esto es porque todos los nuevos estudiantes universitarios estudian .Net o Java. Hay excepciones, por supuesto, pero esta es la tendencia general (y sospecho que esto pasa en India y Asia también, no sólo en países Occidentales).

¿Y por qué los estudiantes universitarios no aprenden o se interesan al menos acerca de VFP? Deje de lado las exageradas promociones y enorme empuje de la comercialización de Microsoft durante un minuto y todo se vuelve al factor de bonito. Si pudiéramos hacer a VFP bonito, conseguiríamos a más interesados.

3. ¿Cómo hacer a Visual FoxPro bonito?

De este manera, ¿qué podemos hacer para hacer a VFP bonito? Aquí están algunas ideas (algunas podemos hacer, otras están fuera del alcance de nuestras manos):

Cambio de nombre (Requiere Microsoft)

Es tiempo para perder la palabra "Fox".

Microsoft no ha indicado como será llamada la siguiente actualización/versión. Por el momento esto es simplemente llamado con el nombre de código Sedna. Sin embargo, yo he comenzado a referirme a ello como Microsoft VF.Net.

VF es la abreviatura para Visual FoxPro, y el .Net se refiere a la integración fuerte que este tiene con el .Net Framework 2.0. No, este no escribe código de .Net, sino que utiliza .Net Framework. Este es un lenguaje .Net despabilado.

También he cambiado el icono en la esquina superior izquierda del IDE de VFP. De esta manera cuando la gente me ve usar VFP, ellos ven el título como Microsoft VF.Net y un icono agradable. También puede deshabilitar la pantalla de presentación usando un archivo de configuración, tanto que, a menos que usted mire la Ayuda -> Acerca de ... no hay ningún "zorro" a la vista.

También uso FoxTabs, aunque esto esté todavía en beta y tenga algunas cuestiones conocidas, y necesite un cambio de nombre :-) que mejora la experiencia de diseño.

Modernizar la interfaz (Requiere Microsoft)

La interfaz necesita una revisión. Actualizar los menús para parecer a Visual Studio 2005, embellecer la pantalla de presentación y los diálogos. Advierta, no necesitamos un cambio de la funcionalidad, sólo de aspecto y sensación del producto.

Promover la integración .Net

En demostraciones a un auditorio variado (es decir no limitado a desarrolladores Fox) trataré de mencionar los nuevos ejemplos de Sedna (y caramba espero que haya nuevo CTP que pronto llegará ...). Los desarrolladores no comprenden que tan fácil pueden usar VFP con .Net (tanto usando Sedna como usando controles .Net, por ejemplo, consulten los sitios de Craig Boyd y de Rick Strahl)

Promueva los datos vinculados (data binding)

Las cosas que trae LINQ para .Net son grandiosas. Sin embargo, muestre a la gente cuanto más ellos pueden hacer con VFP, y díganles que ellos deberían hacer campaña contra el Equipo .Net para que les provean lo mismo. Los desarrolladores de .Net deberían gritar sobre lo mal que ellos han sido tratados en las apuestas de datos vinculados. Dígales que ellos pueden usar VFP como un ejemplo de como es posible hacerlo.

Promueva a VFP como una herramienta de ayuda

VFP es una gran herramienta para usar junto a Visual Studio. No trato de convencer a desarrolladores .Net de cambiar a VFP, pero hay muchas ventajas que ellos podrían sacar teniendo a VFP como una herramienta de ayuda, incluyendo:
  • ¿Necesita escribir algunas pruebas SQL Server rápidas? Use VFP con datos de prueba del sistema. Además use VFP para hacer llamadas a procedimientos almacenados y comprobar los datos devueltos.
  • ¿Necesita sacar algunos datos en una hoja de cálculo? Use VFP.
  • ¿Necesita programar algunas actualizaciones? VFP es extraordinario como una herramienta de programación, similar al lenguaje de programación VB.
  • ¿Necesita comprobar si un objeto de COM está instalado? Pruebe una rápida llamada CREATEOBJECT en VFP.
Promueva a VFP como una herramienta de prototipos

VFP es una gran herramienta para desarrolladores .Net, para construir prototipos. Tome un formulario, tire algunos controles, enlace a algunos datos de ejemplo, entregue la aplicación al cliente en un pequeño instalador, etc.

Difunda el mensaje

Esto no es una nueva petición. Craig Boyd (e incluso yo mismo) ha solicitado de la acción de la comunidad VFP a que ayude a hacer conocer a otras comunidades de desarrolladores un poco de las grandes cosas que VFP tiene, (por la sencilla razón que ellos pueden hacer presión sobre Microsoft para apresurar y conseguirlo en .Net :-)

Sin embargo, el mensaje se trata de la difusión de algunos conceptos equivocados sobre VFP. Aquí están algunas cosas que tenemos que promover:
  • VFP trabaja estupendo con .Net
  • Sedna realmente se enfoca en la interoperabilidad .Net
  • VFP es un conector impresionante para SQL Server
  • VFP tiene llamadas SQL en línea
  • VFP está bien soportado y sigue mejorando
Conclusiones

Después de leer mi artículo, yo comprendería si pensó que era anti .Net. En realidad, es lo contrario, por ejemplo me ocupo de un equipo de 15 desarrolladores; más de la mitad son desarrolladores de .Net. Hacemos muchos desarrollos ASP.Net, SQL Server y BizTalk. Pero también hacemos mucho desarrollo en Visual FoxPro Visual. Mi preocupación es acerca de la percepción que VFP tiene, y afrontar en el largo plazo la obtención de más desarrolladores VFP. De ahí mi interés en mejorar la percepción que VFP tiene.

Sus opiniones

Si usted es un desarrollador .Net y dispone de un minuto para enviarme sus opiniones de lo que piensa de VFP, y lo que tomaría de esto para convencerlo de que VFP es bonito, estaría encantado de tener noticias suyas. Puede enviarme un correo electrónico a: cb@talman.com.au o dejar un comentario en este artículo.

Agradecimientos

Paul Stovell y Adam Cogan me han dado montones de ideas, con muchas de las cuales he concluido este artículo. Sin embargo, cualquier prejuicio, equivocación o animosidad percibida son las totalmente mías.