Modelado de datos booleanos en la base de datos

Posted: Febrero 9th, 2017 | Author: | Filed under: Sin categoría | Tags: , , , , | No Comments »

Cuando definimos la información que un usuario puede visualizar o modificar a través de un formulario nos encontraremos datos aparentemente booleanos. Por ejemplo: ¿Hay un pozo en esta aldea?.

La primera aproximación para implementar esta información es poner un checkbox en el formulario y definir el campo como booleano en la base de datos.

CREATE TABLE aldea (id serial, pozo BOOLEAN);

Haciéndolo de este modo existen varios posibles problemas:

  • A nivel usabilidad. Que pasa si el usuario no sabe si hay un pozo. Lógicamente dejará el checkbox sin marcar, pero cuando se revise esa información no se podrá saber si a conciencia se dejo en blanco indicando que no había pozo, o si se desconocía el dato.
  • A nivel implementación. Por defecto, a no ser que la lógica implementada en cliente lo gestione de otra forma, en la base de datos almacenaremos un valor NULL y no un valor FALSE. Al tener valores nulos las queries que hagamos se pueden complicar, por ejemplo un SELECT * FROM aldea WHERE pozo IS FALSE; no nos devolverá los valores nulos. Si empleamos la tabla para hacer un informe o exportarla a una hoja de cálculo tendremos que lidiar con los nulos, …

Por tanto cuando modelemos una información que parezca binaria, preguntémonos (y preguntemos al cliente) si es necesario distinguir entre falso, y desconocer el dato. Si estamos en la segunda situación debemos huír de usar checkboxes y emplear otro tipo de widget, como un combobox donde el usuario pueda escoger “Existe”, “No existe” o dejar en blanco si no conoce el dato. A nivel implementación la información del combobox la guardaremos en general como un texto o un tipo enumerado. Y si eres un producto owner que usa algún tipo de documento para definir el modelo de datos a los desarrolladores asegurate siempre de especificar esta información.

Habrá situaciones en las que aún presentando al usuario la información mediante un combo, nos interese modelar el campo como un booleano. En este caso la lógica por encima de la base de datos sería la responsable de traducir el campo en blanco por un nulo, el ‘Existe’ por un true y el ‘No existe’ por un false.

Cuando modelemos un campo en la base de datos que sea verdaderamente binario para evitar confusiones deberíamos implementarlo de esta forma.

CREATE TABLE aldea (
id serial,
pozo BOOLEAN NOT NULL DEFAULT FALSE
)

Usando GeoProcesos en gvSIG desde Java

Posted: Septiembre 4th, 2016 | Author: | Filed under: Sin categoría | Tags: , , , , , , , , | No Comments »

La semana pasada había un correo en la lista de desarrollo de gvSIG preguntando como poder lanzar geoprocesos desde tu propio plugin mediante Java. Tras una pequeña investigación he escrito un código de ejemplo que espero que sea útil a quien tenga esta necesidad.

Descargar el código

A mi particularme me gusta descargar el código fuente de las partes de gvSIG con las que voy a trabajar. Esto simplifica el usar las herramientas del IDE para saber como usarlo, encontrar errores, y revisar los tests, en caso de haberlos, para tener pistas de como escribir mi propio código.

Para ello primero se mira la versión del plugin que se corresponda con la versión de gvSIG que estás usando. Creo que lo más fácil es descargar una versión portable de gvSIG. Entrar a la carpeta que contiene el plugin, en este caso org.gvsig.geoprocess.app.mainplugin y abrir el fichero package.info. En la property version está el tag del repo correspondiente a esa versión. Por ejemplo para la 2.3RC2 sería el 2.266. Por tanto para descargar el repo haremos:

svn checkout http://devel.gvsig.org/svn/gvsig-geoprocess/org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.66/

A continuación,e n caso de usar Eclipse, iremos a import -> Existing maven projects, e importaremos la raíz del nuevo plugin descargado.

Añadir las dependencias

