Como ser mejor programador Harbour

En el presente artículo voy a exponer mi opinión personal sobre la manera de ser mejor programador Harbour. Repito que es mi opinión personal, basada en mi propia experiencia, y en la observación de la trayectoria de excelentes programadores Harbour que conozco. Para realizar cualquier aportación por favor hazlo en los comentarios de esta artículo. Los enlaces que nombro son los que uso habitualmente, si conoces otros que sean similares, por favor ponlo en los comentarios del artículo.

0.- Aprende Harbour profundamente y colabora con la comunidad.

Aprende las funcionalidades de Harbour que son distintas de Clipper. Descargate la versión completa de Harbour desde el repositorio oficial y revisa la documentación y los ejemplos. Algunas de las distribuciones de Harbour usadas por los GUI no están completas, pues pueden faltar carpetas como contrib, examples, tests,… por eso debes tener siempre una versión completa de Harbour en tu PC. Aprende a construir el compilador y las librerías, y revisa los ejemplos. Siempre recuerdo las palabras de Rafa Carmona: ‘Pensamos en Harbour como un clon de Clipper, pero va mucho más allá’. Cosas como los tipos extendidos de datos o los hash array no existían en Clipper y debes conocrlos y aprender a utilizarlos.

Ten a mano los enlaces de la documentación oficial que está en https://harbour.github.io/doc/harbour.html, y también la excelente lista de funciones de harbour que Petewg tiene alojada en Github. Sigue los grupos Harbour Users y Harbour Developers para enterarte de las novedades y problemas existentes. Revisa la página de proyectos Harbour en GitHub — https://github.com/rjopek/harbour-list — mantenida por Rafal Jopek y, por supuesto, suscríbete a Harbour Magazine.

Participa en los foros del GUI/entorno que utilices, y se amable con el resto de usuarios. Si planteas una cuestión y las respuestas del resto de usuarios te encaminan a resolverla no contestes con un escueto Resuelto, sino explica la manera en que lo has resuelto y publica tu código.

1.- Aprende otro lenguaje de programación.

Te aconsejo que aprendas otro lenguaje de programación, y te sugiero que aprendas un lenguaje que te permita hacer cosas diferentes a Harbour. Para justificar esto te voy a contar mi experiencia.

Hace unos años comencé a aprender Python, en parte por la influencia de un amigo que es pythonista convencido. Me hablaba de las bondades del lenguaje, así que decidí aprenderlo. Hice un curso online superinteresante, compré varios libros, le dediqué bastante tiempo. Python es un lenguaje increible, sin embargo nunca lo utilicé. ¿ Por qué ? Porque con Python puedo hacer lo mismo que con Harbour, y Harbour es mi lenguaje preferido.

Mi buen amigo Manuel Calero tomó un camino diferente. Aprendió Java y PHP con Laravel, y los usó para realizar proyectos para los que no podía usar Harbour. El resultado es que Manuel ha incorporado los conceptos aprendidos en esos lenguajes a sus programas, tal como nos enseñó en su conferencia en Novelda.

Debes aprender otro lenguaje para aprender conceptos que no son ‘nativos’ a los programadores Harbour, muchos de los cuales venimos de Clipper. Conceptos como programar una aplicación totalmente orientada a objetos, MVC, ORM, patrones,… no son fáciles de asimilar desde Harbour si antes no los has utilizado en otros lenguajes. Una vez domines estos conceptos en otros lenguajes, te será más fácil implementarlos en Harbour

2.- Aprende a usar sistemas de control de versiones.

Los sistemas de control de versiones son imprescindibles en la programación actual. Te permiten mantener varias versiones de tu código, marcar versiones estables, y volver atrás en caso de que sea necesario. Puedes alojar tu código de manera gratuita en Github https://github.com si es opensource, en Bitbucket cualquiera que sea tu licencia, o usar sistemas de control de versiones en tu PC.

3.- Aprende a usar SQL.

SQL te va a permitir realizar aplicaciones cliente/servidor y te familiariza con el uso de bases de datos relacionales, totalmente diferente del sistema de archivos invertidos con índices que usamos en los DBF de Harbour. Además, conocer SQL te facilitará el aprendizaje de otros lenguajes de programación.

Harbour cuenta con soporte para SqLite, MySql, Postgres, ADO,… y existen varios proyectos adicionales de librerías de acceso a motores SQL como TDolphin, HDO, ADORDD,… También puedes acceder a MongoDB con el driver de harbour para MongoDb que Teo Fonrouge tiene disponible en https://github.com/tfonrouge/hbmongoc

4.- Aprende conceptos de diseño gráfico / diseño de interfaces de usuario.

Tanto si haces software de escritorio como aplicaciones web debes conocer los principios de diseño de interfaces. Las guias de diseño de los principales sistemas operativos de escritorio los tienes en estos enlaces:

Puedes hacer prototipos de tus programas rapidamente con programas como Pencil lo que te permitirá mostrar a tus clientes los formularios que vas a realizar y la interacción que habrá entre ellos.

Hay algunos libros clásicos como Presos de la tecnología de Alan Cooper, User interface design for programmers de Joel Spolsky, No me hagas pensar de Steve Krug, Seductive interaction design de Stephen Anderson creo que son lecturas muy beneficiosas para cualquier programador. Lo bueno de estos libros es que los conceptos que explican son conocimiento a largo plazo, los podrás aplicar a cualquier lenguaje que utilice.

