Mi Neurona Favorita

Analizando

Solucionar problema al actualizar de JOOReports a JODReports

leave a comment »

JODReports es un proyecto para generar documentos dinámicamente desde aplicaciones JAVA, usando plantillas en formato OpenDocument (por ejempo OpenOffice o LibreOffice). Hasta la versión 2.0 se llamaba JOOReports (nótese el cambio en la 3ª letra), y si te decides actualizar a una versión nueva, podrás encontrar que al generarse el documento, no se sustituyen los valores de los campos por los del Map usado al generarlo, sino que el documento generado es exactamente igual que la plantilla.

Esto ocurre porque en JOOReports, la antigua versión, para añadir un campo en tu plantilla bastaba con insertar un campo, ponerle un nombre y ya está. A partir de la versión 2.1, con JODReports, los campos de la plantilla se añaden de la siguiente forma:

  1. CONTROL + F2 (o Insertar > Campos > Otros…)
  2. En la pestaña “Funciones” seleccionar “Campo de entrada” y en el campo “Indicación” poner JOOScript.
  3. Al insertar, especificar el campo como ${campo}

¿Qué ocurre si ya tenemos multitud de plantillas sin que los campos cumplan con estas nuevas restricciones? Si usamos la versión 2.3 o superior de JODReports, tenemos una alternativa: establecer el parámetro de configuración process_jooscript_only a false. Lo haríamos así:

Map configurations = template.getConfigurations();
configurations.put("process_jooscript_only", Boolean.FALSE);

Más información aquí.

Anuncios

Written by Recacha

04 septiembre 2012 at 5:00

Publicado en Java

Tagged with

Organización y productividad: mi método (parte IV)

with one comment

Implementación del método

En artículos anteriores hemos visto qué es eso del método, qué requisitos debe cumplir, y por qué fases pasa. Algunos de los que se adentran en el mundo GTD, se pierden en la implementación del método. Desde mi punto de vista es un error muy común dejarnos llevar por la última herramienta online que te permite gestionar tareas (a lo Remember the Milk) o esa aplicación para el smartphone tan atractiva y que hace tantas cosas.

Mi implementación asume que se tiene un ordenador como herramienta principal de trabajo; si no es tu caso y lo quieres aplicar, tendrás que adaptarlo a tus necesidades. Suponiendo que se disponga de él, recomendaría que se olvidase en un principio de todas las aplicaciones que comenté antes, y se empezase con archivos de texto. Al menos en mi caso, tras probar muchos de los gestores de tareas más populares, he acabado siempre en el documento de texto. Me da esa agilidad que nunca llegué a tener con otras herramientas. En mi caso, uso lo siguiente:

  • Bandeja de entrada: inbox.txt + un espacio en la mesa del tamaño de un folio
  • Lista de tareas: tareas.txt
  • Lista en espera: en_espera.txt
  • Calendario: Google Calendar

Bandeja de entrada

Lo más importante es tenerla tan a mano como sea posible. El archivo inbox.txt es el primero que abro al encender el ordenador (de hecho lo programé para que se hiciese automáticamente junto con tareas.txt y en_espera.txt). Cuando me llega una tarea que hacer, lo apunto ahí sin más, al final de la lista, sin ningún orden. Una nueva línea para cada tarea, por insignificante que sea.

Por otro lado, la bandeja de entrada física estará destinada a los documentos, folletos, notas, libros, etc que nos lleguen. Si no tienes la típica caja de plástico, es suficiente con reservar un sitio en la mesa que solo servirá para poner ahí las cosas que te llegan.

Lista de tareas

Tiene el mismo formato que la bandeja de entrada: cada línea una tarea. En este caso el orden sí importa: suelo tener en primer lugar las que tengo que hacer antes, pero sin obsesionarme por ordenarlas, simplemente las importantes por arriba, el resto después.

Lista en espera

Nuevamente otro archivo de texto, en cada línea una tarea delegada e información básica sobre la misma si fuese relevante: fecha en que lo delegué, a quién lo delegué y qué medio usé para ello (email, teléfono, etc).

Calendario

Yo uso Google Calendar porque llevo años haciéndolo y su uso me resulta intuitivo y natural. Es muy potente, y se le puede sacar mucho partido, pero si eres de los de agenda de toda la vida, no hay necesidad de cambiarla. Solo hay que tener un calendario, del tipo que sea, siempre dispuesto para añadirle citas.

Y realmente no se necesita nada más, aunque es en muchos casos necesitaréis guardar un registro de lo que hacéis. En la próxima entrega hablaremos de eso, del Time Tracking.

Written by Recacha

02 septiembre 2012 at 5:00