Al desarrollar en gvSIG debemos tener en cuenta que las dependencias de nuestro plugin, por decirlo de algún modo, serán de dos tipos. En “Tiempo de desarrollo”, y en “Tiempo de ejecución”. Las dependencias en desarrollo se definen en el pom del proyecto permitiéndonos definir el classpath de desarrollo para trabajar con las clases que nos hagan falta.

En ejecución, cuando estamos probando o ejecutando gvSIG, el classpath se define de manera dinámica por decirlo de algún modo en el fichero de config.xml. gvSIG buscará entre las dependencias que hayamos definido en el config las clases que se pueden usar en nuestro plugin.

Para que quede claro, a nuestro pom se añadirán otros proyectos maven. A nuestro config se añadirán plugins de gvSIG.

Por ejemplo para el caso de usar los geoprocesos, añadiremos al pom:

<dependency>
    <groupId>org.gvsig</groupId>
    <artifactId>org.gvsig.geoprocess.lib.api</artifactId>
    <version>2.2.66</version>
</dependency>

<dependency>
    <groupId>org.gvsig</groupId>
    <artifactId>org.gvsig.geoprocess.lib.sextante</artifactId>
    <version>2.2.66</version>
</dependency>

y al config

<depends plugin-name="org.gvsig.geoprocess.app.sextante"/>

Obtener el algoritmo que queremos

Esta una de las partes en las que tengo más dudas que esté correcta.

En general accederemos a las funcionalidades de gvSIG a través de un Locator que nos dará un Manager que nos dará la funcionalidad. En el caso de los geoprocesos sería:

String ALG_NAME = "gvSIG-intersection";
SextanteGeoProcessManager manager = (SextanteGeoProcessManager) GeoProcessLocator.getGeoProcessManager();
HashMap<String, GeoAlgorithm> algs = manager.getAlgorithms();
GeoAlgorithm alg = algs.get(ALG_NAME);

Debemos castear a la implementación por defecto del manager SextanteGeoProcessManager porque la interfaz en sí no proporciona el método getAlgorithms. Esto diría que es un bug.

La forma de obtener ALG_NAME, no estoy seguro de cual es. En principio lo más fácil sería poner un breakpoint y mirar los valores de algs. Aunque en mi caso sólo salen los propios de gvSIG y no los de Sextante.

Seteando valores al algoritmo

Todos los algoritmos definen un método defineCharacteristics que nos indican los valores que recibe, tanto de entrada como de salida. Esta definición de valores se obtiene a través del método getParameters

En nuestro código debemos obtener cada uno de los parámetros necesarios y setear su valor real para nuestro caso. Por ejemplo:

private void setParams(GeoAlgorithm alg) throws WrongParameterIDException {
    ParametersSet params = alg.getParameters();

    FLyrVect interLyr = getLayer("inter");
    FlyrVectIVectorLayer inter = new FlyrVectIVectorLayer();
    inter.create(interLyr);

    FLyrVect layerLyr = getLayer("layer");
    FlyrVectIVectorLayer layer = new FlyrVectIVectorLayer();
    layer.create(layerLyr);

    params.getParameter(IntersectionAlgorithm.INTER).setParameterValue(
            inter);
    params.getParameter(IntersectionAlgorithm.LAYER).setParameterValue(
            layer);
    params.getParameter(IntersectionAlgorithm.SELECTGEOM_INPUT)
            .setParameterValue(false);
    params.getParameter(IntersectionAlgorithm.SELECTGEOM_OVERLAY)
            .setParameterValue(false);
}

En este caso para no escribir a mano los idenfificadores de los parámetros uso las variables estáticas definidas en el propio algoritmo. Eso hace que haya que añadir al pom el algortimo:

<dependency>
    <groupId>org.gvsig</groupId>
    <artifactId>org.gvsig.geoprocess.algorithm.intersection</artifactId>
    <version>2.2.66</version>
</dependency>

Para las capas de entrada al algoritmo hay que generar una FlyrVectIVectorLayer. Como se muestra en el código de ejemplo lo más sencillo es obtener un FLyrVect y construirla con el create.

Ejecutando el algoritmo