Ten en cuenta que si tu programa hace cosas maravillosas pero su interfaz es no está bien trabajado, los usuarios puede que prefieran un programa menos potente pero más sencillo de usar.

Ten tu propia guía de diseño de formularios, y si colaboras en un trabajo en grupo debes plantear la cuestión. Yo he visto cosas espantosas, formularios que se recorrían sin orden, botones en diferentes sitios,… Yo publiqué las mias hace mucho tiempo en https://cincomundos.wordpress.com/2006/07/17/guia-de-diseno-de-formularios

5.- Utiliza software moderno, y por supuesto la última versión de tu sistema operativo.

Debes utilizar la última versión de tu sistema operativo, tanto para probar tus aplicaciones como para ver los nuevos conceptos de diseño de interfaces. Los botones 3D de Windows XP y los gradientes de Windows 7 son historia, así que no los utilices si haces aplicaciones Windows.

Fíjate en el aspecto de las aplicaciones modernas e intenta seguir su estilo. Dale una mirada a editores de código como SublimeText o Visual Studio Code, ambos cuentan con paquetes de soporte de sintaxis de Harbour, y en el caso de Visual Studio Code también cuenta con ayuda de las funciones de Harbour tal como puedes ver en la siguiente imagen.

Visual Studio Code con la extensión Harbour de Antonino Perricone.

El paquete de Antonino Perricone https://marketplace.visualstudio.com/items?itemName=aperricone.harbour es una auténtica maravilla y ha hecho que Visual Studio Code sea mi editor preferido.

Soy un enamorado de los interfaces limpios y minimalistas. Si quieres ver el programa que más me ha impresionado en los últimos meses echa un vistazo a Typora, un editor de ficheros Markdown multiplataforma que es sencillamente maravilloso.

6.- Lee libros que no sean de programación.

Cuando comencé a leer a Joel Spolsky, uno de los temas habituales era la discusión sobre libros que debían leer los programadores. Basicamente eran libros sobre desarrollo de software, pero de vez en cuando aparecían libros de sociología, psicología, emprendimiento, creatividad… cosas que no tienen directamente que ver con la programación, sino que están orbitándo alrededor de ella. Así conocí a autores como Jeson Fried — Remoto, Reinicia, Malcolm Gladwell — Fueras de serie, Inteligencia intuitiva -, Dan Pink — La sorprendente verdad sobre qué nos motiva -, Chris Gillebeau — 100€ Startup — , Angela Duckworth — Grit -, Greg McKeown — Esencialismo -, Austin Kleon — Aprende a promocionar tu trabajo, Roba como un artista — y alguno más. Estos libros se leen sin tener delante el ordenador, lo cual es una ventaja. Sirven para desconectar y al mismo tiempo conocer temas interesantes.

Alguno de los libros mencionados.

Al igual que con los libros de diseño de interfaces, se trata de conocimiento a largo plazo que podrás aplicar tanto en tu trabajo como en tu vida diaria.

7.- Lee noticiarios/agregadores de programación.

Para estar al día de novedades de programación lee noticiarios de programación. Dos de mis preferidos son freeCodeCamp y codeburst. Ahí no podrás encontrar noticias de Harbour, pero si de otros lenguajes y tecnologías. También es un buen termómetro para conocer que lenguajes y entornos son los más utilizados, y posiblemente te ayude a hacer elecciones en el futuro. Si quieres tener sincronizadas tus lecturas de esos noticiarios puedes utilizar feedly.

8.- Realiza proyectos personales y hazlos públicos.

Todos mis programas de alanit son proyectos personales. Siempre he tenido un trabajo distinto a tiempo completo y los programas los hacía en casa por la noche. Alanit significa durante la noche en catalán, mi lengua materna. Comencé haciendo los programas para mi, pero me animé a publicarlos y crear una web alrededor de ellos. Ha sido una de las mayores experiencias de mi vida.

el Puchero, uno de mis proyectos personales.

Además de publicar tus programas crea un blog explicando qué hacen y la manera en que los haces. En mi blog personal, y ahora en Harbour Magazine, he escrito muchos artículos explicando funcionalidades de mis programas, cosas nuevas que iba descubriendo y adaptando, clases nuevas, primeras versiones de esquemas de sintaxis para editores,… incluso gané el concurso de XAAC.

Tener un blog personal de programación es una gran manera de contribuir a la comunidad Harbour.

9.- Colabora con Harbour Magazine.

Cuando abrí Harbour Magazine lo hice con la intención de que fuera un blog colectivo, pero la verdad es que he tenido pocas colaboraciones. Sólo Rafa Carmona y Manuel Calero han escrito articulos para HM, pero sé que hay muchos lectores que tienen los conocimientos suficientes para escribir aquí.

Si eres uno de ellos, ponte en contacto conmigo a través del correo mediumharboutmagARROBAgmailPUNTOcom.

Clean Code en Harbour — I

Esta entrada se publicó originalmente en Harbour Magazine, mi publicación sobre el lenguaje de programación Harbour.

Este es un artículo de Manuel Calero Solís para Harbour Magazine.

Introducción

Principios de ingeniería de software, del libro de Robert C. Martin Código limpio , adaptado para Harbour. Esta no es una guía de estilo, es una guía para producir software legible, reutilizable y refactorizable. No todos los principios de este documento deben seguirse estrictamente, y aún menos serán universalmente acordados. Estas son pautas y nada más, pero están codificadas durante muchos años de experiencia colectiva por los autores de Clean Code.