Refactoring en Eclipse. (9) Self Encapsulate Field

with one comment

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Self Encapsulate Field

Para encapsular el acceso a un atributo de una clase hay que crear los métodos acceso y modificación (get y set) y sustituir cada uso que se haga del atributo por el correspondiente método. En Eclipse podemos hacerlo más rápidamente de la siguiente forma:

  1. Hacer click derecho sobre el atributo a encapsular, Refactor > Encapsulate Field…
  2. En el cuadro de diálogo, seleccionar “use setter and getter”. Eliminar el método set o usar el modificador de acceso a private para evitar su modificación.

Ejemplo antes de refactorizar:

public class Test {
  private int low, high;

  boolean includes(final int arg) {
    return arg >= low && arg <= high;
  }
}

Tras refactorizar, quedaría:

public class Test {
  private int low, high;

  boolean includes(final int arg) {
    return arg >= getLow() && arg <= getHigh();
  }
  
  private int getLow() {
    return low;
  }

  private int getHigh() {
    return high;
  }
}

Written by Recacha

30 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Refactoring en Eclipse. (8) Extract Class

with one comment

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Extract Class

Si tenemos una clase con demasiadas responsabilidades y queremos extraer algunas de ellas a una nueva clase, podemos extraerlas con ayuda de Eclipse. Lo haremos en 3 pasos, y en cada uno de ellos actuaremos según las necesidades de cada caso:

  1. Extraer atributos a una nueva clase
    1. En cualquier punto de la clase hacer click derecho > Refactor > Extract Class…
    2. En la ventana que aparece, le damos un nombre a la nueva clase, seleccionamos los atributos a extraer y nombraremos también la referencia que creará en la clase original del tipo de la nueva clase.
  2. Mover los métodos necesarios a la nueva clase, aplicando el refactoring “Extract Method”: SHIFT + ALT + V (o click derecho > Refactor > Move…)
  3. Eliminamos los getters y setters de los atributos movidos en el paso 1 de la clase original.

Ejemplo antes de refactorizar (sombreados los atributos y métodos que se van a mover a la nueva clase):

public class Person {
  private String _name;
  private String _officeAreaCode;
  private String _officeNumber;

  public String getTelephoneNumber() {
    return ("(" + _officeAreaCode + ") " + _officeNumber);
  }

  // GETTERS AND SETTERS

  public String getName() {
    return _name;
  }

  public String getOfficeAreaCode() {
    return _officeAreaCode;
  }

  public void setOfficeAreaCode(final String arg) {
    _officeAreaCode = arg;
  }

  public String getOfficeNumber() {
    return _officeNumber;
  }

  public void setOfficeNumber(final String arg) {
    _officeNumber = arg;
  }
}

Creamos la nueva clase TelephoneNumber con los atributos _officeAreaCode y _officeNumber (sombreados los cambios en la clase original):

public class Person {
  private String _name;
  private TelephoneNumber _telephoneNumber = new TelephoneNumber();

  public String getTelephoneNumber() {
    return ("(" + _telephoneNumber.get_officeAreaCode() + ") " + _telephoneNumber.get_officeNumber());
  }

  // GETTERS AND SETTERS

  public String getName() {
    return _name;
  }

  public String getOfficeAreaCode() {
    return _officeAreaCode;
  }

  public void setOfficeAreaCode(final String arg) {
    _officeAreaCode = arg;
  }

  public String getOfficeNumber() {
    return _officeNumber;
  }

  public void setOfficeNumber(final String arg) {
    _officeNumber = arg;
  }
}

public class TelephoneNumber {
  private String _officeAreaCode;
  private String _officeNumber;

  // GETTERS AND SETTERS

  public String get_officeAreaCode() {
    return _officeAreaCode;
  }

  public void set_officeAreaCode(final String _officeAreaCode) {
    this._officeAreaCode = _officeAreaCode;
  }

  public String get_officeNumber() {
    return _officeNumber;
  }

  public void set_officeNumber(final String _officeNumber) {
    this._officeNumber = _officeNumber;
  }
}

Por último movemos el método getTelephoneNumber() a la nueva clase y eliminamos de Person los getters y setters de los atributos movidos:

public class Person {
  private String _name;
  private TelephoneNumber _telephoneNumber = new TelephoneNumber();

  public String getTelephoneNumber() {
    return _telephoneNumber.getTelephoneNumber();
  }

  // GETTERS AND SETTERS

  public String getName() {
    return _name;
  }
}

public class TelephoneNumber {
  private String _officeAreaCode;
  private String _officeNumber;

  public String getTelephoneNumber() {
    return ("(" + get_officeAreaCode() + ") " + get_officeNumber());
  }