Los algoritmos se lanzan mediante el método execute que como indica la documentación admite hasta tres parámetros.

  • ITaskMonitor task. Que puede ser nulo y permite monitorizar el estado para por ejemplo poner una barra de progreso al usuario
  • HashMap outputMap. Que permite modificar los nombres que sextante asigna a los parámetros de salida (en general capas)
  • OutputFactory outputFactory. Define como se crearán los objetos de salida. Puede ser nuestra propia implementación o usar la factoría por defecto

Por tanto ejecutarlo sería simplemente:

alg.execute(null, new DefaultOutputFactory(), null);

Obteniendo los resultados

Con la factoría por defecto las capas se crean en un directorio temporal que en linux es /tmp/tmp-andami y les asigna nombres aleatorios (creo que basados en el timestamp). Supongo que habrá alguna utilidad que nos permite ejecutar una especie de FinalActions para añdirlos automáticamente a la vista. O implementando nuestra propia OutputFactory podríamos definir otras rutas. También diría que podemos prescindir del OutputFactory y lanzar el algoritmo mediante processAlgorithm si igual que hicimos con los parámetros de entrada seteamos adecuadamente los valores de salida, especialmente el OutputChannel de las capas.

En todo caso el método getOutputObjects nos devuelve los objetos de salida, así por ejemplo podríamos llegar el FlyrVectIVectorLayer de la capa de polígonos de salida con:

OutputObjectsSet outputSet = alg.getOutputObjects();
OutPut output = outputSet.getOutPut(IntersectionAlgorithm.RESULT_POL)
FlyrVectIVectorLayer result_pol = (FlyrVectIVectorLayer) output.getOutputObject();

Atom: Autocompletado de código en python

Posted: Mayo 8th, 2016 | Author: | Filed under: Sin categoría | Tags: , , , , | No Comments »

Al margen del “Code Completion” de PyCharm, y algún otro, el resto de editores/IDEs proveen autocompletado a través de librerías o “servicios externos”. Para el caso de python hay fundamentalmente dos, rope y jedi. Rope está más enfocada a Refactoring y Jedi a Autocompletado, por tanto las dos son complementarias. En la actualidad varios editores que usaban rope están migrando a jedi, su autor ha hecho una comparación defendiendo su librería.

Además de estas librerías cada editor suele proporcionar un plugin base para autocompletado (autocomplete-plus en atom, auto-complete en emacs) y plugins adicionales para cada lenguaje concreto que actúan como wrapper de las librerías base (rope, jedi,…). Por ejemplo en atom tenemos autocomplete-python que es un wrapper para jedi.

Instalación

Primero hay que instalar jedi sea a nivel global como en el ejemplo, o dentro de un virtualenv.

sudo pip install jedi

Luego se instala el plugin de autocomplete-pyhon (que es el más actualizado de los varios que hay). Si usas virtualenv también debería funcionar sin problemas pero si usas algo como virtualenvwrapper donde tu módulo está en un directorio distinto al “entorno virtual de python” puedes haber más problemas.

Lanzado atom desde un virtualenv activado siempre funciona correctamente. Si lo lanzas de otra forma hay que configurar la opción de configuración Python executable path del plugin con algo como:

PATH_TO_VIRTUALENV_WRAPPERS_FOLDER/$PROJECT_NAME/bin/python

o

PATH_TO_VIRTUALENV_WRAPPERS_FOLDER/$PROJECT/bin/python

Donde PATH_TO_VIRTUALENV_WRAPPERS_FOLDER es la ruta absoluta al directorio donde se guardan todos los entornos virtuales de virtualenwrapper y $PROJECT_NAME y $PROJECT son cadenas que debes escribir tal cual. Son variables que entiende el plugin. De la documentación parece deducirse que lo que hay que usar es $PROJECT pero a mi me ha funcionado sólo con $PROJECT_NAME. Además el directorio padre que se añade a atom a través del “Add project folder” debería llamarse igual que el virtualenv para que $PROJECT_NAME tome el valor correcto y puedas usar la misma configuración para distintos proyectos.

Uso