Inspirado en clean-code-php

Basado en la traducción de Francisco Bórquez

Variables

Use nombres de variables significativos y fáciles de pronunciar.

Mal:

$cdt = DateTime();

Bien:

$currentDateTime = DateTime();

Usa el mismo vocabulario para el mismo tipo de variable

Mal:

getUserInfo()
getUserData()
getUserRecord()
getUserProfile()

Bien:

getUser()

Use los nombres para las búsqueda (parte 1)

Es importante que el código que escribimos sea legible y pueda buscarse. Al no nombrar variables que terminan siendo significativas para comprender nuestro programa, molestamos a los futuros lectores de nuestro código. Hagamos que los nombres sean faciles de buscar y entender.

Mal:

// Que significa realmente el dos
fileHandle = fOpen( "fopen.prg", 2)

Bien:

fileHandle = fOpen( "fopen.prg", FO_READWRITE)

Use los nombres para las búsqueda (parte 2)

Mal:

// What the heck is 4 for?
if (user:access == 4)
// do ...
end if

Bien:

#define ACCESS_READ = 1
#define ACCESS_CREATE = 2
#define ACCESS_UPDATE = 4
#define ACCESS_DELETE = 8
?
if (user:access == ACCESS_UPDATE)
// do ...
end if

Usar variables explicativas

Mal:

programsDirectory := Directory( "*.prg" )
?
aeval( programsDirectory, {|x| sendFile( x[1], x[2] ) } )

Bien:

programsDirectory := Directory( "*.prg" )
?
aeval( programsDirectory, {|programFile| sendFile( programFile[F_NAME], programFile[F_SIZE] ) } )

Evite anidar demasiado y regrese pronto (parte 1)

Demasiadas sentencias ‘if’ pueden hacer que su código sea difícil de seguir. Hay autores que llegan a decir que si tu funcion tiene muchos else (incluso solo uno), debe ser reescrita.

Explícito es mejor que implícito.

Mal:

function isShopOpen(day)
?
if !empty(day)
if hb_isstring(day)
day = lower(day)
if (day == 'friday')
return .t.
elseif (day == 'saturday')
return .t.
elseif (day == 'sunday')
return .t.
else
return .f.
end if
else
return .f.
end if
else
return .f.
end if
?
return .f.

Bien:

function isShopOpen(day)

local openingDays := {'friday', 'saturday', 'sunday'}
?
if empty(day)
return .f.
end if
?
return ( ascan( openingDays, lower(day) ) == 0 )

Evite anidar demasiado y regrese pronto (parte 2)

Mal:

function fibonacci( n )
?
if (n < 50)
if (n != 0)
if (n != 1)
return fibonacci(n - 1) + fibonacci(n - 2)
else
return 1
end if
else
return 0
end if
else
return 'Not supported'
end if
?
return n

Bien:

function fibonacci( n )
?
if (n == 0 .or. n == 1)
return n
end if
?
if (n > 50)
return 'Not supported'
end if
?
return fibonacci(n - 1) + fibonacci(n - 2)
?
return n
?

Evitar el mapeo mental

No obligue al lector de su código a traducir lo que significa la variable. Explícito es mejor que implícito.

Mal:

local li
local l := {'Austin', 'New York', 'San Francisco'}
?
for (i := 1 to len( l ))
li = l[i]
doStuff()
doSomeOtherStuff()
// ...
// ...
// ...
// Espera, ¿qué es `li`?
dispatch(li)
next

Bien:

?
local locations := {'Austin', 'New York', 'San Francisco'}
?
foreach location in location
doStuff()
doSomeOtherStuff()
// ...
// ...
// ...
dispatch(location)
next

No agregue contexto innecesario

Si su nombre de clase / objeto le dice algo, no lo repita en su nombre de variable.

Mal:

CLASS Car
?
DATA carMake
DATA carModel
DATA carColor
?
//...
ENDCLASS

Bien:

CLASS Car
?
DATA make
DATA model
DATA color
?
//...
ENDCLASS

Funciones

Parametros de función (lo ideal es 2 o menos)

Limitar la cantidad de parámetros de función es increíblemente importante porque hace que probarla sea más fácil. Tener más de tres conduce a una explosión combinatoriadonde tienes que probar toneladas de casos diferentes con cada argumento por separado.

Cero argumentos es el caso ideal. Uno o dos argumentos están bien, y se deben evitar tres.Algo más que eso debe consolidarse. Por lo general, si tiene más de dosargumentos entonces su función está tratando de hacer demasiado. En los casos en que no lo es, la mayoríadel tiempo, un objeto de nivel superior bastará como argumento.

Mal:

function createMenu(title, body, buttonText, cancellable)
?
// ...
return

Bien:

class MenuConfig
?
DATA title
DATA body
DATA buttonText
DATA cancellable INIT .f.
?
end class
?
config := MenuConfig():New()
config:title := 'Foo'
config:body := 'Bar'
config:buttonText := 'Baz'
config:cancellable := .t.
?
function createMenu( config )
// ...
return

Las funciones deberían hacer una cosa

Esta es, con mucho, la regla más importante en ingeniería de software. Cuando las funciones hacen másnde una cosa, son más difíciles de componer, probar y razonar. Cuando puedes aislaruna función para una sola acción, se pueden refactorizar fácilmente y su código leerá mucholimpio. Si no quita nada más de esta guía que no sea esto, estará adelantede muchos desarrolladores.