  // GETTERS AND SETTERS

  public String get_officeAreaCode() {
    return _officeAreaCode;
  }

  public void set_officeAreaCode(final String _officeAreaCode) {
    this._officeAreaCode = _officeAreaCode;
  }

  public String get_officeNumber() {
    return _officeNumber;
  }

  public void set_officeNumber(final String _officeNumber) {
    this._officeNumber = _officeNumber;
  }
}

Written by Recacha

28 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Función currval en Postgres

with one comment

Tenemos la siguiente situación: necesitamos hacer un script SQL para Postgres que inserte un valor en una determinada tabla, y para la PK hacemos uso de la función nextval sobre la secuencia. ¿Qué ocurre si a continuación necesitamos ese valor devuelto por la secuencia?

Pongamos un ejemplo práctico. Tenemos la clásica relación empleado – departamento:

department(id, name)
employee (id, name, id_department)

Necesitamos, mediante scripts, añadir un departamento y asignárselo al empleado llamado ‘John’. Además tenemos que hacer uso de la secuencia en el insert. Lo podríamos hacer de la siguiente forma:

INSERT INTO department VALUES (nextval('seq_department'), 'New department');
UPDATE employee SET id_department=currval('seq_department') WHERE name='John';

Written by Recacha

27 agosto 2012 at 17:00

Publicado en Base de datos

Tagged with

Refactoring en Eclipse. (7) Move Method

with 3 comments

Nota: Este post pertenece a una serie. Ver introducción e índice.

Refactoring: Move Method

Para aplicar esta refactorización en Eclipse, consistente en mover un método a una clase más apropiada, lo haremos en 2 pasos:

  1. Encapsular el acceso a los atributos de la clase que se usen en el método (usando get y set). Como veremos más adelante, se corresponde con el refactoring “Encapsulate Field”.
    1. Doble click sobre el atributo a encapsular.
    2. Click derecho > Refactor > Encapsulate Field…
    3. En la ventana, seleccionar el modificador de acceso más adecuado para el get y set, según dónde se encuentre la clase a la que se moverá el método.
  2. Mover el método
    1. Doble click en el nombre del método a mover.
    2. SHIFT + ALT + V (o click derecho > Refactor > Move…)
    3. Si se desea dejar el método original delegando en el nuevo, marcar el check “Keep original method as delegate…”. Eclipse cambiará el modificador de acceso del método si fuese necesario.

Ejemplo antes de refactorizar (sombreados los atributos que se van a encapsular en el primer paso):

public class Account {
  private AccountType _type;
  private int _daysOverdrawn;

  double overdraftCharge() {
    if (_type.isPremium()) {
      double result = 10;
      if (_daysOverdrawn > 7) {
        result += (_daysOverdrawn - 7) * 0.85;
      }
      return result;
    } else {
      return _daysOverdrawn * 1.75;
    }
  }

  double bankCharge() {
    double result = 4.5;
    if (_daysOverdrawn > 0) {
      result += overdraftCharge();
    }
    return result;
  }
}

Tras encapsular los atributos _type y _daysOverdrawn:

public class Account {
  private AccountType _type;
  private int _daysOverdrawn;

  double overdraftCharge() {
    if (get_type().isPremium()) {
      double result = 10;
      if (get_daysOverdrawn() > 7) {
        result += (get_daysOverdrawn() - 7) * 0.85;
      }
      return result;
    } else {
      return get_daysOverdrawn() * 1.75;
    }
  }

  double bankCharge() {
    double result = 4.5;
    if (get_daysOverdrawn() > 0) {
      result += overdraftCharge();
    }
    return result;
  }

  public AccountType get_type() {
    return _type;
  }

  public void set_type(AccountType _type) {
    this._type = _type;
  }

  public int get_daysOverdrawn() {
    return _daysOverdrawn;
  }

  public void set_daysOverdrawn(int _daysOverdrawn) {
    this._daysOverdrawn = _daysOverdrawn;
  }
}

Por último movemos el método overdraftCharge() a la clase AccountType:

public class Account {
  private AccountType _type;
  private int _daysOverdrawn;

  double bankCharge() {
    double result = 4.5;
    if (get_daysOverdrawn() > 0) {
      result += overdraftCharge();
    }
    return result;
  }

  public AccountType get_type() {
    return _type;
  }

  public void set_type(AccountType _type) {
    this._type = _type;
  }

  public int get_daysOverdrawn() {
    return _daysOverdrawn;
  }

  public void set_daysOverdrawn(int _daysOverdrawn) {
    this._daysOverdrawn = _daysOverdrawn;
  }
}