Por la naturaleza dinámica de python muchas veces jedi no es capaz de detectar el tipo de datos de un objeto. Pero podemos ayudarlo documentado el método. Por ejemplo en un caso como el del ejemplo siguiente con una vista de pyramid, jedi no será capaz de determinar el tipo de datos del parámetro request.

@view_config(route_name='my_route')
def my_route(request):
  pass

Pero si hacemos lo siguiente si que autocompletará correctamente los métodos de request:

def cultivos_get(request):
    """
    :type request: pyramid.request.Request
    """

    pass

No lo he probado con python 3 para ver si soporta el type hinting pero este issue me hace suponer que si.
Teclas principales

  • Sugerencias de autocompletado.
    Ctrl+space

    Cursores y tab/intro para escoger y aceptar sugerencia

  • Go to definition:
    Ctrl+Alt+G
  • Show usages:
    Ctrl+Shift+P show usages
  • Renombrado en varios ficheros a la vez: Con el cursor encima del símbolo.
    Ctrl+Shift+P rename

Conclusiones

Las funcionalidades que proporciona son de todas formas muy justas porqué a no ser que documentes los métodos, la mayoría de veces no es capaz de inferir el tipo de datos de una variable. Además las funciones de autocompletado normal de atom incluyen habitualmente opciones que no tienen porque corresponder con métodos o propiedades reales del objeto. Y si se desactiva el autocompletado normal para los ficheros python, tendremos muy pocas sugerencias.


Eventos en backbonejs

Posted: Enero 2nd, 2016 | Author: | Filed under: Sin categoría | Tags: , , , | No Comments »

Una de las formas más interesantes de desacoplar código, vistas fundamentalmente, usando un framework MV* tipo backbone es aprender a usar correctamente los eventos y patrones asociados. Observer (pub/sub), Event Aggregator, Mediator, …

La mejor lectura al respecto que he encontrado es este post de Derick Bailey (creador de MarionetteJS), donde de forma muy ilustrativa examina distintas opciones finalizando con como hacerlo con eventos. Es recomendable también leer los comentarios, donde Derick responde a varias dudas de los lectores.

La sección sobre Eventos de Developing Backbone Applications explica bien como usar los eventos en general en backbone y esta otra sección revisita el post de Derick exponiendo la diferencia entre Event Aggregator y Mediator.

Pero para trabajar con Eventos de forma correcta además de los patrones y las especifidades de backbone es necesario conocer algunas técnicas y características de javascript relacionadas con el contexto. La siguiente selección de artículos puede ahorrarte un par de horas de quebraderos de cabeza:


Libro: Developing Backbone.js Applications

Posted: Diciembre 28th, 2015 | Author: | Filed under: Sin categoría | Tags: , , , , | No Comments »

He terminado de releer estos días Developing Backbone.js Applications, escrito fundamentalmente por Addy Osmani con la colaboración de más gente vía pull-requests en github. Los primeros capítulos del libro (Introduction, Fundamentals, Basics) se leen muy rápido y dan una buena idea, no sólo de como usar backbone si no de porqué usar un framework MVC.

La idea de mezclar el uso concreto de la herramienta con explicaciones de más alto nivel de patrones se produce a lo largo de más capítulos del libro, por lo que uses backbone o no lo que aprendas te seguirá sirviendo. Esto creo que es el principal aliciente del libro, ya seas un programador novato e inexperto en backbone, o no, puedes aprovechar las explicaciones sobre patrones MV*, Mediator vs Event Aggregator, Desarrollo Modular, …

Otra de las cosas que me gusta del libro y que es muchas veces ignorada es que dedica un capítulo entero a testing. Tal vez demasiado centrado en explicar distintas herramientas (Jasmine, QUnit, Sinon) pero aún así d utilidad.

Algunos otros capítulos me dan la impresión de ser demasiado específicos, como aquellos dedicados a desarrollo para móviles y a otros frameworks construidos sobre backbone como Marionotte y Thorax. El capítulo sobre herramientas por ejemplo también es muy específico y al ritmo al que evolucionan en estos momentos ya se ha quedado desactualizado.

Salvando eso, creo que sigue siendo un libro muy recomendable.


Aitor Guevara hablando de la arquitectura de Ducksboard