Mal:

function emailClients(clients)
?
foreach client in clients
clientRecord = clientModel():find(client)
if clientRecord:isActive()
email(client)
end if
next
return

Bien:

function emailClients(clients)
?
local activeClients := activeClients( clients )

aeval( activeClients, {|client| email( client ) } )
?
return nil
?
function activeClients( clients )
?
local activeClients := {}

aeval( clients, {|client| if( isClientActive( client ), aadd( activeClients, client ), ) } )
?
return ( activeClients )
?
function isClientActive( client )
?
if clientModel():find( client )
return ( clientRecord:isActive() )
end if
?
return ( .f. )

Los nombres de las funciones deberían decir lo que hacen

Mal:

CLASS Email
?
//...
?
METHOD handle()

mail( ::to, ::subject, ::body )

RETURN nil
?
ENDCLASS
?
message := Email(...):New()
// ¿Que es esto?
message:handle()

Bien:

CLASS Email 
?
//...
?
METHOD send()

mail( ::to, ::subject, ::body)
?
RETURN nil
?
ENDCLASS
?
message := Email(...):New()
// Limpio y obvio
message:send()

Las funciones deben tener sólo un nivel de abstracción

Cuando tienes más de un nivel de abstracción usualmente es porque tu función está haciendo demasiado. Separarlas en funciones lleva a la reutilización.

Mal:

function ExecutorStaments( tokenizedStatement )
?
local statement
local statements := hb_atokens( tokenizedStatement, "," )
?
for each statement in statements
if SQLConexion():Parse( statement )
SQLConexion():Execute( statement )
// ...
end if
next
?
return

Bien:

Lo mejor es crear una clase que tenga dentro dependencias a otras clases.

CLASS Tokenizer
?
METHOD new()
?
METHOD tokenizer() inline ( hb_atokens( tokens, "," ) )
?
end CLASS
?
CLASS Conexion
?
data oConexion
?
METHOD new()
?
METHOD Parse( statement ) inline ( ::oConexion:Parse( statement ) )
?
METHOD Execute( statement ) inline ( ::oConexion:Execute( statement ) )
?
ENDCLASS
?
CLASS ExecutorStaments
?
DATA tokenizer
DATA conexion
?
METHOD new()

::tokenizer := Tokenizer():New()
::conexion := Conexion():New()

RETURN ( self )
?
METHOD Execute( statement )

local statement
local statements := ::tokenizer:tokenizer( statement )
?
for each statement in statements
if ::conexion:Parse( statement )
::conexion:Execute( statement )
end if
next
?
RETURN ( self )
?
ENDCLASS

No usar logicos como parámetros de funciones

Los valores logicos le dicen al usuario que la función hace más de una cosa. Las funciones deben hacer sólo una. Divide tus funciones si ellas siguen diferentes caminos basados en un valor booleano.

Mal:

function createFile(name, temp)
?
if (temp) {
fcreate( './temp/' + name)
else
fcreate( name )
end if
?
return

Bien:

function createFile(name, temp)
?
fcreate( './temp/' + name)

return
?
function createTempFile(name)
?
fcreate( './temp/' + name)

return

Evitar efectos secundarios

Una función produce un efecto secundario si hace algo más que tomar un valor y devolver otro. Un efecto secundario puede ser escribir en un archivo, modificar alguna variable global, o accidentalmente darle todo tu dinero a un extraño.

Ahora, ocasionalmente necesitaras los efectos secundarios en un programa. Como los ejemplos anteriores, necesitarás escribir en un archivo. Lo que quieres hacer en esos casos es centralizar donde realizarlos. No tengas muchas funciones y clases que escriban un archivo en particular. Ten un servicio que lo haga. Uno y sólo uno.

El punto principal es evitar trampas comunes como compartir estados entre objetos sin alguna estructura, usar tipos de datos mutables que puedan ser escritos por cualquiera, y no centralizar donde el efecto paralelo ocurre. Si puedes hacerlo, serás más feliz que la mayoría de los demás programadores.

Mal:

// Variable global referenciada por la siguiente función.
// Si tenemos otra función que use el mismo nombre, ahora será un arreglo y podría romperla.
?
memvar name
?
function splitIntoFirstAndLastName()
?
name = hb_atokens( name, ' ' )
?
return nil
?
name = 'Manuel Calero'
?
splitIntoFirstAndLastName()
?
? ( hb_valtoexp( name ) ) // {'Manuel', 'Calero'}

Bien:

function splitIntoFirstAndLastName( name )
?
return hb_atokens( name, ' ' )
?
name := 'Manuel Calero'
newName := splitIntoFirstAndLastName(name)
?
? ( hb_valtoexp( name ) ) // 'Manuel Calero'
? ( hb_valtoexp( newName ) ) // {'Manuel', 'Calero'}

No escribas funciones globales

Llenar de funciones globales es una mala práctica en muchos lenguajes porque puedes chocar con otra librería.

Mal:

function config()
?
return { 'foo' => 'bar' }

Bien:

CLASS Configuration
?
DATA configuration INIT {}
?
METHOD New( configuration )

::configuration := configuration
?
RETURN ( self )
?
METHOD get( key )

if hhaskey( ::configuration, key )
RETURN ( hget( ::configuration, key ) )
end if
?
RETURN ( nil )
?
ENDCLASS

Crea la variable configuration con una instancia de la clase Configuration

configuration := Configuration():new( {'foo' => 'bar'} )

Y ahora puedes usar una instancia de la clase Configuration en tu aplicación.

No usar el patrón Singleton

Singleton es un anti-patrón. Citando a Brian Button:

  1. Son usados generalmente como una instancia global, ¿Por qué eso es malo? Porque escondes las dependencias de tu aplicación en tu código, en lugar de exponerlas. Hacer algo global para evitar pasarlo es una hediondez de código.
  2. Violan el principio de la responsabilidad única]: en virtud del hecho de que ellos controlan su propia creación y ciclo de vida.
  3. Inherentemente causan que el código esté estrechamente acoplado. Esto hace que muchas veces sean difíciles de probar, aunque en Harbour no tenemos bancos de pruebas.
  4. Llevan su estado al ciclo de vida de la aplicación. Otro golpe a las pruebas porque puedes terminar con una situación donde las pruebas necesitan ser ordenadas lo cual es un gran no para las pruebas unitarias. ¿Por qué? Porque cada prueba unitaria debe hacerse independiente de la otra. Misko Hevery ha realizado unas reflexiones interesantes sobre el origen del problema.