public class AccountType {
  [...]
  double overdraftCharge() {
    if (get_type().isPremium()) {
      double result = 10;
      if (get_daysOverdrawn() > 7) {
        result += (get_daysOverdrawn() - 7) * 0.85;
      }
      return result;
    } else {
      return get_daysOverdrawn() * 1.75;
    }
  }
}

Written by Recacha

26 agosto 2012 at 7:00

Publicado en Refactoring

Tagged with , ,

Organización y productividad: mi método (parte III)

with 2 comments

Las 3 Fases

A los conocedores del método GTD, las 3 fases que sigo en mi sistema de organización les resultarán familiares.

Fase 1: Recopilar

Como no queremos que ninguna tarea pendiente esté en nuestra cabeza, cualquiera que sea la forma en que nos lleguen las nuevas cosas que hacer, debemos tener un sitio donde soltarlo inmediatamente, olvidarnos, y seguir con lo que estuviésemos haciendo. Es la bandeja de entrada. De momento hablaré de la bandeja de entrada como concepto, más adelante me centraré en la implementación.

Los medios más frecuentes para que nos lleguen tareas son el teléfono, el correo electrónico, correo postal, oído en una reunión u otro lugar, o en la herramienta de gestión de tareas corporativa (si existe y se usa, claro).

Fase 2: Procesar

La bandeja de entrada es un sitio temporal donde están todas las cosas que tenemos que hacer, pero no es nuestra lista de tareas propiamente dicha. Periódicamente hay que procesar la bandeja de entrada. La naturaleza de nuestro trabajo y el sentido común nos ayudarán a decidir cada cuánto tiempo se procesa. Yo intento procesar después de una tarea larga, y como poco, una vez al día.

Procesar la bandeja de entrada no es más que ir recorriendo cada elemento de la lista (sin saltarse ninguno) y realizarse las siguientes preguntas, que conllevan cada una a su respectiva acción:

  • ¿Tardaré menos de 2 minutos? Hacerlo ya.
    Si es una tarea que con toda seguridad nos llevará a lo sumo 2 minutos resolverla, la haremos inmediatamente. No merece la pena que forme parte de mi lista de cosas por hacer algo que me puedo quitar tan rápidamente de encima.
  • ¿Es material de consulta? Archivarlo.
    Si es un documento, un folleto, un libro o cualquier cosa que necesitarás consultar en un momento indeterminado del futuro, archívalo. Sobre formas eficiente de archivar (y me refiero a ficheros físicos y digitales) podéis encontrar información en el propio libro de David Allen, pero no profundizaré más por el momento.
  • ¿Es un evento con fecha determinada? Cita en el calendario.
    Reuniones, llamadas telefónicas a una determinada hora, recordatorios futuros, y en general, cualquier cosa que no se pueda hacer ahora mismo, sino que deba esperar a un momento concreto, se incluirá en nuestro calendario.
  • ¿Es una tarea que deba delegar? Delegar y añadir a la lista “En espera“.
    Si delegarla no me lleva más de dos minutos, la delegamos ya y lo anotamos en una lista de tareas delegadas, que en adelante llamaremos “En espera”. Sobre el arte de delegar también daría para una serie de artículos, por lo que tampoco se profundizará más.
  • ¿Ninguna de las anteriores? Es una tarea pendiente, por lo que se incluye en la lista “Tareas

Fase 3: Hacer

Por último, la mayoría del tiempo realmente estaremos llevando a cabo una tarea de nuestra lista. Aquí surge la pregunta: ¿qué tarea hago primero de mi lista? ¿Uso un sistema de prioridades? ¿Las clasifico por importantes, urgentes, etc? Yo simplemente uso el sentido común, la experiencia y el instinto en cada situación para elegir qué debo hacer en primer lugar. Si algo es importante y/o urgente, lo coloco en los primeros puestos de la lista. Cuando debo comenzar una nueva tarea, echo un vistazo y determino cual será la siguiente. He probado multitud de sistemas para priorizar, ordenar, etc, y ninguno me dio resultado. A veces la mejor tarea a realizar depende del momento del día y del tiempo que tengas para hacerla, sin más.

Conclusión

Como se ve, he simplificado al máximo el procedimiento a seguir en cada caso, y por ello quizá haya personas que necesiten fases intermedias, incrementar la frecuencia de procesado, o tener en cuenta otros factores durante el procesado. Ya queda en manos de cada cual adaptarlo a sus necesidades.

En este artículo hemos hablado de la bandeja de entrada, del calendario, de las listas de espera y la de tareas, pero ¿a qué me refiero exactamente con cada una de ellas? Veremos en el siguiente artículo cómo implemento yo cada uno de ellos.

Written by Recacha

26 agosto 2012 at 1:00