Posted: Septiembre 26th, 2015 | Author: | Filed under: Sin categoría | Tags: , , , , | No Comments »

Un vídeo algo antiguo (2013) en el que Aitor Guevara (CTO de Ducksboard) nos habla de cual era la arquitectura de Ducksboard en aquel momento. A pesar de que el vídeo dura más de una hora y media Aitor consigue hacer amena una charla técnica. No entra al mínimo detalle técnico pero si da una buena idea general. Responde sin rubor a preguntas como cual era el costo de la infraestructura que tenían en Linode (400$) o cuantos clientes de pago tienen.

Por el medio de la charla caen perlas del estilo de:

  • Usamos twisted para hacer aplicaciones asíncronas en python. ¿Conoceis nodejs? pues lo mismo pero tiene 10 años en lugar de 1.
  • Usamos backbone, porque tenemos un montón de javascript. Tenemos un montón no porque nos guste si no porque es lo que hay.

Otra de las cosas que más me gustan es la defensa que hace de PostgreSQL, que es el componente central de su infraestructura (especialmente hacia el minuto 50 pero en realidad lo hace en varios momentos). Hacia el minuto 44 explica como usan ellos backbone. La verdad es que aquí no me quedo muy claro desde donde servían el html, o si iba todo en los templates, porque el django del frontend en principio sólo actuaba como API Rest sirviendo JSON al navegador. Eso si, su django usa SQLAlchemy y no django-orm porque tenían cosas en el postgres que django-orm no soporta.

Los últimos minutos de la charla presenta un par de herramientas que “análisis del negocio” que también son de interés.

En este post además del vídeo están las transparencias.


Video: Aplicaciones en tiempo real con python y postgres

Posted: Agosto 25th, 2015 | Author: | Filed under: Sin categoría | Tags: , , , , , , , | No Comments »

Una charla de como montar aplicaciones en tiempo real con python y postgres. Tiempo real entendido como notificaciones de un chat, hacer algo cada vez que se actulice una tabla de la bd etc,…

El vídeo se hace un poco largo, seguramente con las transparencias llegaba para hacerse una idea general. Pero aún así se hace interesante por alguna de las técnicas que emplea:

  • Aboga por no usar frameworks en python. Con las librerías de hoy en día es sencillo montar una API Rest gestionando las llamadas de bajo nivel directamente
  • Usa las funciones de postgres de LISTEN y NOTIFY que combinadas con un trigger permiten que código cliente (psycopg2) sean notificados cuando algo pasa en la base de datos (se modifica una fila o lo que sea) y actuén en consecuencia (provocar un cambio en el navegador mediante websockets)
  • Para simplificar la API y el diseño de la bd, los datos se guardan como tipos nativos postgres (varchar, boolean,…), y se usa la función de postgres row_to_json para recuperarlos una cadena de texto con formato json.
  • Usa httpie para probar la API Rest. Si alguna vez usaste curl para esto enseguida verás que está bien conocer httpie.
  • A pesar de que la idea principal de la charla es montar una aplicación en tiempo real con el mínimo número de dependencias (complejidad) el proceso de build que monta no parece trivial. pip para dependencias en python, nodeenv (una especie de entorno virtual para node que se integra con el virtualenv de python), bower para las dependencias javascript de cliente,… Todo ello orquestrado por un Makefile.
  • No muestra como hacer la parte del frontend, pero en todo caso el código está en su repo

Comentarios al artículo de Complejidad y Reversibilidad de Kent Beck

Posted: Agosto 9th, 2015 | Author: | Filed under: Sin categoría | Tags: , , | No Comments »

Andrés me pincha para que lea y comente el último post de Kent Beck en su muro de facebook. Como todo lo que escribe Beck hay que leerlo con atención y se pueden sacar lecciones interesantes. Pero este artículo en particular se me hace complicado de leer porque creo que mezcla demasiadas cosas a la vez. Comienza con una teoría general sobre sistemas complejos y luego salta a prácticas concretas de facebook para atajarla en distintos estadios del desarrollo sin pararse a explicar que técnicas tienen sentido en según que contextos. Analicémoslo por tanto atendiendo al artículo como dos partes separadas.