Mal:

CLASS DBConnection
?
CLASSDATA instance
?
METHOD New( dsn )
// ...
RETURN ( self )
?
METHOD getInstance() INLINE ( if( empty( ::oInstance ), ::oInstance := ::New(), ), ::oInstance )
?
// ...
ENDCLASS
?
singleton := DBConnection():getInstance()

Bien:

CLASS DBConnection
?
METHOD New( dsn )
// ...
RETURN ( self )
?
ENDCLASS

Crea una instancia de la clase DBConnection y configúrala con DSN.

connection :=  DBConnection():New( dsn )

Y ahora debes usar la instancia de DBConnection en tu aplicación.

Encapsular condicionales

Mal:

if ( article:state == 'published' ) 
// ...
end if

Bien:

if ( article:isPublished() )
// ...
end if

Evitar condicionales negativos

Mal:

function isNodeNotPresent( node )
?
// ...
?
?
if ( !isDOMNodeNotPresent( node ) )
?
// ...
?

Bien:

function isNodePresent( node )
?
// ...
?
if (isNodePresent( node ) )
?
// ...
?

Evitar condicionales

Esta parece ser una tarea imposible. Al escuchar esto por primera vez, la mayoría de la gente dice, “¿cómo se supone que haré algo sin una declaración if?» La respuesta es que la mayoría de las veces puedes usar polimorfismo para lograr el mismo resultado.

La segunda pregunta usualmente es, “bien, eso es genial, ¿pero cómo puedo hacerlo?” La respuesta es un concepto de código limpio que ya hemos aprendido: una función debe hacer sólo una cosa. Cuando tienes clases y funciones que usan declaraciones if, estás diciéndole al usuario que tu función hace más de una cosa. Recuerda, hacer sólo una cosa.

Mal:

CLASS Airplane
?
// ...
?
METHOD getCruisingAltitude()

SWITCH ::type
CASE '777':
RETURN ::getMaxAltitude() - ::getPassengerCount()
CASE 'Air Force One':
RETURN ::getMaxAltitude()
CASE 'Cessna':
RETURN ::getMaxAltitude() - ::getFuelExpenditure()
END
?
RETURN ( 0 )
?
ENDCLASS

Bien:

CLASS Airplane
?
// ...
?
METHOD getCruisingAltitude() VIRTUAL
?
ENDCLASS
?
CLASS Boeing777 FROM Airplane
?
// ...
?
METHOD getCruisingAltitude()

RETURN ::getMaxAltitude() - ::getPassengerCount()

ENDCLASS
?
CLASS AirForceOne implements Airplane

// ...
?
METHOD getCruisingAltitude()

RETURN ::getMaxAltitude()

ENDCLASS
?
CLASS Cessna implements Airplane
?
// ...
?
METHOD getCruisingAltitude()

RETURN ::getMaxAltitude() - ::getFuelExpenditure()

ENDCLASS

Evitar revisión de tipo

Harbour es un lenguaje no tipado, lo que quiere decir que tus funciones pueden tener cualquier tipo de argumento. Algunas veces habrás sentido esta libertad y te habrás tentado a hacer revisión de tipo en tus funciones. Hay muchas maneras de evitar tener que hacerlo.

Mal:

METHOD travelToTexas( vehicle )
?
if vehicle:IsDerivedFrom( 'Bicycle' )
vehicle:pedalTo( Location():New( 'texas' ) )
elseif vehicle:IsDerivedFrom( 'Car' )
vehicle:driveTo( Location():New( 'texas' ) )
end if

RETURN ( nil )

Bien:

METHOD travelToTexas( vehicle )
?
vehicle:travelTo( Location():New( 'texas' ) )

RETURN ( nil )

Quitar código muerto

El código muerto es tan malo como el código duplicado. No hay motivos para mantenerlo en tu código fuente. Si no está siendo llamado, ¡deshazte de él! Siempre estará a salvo en tu versión histórica si aún lo necesitas.

Mal:

CLASS oldRequestModule( url )
?
// ...
?
ENDCLASS
?
CLASS newRequestModule( url )
?
// ...
?
ENDCLASS
?
request := newRequestModule():New( requestUrl )
?
inventoryTracker('apples', request, 'www.inventory-awesome.io')
?

Bien:

CLASS RequestModule( url )
?
    // ...
