martes, 1 de octubre de 2019
lunes, 30 de septiembre de 2019
domingo, 29 de septiembre de 2019
sábado, 28 de septiembre de 2019
miércoles, 25 de septiembre de 2019
martes, 24 de septiembre de 2019
lunes, 23 de septiembre de 2019
domingo, 22 de septiembre de 2019
sábado, 21 de septiembre de 2019
viernes, 20 de septiembre de 2019
miércoles, 18 de septiembre de 2019
viernes, 13 de septiembre de 2019
jueves, 12 de septiembre de 2019
miércoles, 11 de septiembre de 2019
martes, 10 de septiembre de 2019
lunes, 9 de septiembre de 2019
domingo, 8 de septiembre de 2019
sábado, 7 de septiembre de 2019
viernes, 6 de septiembre de 2019
jueves, 5 de septiembre de 2019
martes, 3 de septiembre de 2019
lunes, 26 de agosto de 2019
domingo, 25 de agosto de 2019
sábado, 24 de agosto de 2019
jueves, 22 de agosto de 2019
lunes, 5 de agosto de 2019
miércoles, 31 de julio de 2019
jueves, 11 de julio de 2019
martes, 9 de julio de 2019
domingo, 7 de julio de 2019
jueves, 27 de junio de 2019
miércoles, 26 de junio de 2019
viernes, 7 de junio de 2019
FoxFaker para generar datos falsos en Visual FoxPro
He liberado una librería (que tal vez no despierte el interés de muchos, pues no todos trabajamos de la misma forma) que permite generar datos falsos. Si alguna vez han trabajado con librerías Faker de PHP, Ruby o Python entonces esto les será muy familiar.
Uso:
PUBLIC
Faker
Faker
= NewObject("FoxFaker",
"FoxFaker.prg")
?Faker.fakeName() &&
Vincenzo Kihn MD
?Faker.fakeLastName() &&
Willms
?Faker.fakeBoolean() &&
.T.
?Faker.fakeColorName() &&
maroon
?Faker.fakeEmail() &&
clara.hauck@hagenes.biz
Casos de uso: poblar los objetos de negocio para pruebas de estrés (solo para quienes trabajan en capas o al menos separen las responsabilidades en clases).
Para mis estudiantes de "El Zorro Peregrino", esta es una materia obligatoria. Ya daré detalles en los próximos videos.
Agradecimientos especiales:
Hasta la próxima!
viernes, 26 de abril de 2019
Metodologías Ágiles en VFP de las Historias de Usuario al código - ppt descargar
Metodologías Ágiles en VFP de las Historias de Usuario al código - ppt descargar: ¿Quién soy? Martín Salías Arquitecto de Software Latinoamérica, USA, Canadá, Australia y Escandinavia Microsoft Consulting Services Microsoft MVP Editor en Jefe Universal Thread Magazine (3 años) Level Extreme .Net Magazine (actual) Miembro de la Agile Alliance Orador y colaborador de MSDN Cono Sur
miércoles, 17 de abril de 2019
Parser JSON para FOX (JSONFOX)
Hace unos meses comencé un proyecto llamado "El zorro peregrino" el cual consiste en mostrar el camino a través de la practica, a los foxeros que ya tienen sus años trabajando con este maravilloso lenguaje de programación; el camino mencionado es el de las nuevas tecnologías o tendencias de desarrollo.
He dicho por largo tiempo en grupos de debates y opiniones que la tecnología sube por ascensor y nosotros (los foxeros) subimos por escalera, esto quiere decir que cada dia literalmente nos hacemos más obsoletos y menos cotizables en el monstruoso mercado laboral.
Aún recuerdo aquella vez cuando fui a una entrevista de trabajo para desarrollador y me preguntaron que si hacía servicios web, entre mi dije, ¡Vaya, que será servicios web!, ¿será que son páginas web?, si digo que si entonces puede que me pregunten algo sobre eso y voy a quedar mal, más vale ser ignorante por 1 minuto que por toda la vida, mejor pregunto.
Les pregunté que si era hacer páginas web, me dijeron que sí entonces les dije que si sabia pero que no era mi fuerte. Más tarde me di cuenta de que me habian dicho que si solo porque ya no les interesaba y les daba igual mi respuesta.
Desde ese entonces sufri una gran decepción conmigo mismo porque no estaba al dia con los avances tecnológicos; me quedé estancado depurando errores en una empresa de software que terminaron cegándome al punto de sentir temor si algún dia me decidía a salirme del yugo patrono-empleado y comenzar mi carrera como freelancer.
Me di cuenta de que estaba muy por debajo del nivel que exigía el mundo tecnológico en ese momento asi que me dediqué a leer y actualizarme poco a poco, claro que siguiendo con Visual FoxPro porque era el que daba de comer (de hecho sigue dando).
Es por eso que comencé el proyecto El zorro peregrino, para que los programadores tengan una guia de como realizar la transición a este mundo moderno, seguramente muchos de los foxeros están desactualizados como me pasó a mi, lo puedo apostar porque en ese entonces era un venteañero, ahora tengo 33, soy un Foxero joven considerando los años que lleva el lenguaje y la cantidad de empresas de software que aún hoy dia siguen sostenidas por su software desarrollado en Visual FoxPro, lo cual se traduce en foxeros esparcidos por el mundo con un minimo de 15 años y un minimo de 45 años de edad.
Si fue dificil para mi adaptarme a las nuevas tendencias entonces no lo supone para ellos?
Bueno, dejemos tanta chachara y veamos el JSONFox
Es una libreria de código abierto que permite parsear JSON a un objeto o representación string, lo interesante de la librería es que nació de la necesidad de intercambiar información con las aplicaciones de Fox separadas en capas, por lo tanto era indispensable conseguir algún medio de transporte e intercambio de data entre los componentes de las capas y, sabiendo que Fox tiene compatibilidad bidireccional con Cursores y XML entonces se me ocurrió la idea de hacer el parser de JSON a XML y viceversa.
De esta manera ya tendríamos cubierta la necesidad de transportar data en formaro XML para luego serializar a un cursor (los cursores no se deben transferir entre capas)
Descarga la librería de github
https://github.com/Irwin1985/JSONFox
Hasta la próxima!!!
He dicho por largo tiempo en grupos de debates y opiniones que la tecnología sube por ascensor y nosotros (los foxeros) subimos por escalera, esto quiere decir que cada dia literalmente nos hacemos más obsoletos y menos cotizables en el monstruoso mercado laboral.
Aún recuerdo aquella vez cuando fui a una entrevista de trabajo para desarrollador y me preguntaron que si hacía servicios web, entre mi dije, ¡Vaya, que será servicios web!, ¿será que son páginas web?, si digo que si entonces puede que me pregunten algo sobre eso y voy a quedar mal, más vale ser ignorante por 1 minuto que por toda la vida, mejor pregunto.
Les pregunté que si era hacer páginas web, me dijeron que sí entonces les dije que si sabia pero que no era mi fuerte. Más tarde me di cuenta de que me habian dicho que si solo porque ya no les interesaba y les daba igual mi respuesta.
Desde ese entonces sufri una gran decepción conmigo mismo porque no estaba al dia con los avances tecnológicos; me quedé estancado depurando errores en una empresa de software que terminaron cegándome al punto de sentir temor si algún dia me decidía a salirme del yugo patrono-empleado y comenzar mi carrera como freelancer.
Me di cuenta de que estaba muy por debajo del nivel que exigía el mundo tecnológico en ese momento asi que me dediqué a leer y actualizarme poco a poco, claro que siguiendo con Visual FoxPro porque era el que daba de comer (de hecho sigue dando).
Es por eso que comencé el proyecto El zorro peregrino, para que los programadores tengan una guia de como realizar la transición a este mundo moderno, seguramente muchos de los foxeros están desactualizados como me pasó a mi, lo puedo apostar porque en ese entonces era un venteañero, ahora tengo 33, soy un Foxero joven considerando los años que lleva el lenguaje y la cantidad de empresas de software que aún hoy dia siguen sostenidas por su software desarrollado en Visual FoxPro, lo cual se traduce en foxeros esparcidos por el mundo con un minimo de 15 años y un minimo de 45 años de edad.
Si fue dificil para mi adaptarme a las nuevas tendencias entonces no lo supone para ellos?
Bueno, dejemos tanta chachara y veamos el JSONFox
Es una libreria de código abierto que permite parsear JSON a un objeto o representación string, lo interesante de la librería es que nació de la necesidad de intercambiar información con las aplicaciones de Fox separadas en capas, por lo tanto era indispensable conseguir algún medio de transporte e intercambio de data entre los componentes de las capas y, sabiendo que Fox tiene compatibilidad bidireccional con Cursores y XML entonces se me ocurrió la idea de hacer el parser de JSON a XML y viceversa.
De esta manera ya tendríamos cubierta la necesidad de transportar data en formaro XML para luego serializar a un cursor (los cursores no se deben transferir entre capas)
Descarga la librería de github
https://github.com/Irwin1985/JSONFox
Hasta la próxima!!!
viernes, 5 de abril de 2019
Exclusiones de Archivos en un .gitignore
Aquí un archivo .gitignore que contiene los tipos de extensiones que debemos excluír del control de versiones con git.
Copia el siguiente contenido y pega en un archivo que deberás guardar en tu carpeta raíz como .gitignore
NOTA: debes usar un editor de textos como notepad++ ya que windows no te dejará guardar un archivo sin nombre.
# Contine la lista de los archivos y carpetas a ignorar
# Ignorar proyecto
*.pjx
*.PJX
*.pjt
*.PJT
# Ignorar todos los programas compilados, fomularios, menues y clases
*.scx
*.sct
*.SCX
*.SCT
*.mnt
*.MNT
*.mnx
*.MNX
*.mpr
*.MPR
*.vct
*.VCT
*.vcx
*.VCX
*.fxp
*.FXP
# Ignorar bases de datos, tablas, indices
*.dbf
*.DBF
*.cdx
*.CDX
*.dbc
*.DBC
*.dct
*.DCT
*.fpt
*.FPT
*.dcx
*.DCX
*.irt
*.IRT
*.tbk
*.TBK
# Ignorar reportes
*.frx
*.FRX
*.frt
*.FRT
# Ignorar archivos temporales
*.bak
*.BAK
# Archivos ejecutables
*.exe
Extraído de: https://github.com/ircsasw/VFPconGit/blob/master/.gitignore
Copia el siguiente contenido y pega en un archivo que deberás guardar en tu carpeta raíz como .gitignore
NOTA: debes usar un editor de textos como notepad++ ya que windows no te dejará guardar un archivo sin nombre.
# Contine la lista de los archivos y carpetas a ignorar
# Ignorar proyecto
*.pjx
*.PJX
*.pjt
*.PJT
# Ignorar todos los programas compilados, fomularios, menues y clases
*.scx
*.sct
*.SCX
*.SCT
*.mnt
*.MNT
*.mnx
*.MNX
*.mpr
*.MPR
*.vct
*.VCT
*.vcx
*.VCX
*.fxp
*.FXP
# Ignorar bases de datos, tablas, indices
*.dbf
*.DBF
*.cdx
*.CDX
*.dbc
*.DBC
*.dct
*.DCT
*.fpt
*.FPT
*.dcx
*.DCX
*.irt
*.IRT
*.tbk
*.TBK
# Ignorar reportes
*.frx
*.FRX
*.frt
*.FRT
# Ignorar archivos temporales
*.bak
*.BAK
# Archivos ejecutables
*.exe
Extraído de: https://github.com/ircsasw/VFPconGit/blob/master/.gitignore
martes, 2 de abril de 2019
Imprimir un PDF usando Adobe Reader
Extraído de: https://www.foxite.com/archives/print-a-pdf-file-0000080476.htm
lcOldPrinter = SET('Printer',2)
lcPrinter = GetPrinter()
IF lcOldPrinter <> lcPrinter
DECLARE Integer SetDefaultPrinter
IN WINSPOOL.DRV String
IF SetDefaultPrinter(lcPrinter) = 0
messagebox("Cannot change default
Windows Printer")
ENDIF
ENDIF
DECLARE INTEGER ShellExecute IN SHELL32.DLL ;
INTEGER lnHWnd, ;
STRING lcAction, ;
STRING lcFileName, ;
STRING lcExeParams, ;
STRING lcDefDir, ;
INTEGER lnShowWindow
DECLARE Sleep ;
IN WIN32API ;
INTEGER nMillisecs
IF ShellExecute(0,"open", FULLPATH(This.cDefaultOutputFile),"","",1) > 32
oShell = CreateObject("WScript.Shell")
IF VARTYPE(oShell) = "O"
*wait for Acrobat reader
lntimeout=60
lnstarttime=SECONDS()
DO WHILE not (oShell.AppActivate("Adobe
Reader") OR oShell.AppActivate("Adobe Acrobat")) AND ;
SECONDS()-lnstarttime<lntimeout
sleep(2000)
ENDDO
IF oShell.AppActivate("Adobe
Reader") OR oShell.AppActivate("Adobe Acrobat")
oShell.SendKeys("^p") && print the file
lnstarttime=SECONDS()
DO WHILE NOT oShell.AppActivate("Print") AND SECONDS()-lnstarttime<lntimeout
sleep(2000)
ENDDO
IF oShell.AppActivate("Print")
oShell.SendKeys("{ENTER}")
ENDIF
lnstarttime=SECONDS()
* While printing, Acrobat reader cannot
be closed; so repeat attempts to close it.
DO WHILE (oShell.AppActivate("Adobe
Reader") OR oShell.AppActivate("Adobe Acrobat")) AND ;
SECONDS()-lnstarttime<lntimeout
oShell.SendKeys("^q") && try to close Acrobat reader
sleep(2000)
enddo
endif
oShell=.null.
ENDIF
ELSE
MESSAGEBOX("There's a problem with the Acrobat Reader.",64,'Reader problem')
ENDIF
IF lcOldPrinter <> lcPrinter
* Reset back to original printer default
SetDefaultPrinter(lcOldPrinter)
ENDIF
domingo, 24 de marzo de 2019
Entendiendo el objeto Microsoft.xmlHTTP
Microsoft.xmlHTTP (Extensible MarkUp Language / Hyper Text Transfer Protocol) es un objeto de la familia COM ActiveX que Microsft originalmente provee como acceso del lado del cliente a documentos XML alojados en servidores remotos. La comunicación se logra a traves del protocolo HTTP y consta de una pequeña API que permite realizar peticiones HTTP y obtener los resultados en distintos formatos (XML, HTML, JSON, BINARY DATA, ETC).
Sus atributos principales son: (extraído de Wikipedia)
Sus atributos principales son: (extraído de Wikipedia)
- readyState: devuelve información del estado del objeto (0 = sin inicializar, 1 = abierto, 2 = cabeceras recibidas, 3 = cargando, 4 completado).
- responseBody: devuelve la respuesta como un array de bytes.
- responseText: devuelve la respuesta como una cadena.
- responseXML: devuelve la respuesta como XML.
- status: devuelve el estado como un número. Ejemplo: 404 para "Not Found"
- statusText: devuelve el estado como una cadena. Ejemplo: "Not Found"
Lista de métodos: (extraído de Wikipedia)
- abort(): simplemente cancela la petición en curso. En un caso de uso pudieramos tener una ventana donde la solicitud se esté procesando y a traves de un commandButton podemos brindarle la opción al usuario de poder cancelar la petición (mala conexión al internet, fallas en el sistema operativo, latencia en la red, etc). Al dar click en cancelar, utilizamos este método y finalmente presentaríamos un mensaje de "proceso cancelado por el usuario".
- getAllResponseHeader(): devuelve el conjunto de cabeceras HTTP como una cadena. Esta información sería las cabeceras definidas por el servidor y no las definidas en el cliente.
- getResonseHeader(cHeaderName): devuelve el valor de la cabecera HTTP especificada.
- open(cMethodName, cURL [,asyncrono [, nombre usuario [, clave]]]): abre la comunicación con el servidor. Se especifica el Método y la URL; los demás argumentos son opcionales.
- send([datos]): envía la petición.
- setRequestHeader(): añade un KVP (key, value, pair) a la cabecera HTTP a enviar.
Aplicación en Visual FoxPro
Para aplicar el objeto XMLHTTP dentro de Visual Foxpro 9.0 simplemente hacemos uso del comando CREATEOBJECT.
Veamos algunos ejemplos con lo descrito anteriormente:
*-- Declarar la variable xmlHTTP [Opcional]
LOCAL xmlHTTP as
"Microstft.XMLHTTP"
Aunque este paso es opcional debido a que VFP es debilmente tipado, siempre es bueno mantener las buenas practicas de programación y declarar las variables con su respectivo tipo antes de usarlas.
*-- Crear la instancia del objeto
XMLHTTP
xmlHTTP = CREATEOBJECT("Microsoft.XMLHTTP")
En este paso ya tenemos una referencia al objeto XMLHTTP creada. (Estos pasos los puedes realizar en modo interactivo usando la consola de VFP)
*-- Enviando la peticion HTTP a un
servidor remoto
xmlHttp.open("GET", "https://swapi.co/api/planets/1/")
Aquí usamos el método open para enviar la petición HTTP. En el ejemplo se especifica el verbo GET a la direccion del servidor https://swapi.co/api/planets/1/. La URL apunta a una API gratuita de Star Wars que sirve consumir recursos relacionados con la serie. En este caso estamos pidiendo el detalle del plateta cuyo identificador unico es el número 1.
?xmlHttp.readyState
Si en este momento consultamos el atributo readyState obtendríamos por pantalla un "1". Nuestro objeto nos está diciendo que la petición está abierta.
?xmlHttp.responseText
Si nos adelantamos a imprimir un responseText por pantalla entonces obtendríamos una excepción no controlada diciendo que la operación no esta disponible todavía. Esto se debe a que no hemos enviado la petición al servidor aún, solo quedamos en el método open que es distinto del método send.
xmlHTTP.send()
?xmlHttp.readyState
Si ejecutamos el método send del objeto xmlHTTP entonces ya estaríamos enviando la petición al servidor. Seguidamente si imprimimos el atributo readyState por pantalla entonces obtendríamos un "4" que significa completado.
NOTA: el atributo readyState no pasa del 1 al 4 directamente, en esa transición se encuentra el valor 3 que significa "cargando" y puede demorarse por motivos ajenos a nuestro código (latencia en la señal de internet, sin conexión de red, etc), por lo tanto siempre es recomendable evaluar su valor antes de pedir la respuesta dela petición.
?xmlHttp.status
Al imprimir por pantalla el atributo status (si todo ha marchado bien) vemos que nos muestra el valor "200" indicandonos que la respuesta HTTP del servidor es "OK"
Para mayor información acerca de los códigos de respuestas HTTP véase el siguiente link: https://es.wikipedia.org/wiki/Anexo:Códigos_de_estado_HTTP
?xmlHttp.statusText
El atributo statustext es la representación en cadena del atributo status, es decir, la descripción del valor numérico obtenido como respuesta al hacer uso del atributo status. (ver enlace anterior).
?xmlHttp.responseText
A estas alturas ya es posible obtener el contentido del atributo responseText, en este caso lo imprimimos por pantalla y obtendríamos la respuesta enviada desde el servidor.
RELEASE xmlHTTP
Finalmente hay que liberar la variable de la memoria.
Un ejemplo controlado sería el siguiente:
CLEAR ALL
RELEASE ALL
*-- Declarar la variable de tipo
XMLHTTP
LOCAL xmlHTTP As "Microsoft.XMLHTTP", ;
lcURL As String
*-- Definir las constantes para la
evaluación de resultados.
#DEFINE HTTP_STATUS_OK 200
#DEFINE HTTP_COMPLETED 4
#DEFINE HTTP_OPEN 1
#DEFINE CR CHR(13)
#DEFINE MSGBOX_INFO 64
#DEFINE MSGBOX_WARNING 48
#DEFINE TYPE_OBJECT "O"
#DEFINE TIME_OUT 3 && Tiempo
de espera máximo para la respuesta.
lcURL = "https://swapi.co/api/planets/1/"
*-- Creamos la instancia del
objeto XMLHTTP
xmlHTTP = CREATEOBJECT("Microsoft.XMLHTTP")
IF TYPE("xmlHTTP") <> TYPE_OBJECT
WAIT "No se pudo
crear el objeto (XMLHTTP)." WINDOW NOWAIT
RETURN
ELSE &&TYPE("xmlHTTP")
<> TYPE_OBJECT
ENDIF &&TYPE("xmlHTTP")
<> TYPE_OBJECT
*-- Abrimos la conexión
xmlHTTP.open("GET", lcURL)
*-- Evaluamos el stado del objeto.
IF xmlHTTP.readyState <> HTTP_OPEN
WAIT "No se pudo
procesar su solicitud." WINDOW NOWAIT
RETURN
ELSE &&xmlHTTP.readyState
<> HTTP_OPEN
ENDIF &&xmlHTTP.readyState
<> HTTP_OPEN
*-- Enviamos la petición HTTP
xmlHTTP.send()
*-- Tenemos que esperar a que
cambie el valor del atributo readyState.
*-- para ello utilizamos un bucle
controlado con un máximo de 3 segundos.
nSeg = SECONDS() + TIME_OUT
DO WHILE SECONDS() <= nSeg
WAIT "Esperando
respuesta del servidor, tiempo restante {" + STR(nSeg - SECONDS()) + "}
Seg." WINDOW NOWAIT
IF
xmlHTTP.readyState <> HTTP_OPEN
*-- Hubo una
respuesta
EXIT
ELSE
&&xmlHTTP.readyState
<> HTTP_OPEN
ENDIF &&xmlHTTP.readyState
<> HTTP_OPEN
WAIT CLEAR
ENDDO &&WHILE
SECONDS() <= nSeg
*-- Evaluamos la respuesta.
IF xmlHTTP.readyState == HTTP_COMPLETED AND xmlHTTP.status == HTTP_STATUS_OK
MESSAGEBOX("Solicitud
procesada exitosamente." + CR + "La respuesta del servidor es: " + CR + xmlHTTP.responseText, MSGBOX_INFO, "Success")
ELSE &&xmlHTTP.readyState
== HTTP_COMPLETED AND xmlHTTP.status == HTTP_STATUS_OK
*--
Es recomendable encapsular el control de errores HTTP en una función.
WAIT "No se pudo
procesar su solicitud." WINDOW NOWAIT
ENDIF &&xmlHTTP.readyState
== HTTP_COMPLETED AND xmlHTTP.status == HTTP_STATUS_OK
RELEASE xmlHTTP
Espero que el artículo les haya sido de utilidad.
Happy coding!!!
Suscribirse a:
Entradas (Atom)