Complejidad y Software

Software complexity es un término con definición propia en el mundo académico. En la práctica todo desarrollador tiene una noción intuitiva de que es complejidad y debería tener como principio el atajarla. Beck explica alguno de los elementos de la complejidad y cuales de ellos se puede intentar mantener bajo control en un producto como facebook. La cuestión es, si en otro tipo de productos software se puede o tiene más sentido atacar otro frente distintos al de la irreversibilidad. Personalmente se escapa de mis conocimientos esta reflexión pero apunto algunos elementos para el debate:

  • Estados. Atendiendo al producto como un todo (hardware, acciones del usuario, red,..) seguramente será difícil de atajar. Si nos quedamos con las acciones (interacción) del usuario me recuerda a la diferenciación entre mapa y camino de la que se reapropió Andrés atendidendo a Verplank.
  • Interdependencias. SOLID, KIS, Patrones, Modularidad o cualquier práctica de buen diseño entiendo que ayuda a disminuirla a no ser que se me escape algo.
  • Incertidumbre. Supongo que es el más complicado. Usuarios usando la aplicación en formas no previstas. Requisitos cambiantes,…
  • Irreversibilidad. Nada que decir, es en el que se centra Beck.

Atajar la Irreversibilidad

La segunda parte del artículo habla de algunas de las técnicas que usan en Facebook para combatirla. Algunas pueden ser consideradas de modernas como el Frequent Pushes (¿Continuous Delivery?) y otras como el Code Review llevan con nosotros mucho tiempo. Beck las enumera todas juntas pero creo que intentar ponerlas bajo una clasificación más o menos habitual en factorías de software tradicionales puede ayudar a decidir cuales pueden ser aplicables en cada caso. Dejo fuera (IRC y Data-informed decisions)

  • Desarrollo
    • Development servers
    • Code review
    • Correlation
  • Pre-Producción / Testing
    • Internal usage
    • Staged rollout
    • Advance countries
    • Shadow production
  • Producción
    • Frequent pushes
    • Soft launches
    • Dynamic configuration
    • Right hand side units
    • Double write/bulk migrate/double read

Sin duda algunas de las técnicas como Staged Rollout es discutible en que fase van y son clasificables bajo esta óptica. La idea de intentar clasificarlas es sólo para poder compararlas con una forma de trabajo que nos resulte más cercana para a partir de ahí ver cuales podemos empezar a aplicar y en que punto de nuestro proceso.

Qué puedo aplicar y cómo si no soy Facebook

Más que técnicas concretas en realidad lo que Beck plantea es una cultura (o dos). El Desarrollo Ágil y el DevOp. Intentar aplicar alguna de sus estrategias de forma separada sin abrazar la filosofía subyacente creo que sólo produce desgaste. Con esto no quiero decir que tengas que hacer pair programming y tener un devop en tu equipo, pero sí al menos comprender que hay valor en los principio que proponen.

Para mi los pasos en ese camino son tres: Tests, Automatización y Monitorización.

Monitorización. Si no estás midiendo lo que sucede rendimiento, comportamiento de usuarios, … saber lo que está pasando o cuando un cambio no tiene el efecto previsto.

Automatización. Si hacer un despliegue es costoso e implica varios pasos, se harán pocos , se tardará más tiempo en tener feedback, se introducen más posibilidades de error y no hablemos de lo que supone revertir un mal cambio. Si no se automatizan los procesos se vuelve más complicado que todos los desarrolladores tengan el mismo entorno y este sea parecido a producción.

Tests. Probablemente la piedra angular. Estoy leyendo Working Effectively with Legacy Code, y en los primeros capítulos expone algunas cuestiones sobre tests que tienen relevancia para la “reversibilidad”. En el libro comparan trabajar sin tests a hacer acrobacias sin red, y expone dos formas de introducir cambios en un sistema.