?
ENDCLASS
?
request := RequestModule():New( requestUrl )
?
inventoryTracker('apples', request, 'www.inventory-awesome.io')

Pon filtros en tus programas

Esta entrada se publicó originalmente en Harbour Magazine, mi publicación sobre el lenguaje de programación Harbour.

En mis programas Windows utilizo un interfaz propio que he llamado FSDI — full simple display interface — del que publiqué varios artículos en mi blog cincomundos y que puede ser descargado junto con el código de Colossus que tengo publicado en GitHub.

Este interfaz FSDI consta basicamente de:

  1. Una barra lateral de acciones, que permite elegir las acciones a realizar con los datos mostrados.
  2. Una rejilla de datos configurable que muestra tipicamente los datos de un fichero DBF.
  3. Una fila de pestañas, que permite elegir la ordenación de los datos de la rejilla.
Interfaz FSDI en Fester, mi programa de gestión de comparsas de moros y cristianos.

El problema de este interfaz es que es demasiado rígido. Normalmente muestran todos los datos del DBF salvo que en un índice se haya incluido una condición. Para añadir flexibilidad a los datos a mostrar podemos incluir opciones de filtrado.

La opción de filtrado despliega un menú con todas las opciones de filtrado y la opción de eliminar el filtro. Normalmente el filtrado lo realizo por todos los campos que son clave ajena de la tabla, así como por algunos valores o rango de valores propios de la tabla como fechas, campos de marcas, etc. Antes de realizar el filtro se permite elegir el valor a filtrar mediante un diálogo auxiliar.

Acción y menú de opciones de filtrado.

En Harbour se puede definir filtros sobre un DBF usando la sentencia dbSetFilter([<bCondition>], [<cCondition>]) y definiendo las condiciones mediante codeblocks. Lo bueno de los filtros es puedes realizar otras acciones sobre las tablas como puede ser cambios de índice o búsquedas, y simplemente estas acciones se realizarán sobre los datos filtrados.

Un problema que podemos tener al definir filtros es que realicemos una acción en bloque sobre la tabla, por lo que deberemos llevar cuidado de quitar el filtro y luego reponerlo. Para guardar el contenido del filtro podemos usar las funciones dbFilter() y para eliminarlo dbClearFilter().

Una acción importante, desde mi punto de vista, cuando creamos un filtro es que el usuario debe tener conocimiento visual de ello, es decir, debemos decirle a nuestro usuario que hay un filtro activado. En mis programas hago esto de dos formas:

  1. Añadiendo el nombre del filtro al nombre del mantenimiento en la barra de opciones.
  2. Cambiando el color de la etiqueta de la opción de definición de filtros a rojo.

Una vez se elimina el filtro, mediante la misma opción de filtrado todos estos elementos visuales desaparecen.

La posibilidad de definición de filtros sobre tablas es una opción existente en Harbour que podemos incluir de manera sencilla en nuestros programas, lo que nos permitirá añadir una gran flexibilidad a los mismos. Es importante que cuando apliquemos filtros lo hagamos de manera que el usuario vea claramente que hay un filtro activo, y no le lleve a confusión.

Noticias de Harbour — diciembre 2017

Esta entrada se publicó originalmente en Harbour Magazine, mi publicación sobre el lenguaje de programación Harbour.

En los últimos meses tenemos varias novedades sobre Harbour que te presentamos a continuación:

¿ Conoces alguna novedad sobre Harbour, su entorno de programación, artículos sobre el lenguaje, código fuente, etc. que merezcan ser publicados ? Escribeme a [email protected] y lo publicaré en el próximo boletín sobre Harbour.

Videos de las conferencias de la 1ª Reunión de Harbour Magazine

Esta entrada se publicó originalmente en Harbour Magazine, mi publicación sobre el lenguaje de programación Harbour.

En la reunión que realizamos en Novelda grabamos todas las conferencias. Bueno, todas no porque se acabó el disco de la cámara justo al final de la charla de Manu Expósito, por lo que la conferencia de Manuel Calero no la pudimos grabar. He creado un canal en Youtube con los videos de las conferencias y aquí os las muestro. Todas las conferencias están en español.

Fundamentos técnicos de la Inteligencia Artificial, por Antonio Linares

Api Rest y su uso en Google, por Cristobal Navarro

Servicios web con Harbour, por Rafa Carmona

Win & Web, los nuevos escenarios, por Carles Aubia

Harbour Data Objects, por Manu Expósito

XEdit y control de versiones, por José F. Giménez

Experiencias de una publicación sobre Harbour, por José Luis Sánchez

Inspiradora

Esta entrada se publicó originalmente en Harbour Magazine, mi publicación sobre el lenguaje de programación Harbour.

Esta es la palabra que para mi mejor describe la 1ª reunión de programadores de Harbour Magazine.

Inspiradora porque Harbour es un gran lenguaje de programación, porque con Harbour se pueden hacer más cosas que software de escritorio, porque hay mucho que estudiar y aprender, porque hay gente que hace estas cosas y puede ayudar a la comunidad, porque podemos atacar motores de bases de datos de una manera cómoda, porque el uso de patrones de diseño es posible, porque tenemos herramientas potentes.

Inspiradora porque el sentimiento de comunidad no se ha perdido entre los desarrolladores Harbour, porque la asistencia a la reunión ha estrechado de nuevo los lazos entre los asistentes y nació el compromiso colectivo de organizar de nuevo reuniones entre nosotros e invitar a toda la comunidad Harbour a unirse a las reuniones.

Los asistentes en el castillo de Novelda.

Este es un primer post sobre la reunión pues tengo grabadas casi todas las conferencias en video, y voy a ir montando y subiendo los videos conforme tenga tiempo.

¿ Y las conferencias ? Pues para mi todas fueron una pasada total. Vamos a verlas una a una.

La sala de conferencias con algunos de los asistentes.

Fundamentos técnicos de la Inteligencia Artificial, por Antonio Linares

Antonio nos hizo una exposición muy amena de lo que es la inteligencia artificial, adentrándonos en los conceptos básicos hasta llegar al concepto de perceptrón y red neuronal, pasando a ver ejemplos de un perceptrón hecho con Harbour. Después siguió con más ejemplos hasta llegar a hacer una introducción de TensorFlow y mostrar un ejemplo funcionando con Python.

Antonio Linares.

La presentación de Antonio se puede descargar en la siguiente dirección:

https://bitbucket.org/fivetech/harbour_novelda_2017/downloads/Fundamentos%20t%C3%A9cnicos%20de%20la%20Inteligencia%20Artificial.pdf

Los ficheros usados en la conferencia se pueden descargar desde el siguiente enlace:

https://bitbucket.org/fivetech/harbour_novelda_2017/downloads/

Api Rest y su uso en Google, por Cristobal Navarro

Cristobal nos explicó los conceptos de API’s REST, mostrandonos a continuación los distintos APIS existentes en Google, describiéndolos y mostrándo ejemplos de su uso. Por último nos mostró una jerarquía de clases que está desarrollando y que permitirán utilizar comodamente estos API RST de Google desde programas Harbour.

Cristobal Navarro.

La presentación de Cristobal se puede descargar en el siguiente enlace:

https://bitbucket.org/fivetech/harbour_novelda_2017/downloads/Cristobal_Navarro_REST.pdf

Servicios web con Harbour, por Rafa Carmona

La conferencia de Rafa volvió a demostrar que es una auténtica esponja absorbiendo conocimientos. Primero nos contó la manera de montar un servidor web con Harbour usando el ejemplo existente en contrib/hbhttpd y a continuación la manera de montar un servicio web con Harbour y utilizarlo para conectarlo con otros sistemas.

Rafa ‘TheFull’ Carmona.

La presentación de Rafa se puede descargar en el siguiente enlace:

https://drive.google.com/open?id=1L7QB6tVbF4e_tqghmBfTGp8-nNwt_zPn

Win & Web, los nuevos escenarios, por Carles Aubia

Carles nos presentó un framework de programación web que ha desarrollado y que permite realizar aplicaciones web con una sintaxis similar a Harbour y definiendo los formularios web mediante un editor de recursos y almacenarlos en un fichero .rc. Algo realmente novedoso e impresionante, y que Carles tiene intención de liberar como open source en un futuro muy próximo con el nombre de TWeb.

Carles Aubia.

La presentación de Carles se puede descargar en el siguiente enlace:

https://drive.google.com/open?id=1Ckp9xMlFqB49aQQizFPe6AXq4buzjCww

Harbour Data Objects, por Manu Expósito

Manu explicó en que consiste su solución de acceso a datos llamada HDO, mostrando su arquitectura multicapa y dando un repaso a todos los métodos de la clase que permite en acceso a bases de datos MySql. Toda la clase está escrita en C lo que le da una rapidez endiablada.

Manu Expósito.

La presentación de Manu se puede descargar en el siguiente enlace:

https://drive.google.com/open?id=1aBgtQn9ZWJYTSRZw1_PTuEclVl8YK3Is

Patrón MVC en Harbour, por Manuel Calero

Manuel nos hizo una exposición del patrón MVC, explicando cada uno de sus componentes y nos explicó como está usando MVC en la refactorización completa de su aplicación Gestool. También nos habló de Validators y Asserts y como integrarlos en un desarrollo con patrón MVC.

Manuel Calero.

La presentación de Manuel se puede descargar en el siguiente enlace:

https://drive.google.com/open?id=1xnIducezrd_lBHH_zeshhOOeUVbUzSCx

XEdit y control de versiones, por José F. Giménez

José nos mostró el uso básico de su editor gratuito XEdit y a continuación nos explicó la manera de usar el sistema de control de versiones que han integrado en el editor. Este sistema de control de versiones funciona en local y tiene todas las funcionalidades de un sistema de control de versiones sin necesidad de contar con un servidor, sino unicamente el editor XEdit.

José F. Giménez.

La presentación de José y la documentación de XVC se pueden descargar de los siguientes enlaces:

https://drive.google.com/open?id=1wJUnw_2wELqnn7c1x6JXR-iVBOzFwtmn
https://drive.google.com/open?id=1qzRaz-qb6dhq1MGs6HAk_NaxI6gTvOy1

Experiencias de una publicación sobre Harbour, por José Luis Sánchez

En mi charla conté los motivos que me llevaron a iniciar Harbour Magazine y mostré la importancia de publicar los artículos tanto en español como inglés. Mostré las estadísticas de lecturas de las entradas, el motivo de convocar una reunión y expuse los planes de continuar potenciando la comunidad Harbour.

José Luis Sánchez

Mi presentación se puede descargar en el siguiente enlace:

https://drive.google.com/open?id=1Lm1irwwk6u1eukJMhH_9l1gdIjwig0kF