Changes in a system can be made in two primary ways. I like to call them Edit and Pray and Cover and Modify. Unfortunately, Edit and Pray is pretty much the industry standard. When you use Edit and Pray, you carefully plan the changes you are going to make, you make sure that you understand the code you are going to modify, and then you start to make the changes. When you’re done, you run the system to see if the change was enabled, and then you poke around further to make sure that you didn’t break anything. The poking around is essential. When you make your changes, you are hoping and praying that you’ll get them right, and you take extra time when you are done to make sure that you did.
Superficially, Edit and Pray seems like “working with care,” a very professional thing to do. The “care” that you take is right there at the forefront, and you expend extra care when the changes are very invasive because much more can go wrong. But safety isn’t solely a function of care. I don’t think any of us would choose a surgeon who operated with a butter knife just because he worked with care. Effective software change, like effective surgery, really involves deeper skills. Working with care doesn’t do much for you if you don’t use the right tools and techniques.
Cover and Modify is a different way of making changes. The idea behind it is that it is possible to work with a safety net when we change software. The safety net we use isn’t something that we put underneath our tables to catch us if we fall out of our chairs. Instead, it’s kind of like a cloak that we put over code we are working on to make sure that bad changes don’t leak out and infect the rest of our software. Covering software means covering it with tests. When we have a good set of tests around a piece of code, we can make changes and find out very quickly whether the effects were good or bad. We still apply the same care, but with the feedback we get, we are able to make changes more carefully.

En esencia, durante el desarrollo tener tests te permite probar y si no funciona revertir a coste casi cero. En producción el coste de revertir no es cero (al menos sin aplicar otras de las técnicas mencionadas) pero al menos te permite detectar errores de forma temprana.

 

 

 

 


Compilando y depurando un plugin de ejemplo para gvSIG 2.1 desde Eclipse

Posted: Enero 12th, 2015 | Author: | Filed under: Sin categoría | Tags: , , , , , , , | 1 Comment »

Joaquín del Cerro ha publicado un artículo explicando como compilar y depurar un plugin de ejemplo para gvSIG 2.1 con NeatBeans. He adaptado sus instrucciones para Eclipse que es mi IDE habitual. Este artículo no es tan detallado como el suyo así que seguramente tendrás que consultar los dos, especialmente los pasos previos que comenta Joaquín para que todo funcione.

Una vez que tenemos los “previos” realizados, creamos un nuevo workspace en eclipse, por ejemplo workspace-gvsig-landregistry.

Nos aseguramos de que tenemos instalados en eclipse:

Abrimos la perspectiva de eclipse de SVN Repository Exploring, desde Window -> Open perspective -> Other, o cualquier otro de los sitios desde los que se puede abrir.

Y añadimos el repositorio del plugin desde File -> New -> Repository Location o el icono correspondiente. Como URL usaremos:

http://devel.gvsig.org/svn/gvsig-plugintemplates/org.gvsig.landregistryviewer/trunk/org.gvsig.landregistryviewer/

Seleccionamos el repositorio que acabamos de añadir y en el menú contextual escogemos Check out as maven project

Si no tenemos el conector de maven-svn instalado, nos pedirá instalarlo. En la ventana previa al checkout nos aseguraremos de que la opción “All projects” está activada

Puede tardar un ratito en descargar, sobre todo si tiene que descargar muchas dependencias. Cuando acabe, pasamos a la perspectiva Java y ya tendremos los proyectos correspondientes al plugin configurados en el workspace.

Si no tienes la opción de Build automatically activada, haz un build all. A continuación pon un punto de ruptura para comprobar que todo funciona correctamente en el punto que indica Joaquín (método createWindow de la clase LandRegistryViewerExtension).

Tras lanzar gvSIG en modo debug,

./gvSIG --debug --pause

configuramos el debugger. En Debug Configurations, añadiremos una nueva configuración del tipo Remote Java Application

En name pondremos lo que queramos, por ejemplo org.gvsig.landregistryviewer.app, en project org.gvsig.landregistryviewer.app.mainplugin y en port 8765. Si antes de crear la configuración de debug seleccionamos el proyecto org.gvsig.landregistryviewer.app.mainplugin en el package explorer nos rellenará automáticamente name y project.

Al darle a debug debería abrirse gvSIG y pararse la ejecución en el punto que hemos marcado.


Aptana. Un IDE para desarrollo web

Posted: Junio 26th, 2014 | Author: | Filed under: Sin categoría | Tags: , , , | No Comments »

Hace unos meses escribía en el blog que estaba buscando un IDE para desarrollo web el cliente. Al final no me he dedicado tanto a web-cliente como pensaba y he estado jugando más en la parte de backend sobre todo con nodejs.

Dado que es el primer IDE (para web) que pruebo y tampoco tengo gran experiencia en desarrollo web me resulta difícil hacer una buena revisión, pero aquí van algunos pros y contras de programar Javascript en Aptana desde el punto de vista de alguien que viene de Java+Eclipse.

Contras

* El debugger de Apata es incompatible con la última versión de firebug por lo que debes instalar una más antigua. Tuve unos cuantos problemas intentando instalarlo y no he sido capaz de hacer un cambio en el código y recargar la página sin tener que relanzar todo firefox a través del debugger. En resumen el debugger no he sido capaz de hacerlo funcionar de una forma cómoda y he vuelto a firebug.
* El preview de la página cuando está puesto el código del google analytics hace que se cierre aptana.
* Para que el Code Assist funcione correctamente, hay que tener unos ficheros de documentación en un formato especial (ScriptDoc), y practicamente ninguna librería los tiene.
* En el “Save Action” sólo se pueden quitar los trailing spaces, estaría bien que permitiera al menos reformatear el código
* No es capaz de navegar por ocurrencias correctamente. Si marco una variable no soy capaz de moverme entre las apariciones de esa variable (Ctrl + .) como en java. Tampoco es capaz de encontrar desde donde se llama a una función (aunque este es un problema genérico de los lenguajes dinámicos). Aquí hay un listado de funcionalidades aunque no está del todo actualizado. No he probado a documentar las funciones con ScriptDoc, tal vez así el editor sea más inteligente.
* La documentación es escasa
* Así como cuando programo en Java todo el equipo usa Eclipse, con web no pasa lo mismo. Así que la idea de tener que crear workspaces y proyectos dentro del workspace llenos de directorios de configuración ocultos me resulta conceptualmente incómodo.

Pros

* Me gusta la consola interactiva. Puedo probar código sin tener que abrir la consola javascript del navegador.
* Me gusta el Content Assist de html, creo que funciona bastante bien.
* Al margen del problema con el debugger, me gusta la funcionalidad de preview ( https://wiki.appcelerator.org/display/tis/Side-by-Side+Previewing ). Me permite poner en dos pestañas paralelas mi código (html, css, js) y el navegador empotrado de aptana, al salvar uno de los ficheros la previsualización se recarga automáticamente. Está bien para ir viendo como queda. Una pena que no haya encontrado forma de debuguear desde el preview.
* Me gusta el “Go To Declaration (F3)”, aunque se equivoca de vez en cuando, si por ejemplo has estado haciendo pruebas en otro fichero, poniéndolo a las funciones el mismo nombre puede saltar a la que no es.
* Me gusta la buena integración (heredada de eclipse) con el escritorio. Poder copiar un fichero en el explorador de archivos y pegarlo en una vista de aptana, o copiar un snippet de código de una página web y pegarlo en Aptana creando automáticamente un nuevo fichero
* El sistema de templates para no arrancar proyectos como una página en blanco funciona bien.
* Es relativamente fácil, extender la funcionalidad a través de Snippets y Rubles. Aunque los Rubles hay que escribirlos en Ruby

Enlaces de interés sobre aptana

* Una revisión genérica de Aptana.
* Documentación sobre html, css, y javascript

Conclusiones

Me da la impresión de que la mayoría de opiniones favorables vienen de gente que lo uso en su día cuando no había opciones libres/gratuitas mejores. Además da la impresión de que el proyecto está muerto desde que lo compró Appcelerator.

Creo que el caso de uso más favorable para Aptana es que ya estés usando el IDE en el backend (ruby, php, python) y sólo toques ocasionalmente el cliente por lo que no te merece cambiar de entorno.