Y además…

Fueron un par de dias de volver a vernos los que ya nos conociamos y ponernos cara los que no nos conociamos. Creo que lo pasamos muy bien y hubo un gran ambiente entre los asisntentes a la reunión.

Aquí dejo alguna muestra de ello.

Y también hubo tiempo de ocio 😉

¡ Muchas gracias a todos por venir a Novelda !

Agenda de conferencias de la 1ª Reunión de programadores Harbour Magazine

Esta entrada se publicó originalmente en Harbour Magazine, mi publicación sobre el lenguaje de programación Harbour.

Ya tengo ultimada la agenda de conferencias para la Reunión de programadores Harbour que vamos a realizar los próximos 11 y 12 de Noviembre en Novelda (Alicante-España). Salvo modificaciones de última hora, la agenda va a ser la siguiente:

Agenda para la 1ra reunión de programadores Harbour

Todos los conferenciantes son programadores del máximo nivel, muy conocidos tanto dentro como fuera de España, con una activa participación en los distintos foros existentes de Harbour.

Las conferencias se realizarán en el Ecoalbergue La Mola y la entrada a las mismas es libre, condicionada al aforo de la sala. Para facilitar la organización, solicito a los interesados en acudir a las conferencias que rellenen el formulario de inscripción a las mismas.

Harbour Magazine

Publication about Harbour programming language

TRecord o cuando menos es más

Hace unos meses tuve un problema de lentitud con una aplicación. Se había eliminado el servidor de una oficina y la aplicación, que funciona en red, se tenía que ejecutar en remoto desde otra. Comenzaron los problemas de lentitud, abrir una formulario TFSDI — https://cincomundos.wordpress.com/2006/06/13/fsdi2006/ — con una rejilla de datos sobre un fichero tardaba casi 10 segundos. Después de varias pruebas, vi que el problema era una clase browse muy vieja, y que simplemente actualizando la versión de Harbour + FWH usada en la aplicación la lentitud desaparecía hasta niveles aceptables.

Entonces caí en la cuenta de que en esta aplicación estaba utilizando una clase de manejo de dbf, y al intentar compilarla para la versión de Harbour a utilizar me daba un montón de errores. La alternativa era rehacer todo el código afectado por la clase o seguir utilizándola actualizándola, cosa que a su vez llevaba a rehacer código pues esa clase había sido actualizada de manera no compatible con la que yo tenía.

Lo que hice fue coger la calle de enmedio. Rehice todo el código afectado por la clase a Harbour puro, y comencé a utilizar una clase de manejo de buffer de registro que me proporcionó Marcelo Via Giglio en http://forums.fivetechsupport.com/viewtopic.php?f=6&t=34402 . Con esta clase podría manejar todos los campos de un dbf como datas de un objeto y cargarlos/salvarlos con una llamada a un método. Es una solución sencilla, pero me evitó tener que aprender el manejo de otra clase de gestión de dbf que suelen tener montones de opciones que nunca utilizo. En mi caso, menos es más.

La clase TRecord está publicada en https://github.com/JoseluisSanchez/TRecord y he actualizado Colossus para mostrar el uso de esta clase, los cambios están en la gestión de claves https://github.com/JoseluisSanchez/colossus/blob/master/prg/pclaves.prg

¿ Usas clases de terceros y has tenido situaciones como la mía ? ¿ Estás a favor o en contra de estas clases ? Espero tu respuesta en los comentarios.

Harbour Magazine

En febrero de este año comencé la publicación de Harbour Magazine, una publicación dedicada al lenguaje de programación Harbour.
Es por ello que este blog ha estado un tanto abandonado, pues he estado publicando allí información acerca del lenguaje Harbour. Harbour Magazine es bilingue español/inglés, es la primera vez que hago algo así y está siendo una gran experiencia.

Los post publicados hasta ahora han sido los siguientes:

Con Harbour Magazine ya son tres los sitios web donde publico: el blog de alanit, cincomundos y Harbour Magazine. Sinceramente no me gusta nada tanta dispersión de contenidos así que estoy pensando seriamente en unificar todo en un único sitio. Veremos como lo hago.

1ª Reunión de programadores Harbour Magazine

Esta entrada se publicó originalmente en Harbour Magazine, mi publicación sobre el lenguaje de programación Harbour.

Harbour Magazine organiza una reunión de programadores en Novelda (Alicante — España) los próximos días 11 y 12 de Noviembre de 2017.

En la reunión tendremos una visita turística a la ciudad, conferencias de destacados programadores y mesas redondas. El idioma de la reunión será el español. Las conferencias previstas en el momento de abrir la inscripción son las siguientes:

  • Patrón MVC con FWH y MySQL, por Manuel Calero Solís.
  • Harbour Data Objects, por Manu Expósito.
  • Inteligencia Artificial con Harbour, por Antonio Linares Cañas.
  • Uso de Advantage Data Server con Harbour, por Reinaldo Crespo.
  • Charla de Rafa ‘TheFull’ Carmona, pendiente de concretar.

En caso de que algún asistente desee realizar una conferencia puede comunicarlo en el formulario de inscripción.

En el siguiente documento se presenta toda la información práctica de la reunión: Reunión de Programadores Harbour Magazine.

Debido a la capacidad de las salas de conferencias hay unicamente 40 plazas para asistentes a la reunión.

Ya está abierto el formulario de inscripción.Harbour Magazine

Publication about Harbour programming language