Weblogs Código

Blog Bitix

Cómo implementar correctamente y por qué los métodos equals y hashCode de los objetos Java

December 07, 2016 01:00 PM

Los métodos equals y hashCode son esenciales en las colecciones de objetos. Para su correcta implementación es necesario conocer unas cuantas propiedades que han de cumplir estos métodos. Pueden parecer sencillos pero no lo son tanto y una mala implementación posiblemente produzca algún tipo de error o comportamiento anómalo indeseado. En el siguiente artículo comento varias formas de implementarlos de forma sencilla y correcta.

Java

En Java los métodos equals y hashCode están definidos en la raíz de la jerarquía de clases, esto es en la clase Object, lo que significa que todas las instancias de objetos los poseen. Estos métodos son especialmente importantes ya que afectan al correcto funcionamiento de las colecciones como Collection, List, Set y Map, colecciones, listas, conjuntos y mapas que es difícil que cualquier programa no use alguna implementación de ellas.

El método equals es usado en las colecciones de tipo List, Set, y también Map para determinar si un objeto ya está incluida en la colección, el método hashCode es usado en los Map para encontrar el objeto asociado a la clave. Dado que las colecciones son ampliamente usadas en cualquier programa la correcta implementación implementación de los métodos equals y hashCode es fundamental ya que de lo contrario descubriremos errores poco agradables.

Una de las cosas que tenemos que tener cuenta es que siempre que sobreescribamos el método equals también debemos sobreescribir el método hashCode. Según el contrato definido en la clase Object deberemos saber que:

  • Durante la ejecución del programa el método hashCode debe retornar el mismo valor siempre que no se modifique la información usada en el método equals.
  • Si dos objetos son iguales según sus métodos equals entonces el valor devuelto por hashCode en cada uno de los dos objetos debe devolver el mismo valor.
  • Si dos objetos son distintos según sus métodos equals el valor devuelto no ha de ser necesariamente distinto aunque se recomienda para mejorar el rendimiento de las colecciones Map.

Cómo implementar el método equals

Según la especificación del método equals definido en la clase Object debe tener las siguientes propiedades:

  • Es reflexiva: para cualquier referencia no nula de x, x.equals(x) debe retornar true.
  • Es simétrica: para cualquier referencia no nula de x e y, x.equals(y) debe retornar true si y solo si y.equals(x) retorna true.
  • Es transitiva: para cualquier referencia no nula de x, y y z, si x.equals(y) debe retorna true y y.equals(z) retorna true entonces x.equals(z) debe retornar true.
  • Es consistente: para cualquier referencia no nula de x e y, múltiples invocaciones de x.equals(y) consistentemente debe retornar true o false, si no se ha modificado la información utilizada en la comparación.
  • Para para cualquier referencia no nula de x, x.equals(null) debe retornar false.

La implementación del método equals de la clase Object usa la equivalencia más restrictiva posible, esto es, para cualquier referencia no nula de x e y este método retorna true si y solo si son el mismo objeto (x == y tienen la misma referencia).

Según estas reglas una implementación del método equals tiene la siguiente forma:

Usando la clase EqualsBuilder de la librería commons-lang la implementación es aparentemente similar pero en el caso de necesitar hacer comparaciones con datos de tipo float, double, arrays u objetos hace la implementación un poco más sencilla. En los float y double para hacer la comparación deberíamos usar los métodos Float.compare y Double.commpare y en los objetos deberemos tener en cuenta si la referencia es posible que se a nula para evitar la excepción NullPinterException cosas que la clase EqualsBuilder ya tiene en cuenta.

Como implementar el método hashCode

La implementación del método hashCode se debe realizar según los siguientes pasos:

  • Almacenar un valor constante distinto de 0 en una variable int, por ejemplo 17.
  • Por cada campo usado en el método equals se debe obtener un hash code (int) realizando:
    • Si el campo es un boolean se debe calcular (f ? 1 : 0).
    • Si el campo es un byte, char, short o int se debe calcular (int) f.
    • Si el campo es un long se debe calcular (int) (f ^ (f >>> 32)).
    • Si el campo es un float se debe calcular Float.floatToIntBits(f).
    • Si el campo es un double se debe calcular Double.doubleToLongBits(f) y calcular el hash del long obtenido en el paso para los tipos long.
    • Si el campo es una referencia a un objeto y el método equals de esta clase compara recursivamente invocando el método equals del campo, invocar su método hashCode. si el valor de campo es nulo se debe retornar una constante que tradicionalmente es 0.
    • Si el campo es un array se debe tratar individualmente cada elemento aplicando estas reglas a cada elemento. Si cada elemento del array es significativo se puede usar Arrays.hashCode.
    • Combinar los hash code obtenidos de la siguiente forma, result = 31 * result + c.

Implementar este método en cada clase de una aplicación es tedioso, repetitivo y propenso a errores, para hacer más sencilla su implementación existe el método Objects.hash desde la versión 7 de Java. Si usamos una versión anterior a Java 7 disponemos de la clase HashCodeBuilder en la librería commons-lang. La misma implementación anterior quedaría.

En el libro Effective Java se explican con un poco más detalle estas dos cosas y muchas otras otras sobre Java que son muy interesantes conocer, el libro es una buena y recomendada lectura para todo programador Java que está entre los 8+ libros para mejorar como programadores que recomiendo.

» Leer más, comentarios, etc...

Navegapolis

¿Comprarías una casa si te obligaran a firmar un proyecto con las dimensiones y todos los detalles cerrados?

December 06, 2016 05:49 PM

bricks"¿Te comprarías una casa nueva en construcción sin haber visto los planos? Seguramente la respuesta es no. De hecho, seguro que al vendedor le exiges que te muestre los planos a escala de lo que va a ser tu nueva vivienda"... "Sin embargo, hasta hace poco la situación con las aplicaciones software no era así. Aunque en algunos casos la inversión en un sistema software podía ser superior al precio de una vivienda, a los ingenieros de software no se nos exigía que entregásemos los planos de la aplicación antes de empezar a construirla."

Esta cita es de un artículo publicado el pasado 21 de noviembre en País Digital. Una muestra de que en 2016 la Ingeniería del Software continúa insistiendo en aplicar a la programación el mismo modelo de adquisición y suministro que el usado en otras ingenierías.

Pero no nos engañemos, queremos tener los planos completos desde el principio y saber cómo va a ser toda la casa, porque es algo que nos van a entregar en una sola vez, cuando esté completamente terminada y que luego no podremos modificar.

Si las casas no fueran estructuras físicas de cemento, sino lógicas, el razonamiento sería algo así:

¿Comprarías una casa si te obligaran a firmar un proyecto con las dimensiones y todos los detalles cerrados, como si fuera un contrato del que no pudieras cambiar nada. Y que si luego vieras que el comedor resulta pequeño no pudieras ampliar por el muro exterior quitando un poco de jardín, o incluso si necesitaras más, pudieras hacer una bodega?
¿Comprarías una casa si te dijeran que no te la van a entregar hasta estar toda terminada? Que no te van a dar primero el dormitorio y el baño para que puedas tener cuanto antes un mínimo viable y luego mes a mes te irán entregando o modificando las partes que tú quieras hasta que decidas que ya está terminada.

Falacia: argumento que parece válido, pero no lo es. Algunas falacias se cometen intencionalmente para persuadir o manipular a los demás, mientras que otras se cometen sin intención debido a descuidos o ignorancia. En ocasiones las falacias pueden ser muy sutiles y persuasivas, por lo que se debe poner mucha atención para detectarlas.

(Wikipedia, Falacia, dic 2016.)

 

» Leer más, comentarios, etc...

Adrianistán

Nace el foro Gamedev Hispano

December 05, 2016 04:59 PM

Hoy tengo el placer de anunciar la inauguración del foro Gamedev Hispano.

Se trata de un punto de encuentro para preguntar, debatir y descubrir sobre desarrollo de juegos en la lengua de Cervantes. Inicialmente enfocado al desarrollo de juegos HTML5 (Phaser y Babylon), el foro huye de ser “otro más” de Unity/Unreal y se centra en un desarrollo de juegos quizá para algunos más artesanal.

screenshot-gamedevhispano-com-2016-12-05-15-00-18

Aunque Phaser y Babylon hayan sido los frameworks elegidos para el foro, nadie está excluido. Existen subforos de SDL, Ogre3D, PyGame, libGDX y Godot y foros de temática general como ¡Enseña tu juego! y Multimedia.

Os animo a todos a registraros en el foro y a crear un hilo. Que la gente participe y colabore para ayudarse mutuamente.

Gamedev Hispano

La entrada Nace el foro Gamedev Hispano aparece primero en Blog - Adrianistan.eu.

» Leer más, comentarios, etc...

Poesía Binaria

Operador coma. Cómo incorporarlo a nuestro día a día con muchos ejemplos en C

December 05, 2016 09:09 AM

photo-1477413114673-6708cad13418
Seguro que lo has visto cientos de veces por ahí, pasando desapercibido en multitud de programas hechos en C. Es más, incluso el primer día que empezaste a ver programación os visteis las caras y casi no te diste cuenta. Incluso puede que lo hayas utilizado sin siquiera ser consciente de lo que hace en realidad.

Otros muchos sí que sabréis de qué va este operador, y me gustaría que los que sí sabéis de qué va, sugirierais más ejemplos en los comentarios.

Para situarnos

Seguramente hayas utilizado la coma en varias situaciones como por ejemplo la creación de variables del mismo tipo:

1
2
3
4
5
int main ()
{
  int a=2, b=1, c, d, e=4;
  int f, g, h=f=g=2;
}

O en declaraciones y llamadas a funciones:

1
2
3
4
5
6
7
8
9
10
11
int funcion(int a, int b)
{
  ...
}

int main()
{
  int a=2, b=3;
  funcion(a, b);
  return 0;
}

Pero este símbolo tiene muchos más usos en C, C++ y otros lenguajes derivados (Java, Perl o Javascript, por ejemplo) en los que podemos utilizarlo como algo más que un simple separador y con el que podemos ahorrar muchas líneas de código.

Para probar estos programas

Si queréis probar todos los ejemplos que muestro en el post, no tenéis más que copiar y pegar en vuestro editor favorito y compilar con vuestro compilador preferido. Yo utilizo GCC (no hace falta ninguna biblioteca ni nada):

gcc -o compilado fuente.c

¿ Para qué vale el operador coma ?

Este operador se utiliza generalmente para evaluar varias expresiones dentro de la misma línea de código. Es, además, el operador con menor preferencia de todos. Esto último quiere decir que asignaciones, operaciones matemáticas, lógicas, direccionamiento, ternarios, etc; se ejecutarán antes que la coma y esto nos puede llevar a pensar que no funciona bien, pero tiene su lógica. Además, una vez que hemos ejecutado todas las expresiones que están separadas por coma de izquierda a derecha, devolveremos como resultado el valor de la última (la que más a la derecha estará).

1
2
3
4
int main()
{
   expresión1, expresión2, expresión3;
}

Como todos los elementos de un lenguaje, pueden ser utilizados con buenos o males fines. Por un lado, podemos hacer un código muy críptico con este operador, y hacer que el próximo que se siente a analizar nuestro código lo pase mal para entender qué estamos haciendo, y todo para ahorrar unas cuántas líneas de código. Aunque también puede utilizarse con buenos fines, y hacer que todo se entienda mucho mejor.

Como consejo para beneficiarnos en la legibilidad y el mantenimiento del código, debemos utilizar el operador coma para ejecutar expresiones que estén relacionadas, incluso que para ejecutar las expresiones de la derecha sea necesario que las de la izquierda se hayan ejecutado antes, ya que si vamos a ejecutar cosas que no tienen nada que ver, es mejor separarlas con punto y coma (;) y ponerlas en otra línea, por el bien de los que vayan a leer nuestro código en el futuro.

Aunque la mejor forma de conocer el funcionamiento es este operador es viendo ejemplos y jugando con ellos. Así que vamos a ver una buena selección de ejemplos para empezar a poner en práctica ya. He de decir que la coma siempre hace lo mismo, todos estos son diferentes escenarios donde podemos hacerlo, no estamos inventando nada en cada uno de los ejemplos.

La coma en asignaciones

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main()
{
  int a;
  a = 1, 2, 3, 4;
  printf ("a = %d\n", a);
  return 0;
}

Este código puede parecer (y de hecho lo es) una tontería y no sirve para nada. Pero nos ayuda a comprender la preferencia de los operadores. En realidad, si hacemos un programa y ponemos un 7;, éste compilará bien, aunque será cosa del compilador ignorar lo que hemos hecho, ya que no estamos haciendo nada con ese valor. En realidad, en este código estamos evaluando las expresiones:

  • a = 1
  • 2
  • 3
  • 4

Por lo que el resultado será:

a = 1

¿No dije yo antes que el valor devuelto era el de la derecha? Y, ¿el de la derecha no es el 4? Sí, pero si vemos las expresiones, la primera es a=1, por lo que se realiza dicha asignación. Sería distinto decir lo siguiente:

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main()
{
  int a;
  a = (1, 2, 3, 4);
  printf ("a = %d\n", a);
  return 0;
}

Esto sí que devolverá 4

Modificando los valores dentro de la igualación

Podemos intentar cosas como:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main()
{
    int a=3, b=4;
    int c=(a*=a, b*=b, a+b);

    printf ("a=%d\nb=%d\nc=%d\n", a, b, c);
    return 0;
}

Es decir, aqui, hemos cogido a y la hemos multiplicado por sí misma, b también, y luego en c hemos metido a y b (que ahora son los cuadrados de los originales). Como resultado, hemos modificado las tres variables.

Intercambiando valores en una sola línea

Tenemos dos valores (a y b) y queremos que b sea a y a sea b. (Podemos ver algunas técnicas aquí). Aunque esto podemos resumirlo en una línea de esta manera:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main()
{
    int temp;
    int a=33, b=22;

    a=(temp=a,b),b=temp;

    printf ("a = %d\nb = %d\n", a, b);
}

Necesitaríamos una variable temporal, declarada (temp), pero lo demás sería ejecutar las expresiones:

  • temp = a
  • a=b
  • b=temp

En un orden determinado y con una preferencia determinada.

Un ejemplo para explotarnos la cabeza

Veamos ahora:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main()
{
    int a=1;
    int b=(a++, a++, a++);

    printf ("a=%d\nb=%d\n", a, b);
    return 0;
}

¿Cuánto debe valer a y b? La lógica nos diría que a y b valen lo mismo, 4. Pero no es así. A termina valiendo 4, es cierto, porque inicialmente vale 1 y lo incrementamos 3 veces (1 + 1 + 1 + 1 = 4), bien. Pero ¿b? En realidad, las expresiones se evalúan todas, pero a++ en realidad es un post-incremento, esto es, que primero devolverá el valor y luego incrementará, por lo que antes del tercer incremento a vale 4 y es lo que llega a b. Después de esto se incrementará.

Operación pop_first() en listas enlazadas

Una de las posibles operaciones es la extracción del primer elemento de la lista. Es decir, devolvemos el valor del primer elemento y lo quitamos al mismo tiempo de la lista. Imaginemos que nuestra lista está formada por (TNodo)s y éstos tienen un TDato (que podrá ser un entero, una cadena, un struct, etc):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct TNodo
{
  TDato dato;
  struct TNodo* sig;
}

TDato pop_first(TLista** lista)
{
  TDato dato;
  TLista _lista = *lista;
  TNodo sig = _lista->sig;

// Aquí a dato le asignamos el dato que hay actualmente en la lista, luego liberamos la lista y apuntamos lista al siguiente nodo.
  dato = _lista->dato, free(*lista), *lista=sig;
  return dato;
}

Cálculo de salarios

Imaginémonos que vamos a calcular el salario de un empleado. Éste es el salario base + 0.1 * años de antigüedad * salario base + bonificación. Eso sí, cada una de las variables (salario base, antigüedad y bonificación debe obtenerse con llamadas a varias funciones), podríamos hacer lo siguiente:

1
2
3
4
5
6
int main()
{
  double base, bonificacion;
  unsigned years;
  double salario = (base = get_salario_base(), years=get_antiguedad(), bonificacion = get_bonificacion(), base + base*years*0.1 + bonificacion);
}

Otro ejemplo curioso más

#include

int main()
{
int i, j;

j = 10;
i = (j++, j+100, 999+j);

printf (“i=%d\nj=%d\n”, i, j);
return 0;
}
¿ Y el resultado ?

i=1010
j=11

Esto es así porque el j++ se ejecuta (por lo que j vale 11 ya. La segunta expresión j+100 no hace nada, se ejecuta, pero no se guarda en ningún lado (seguramente un compilador listo la ignore), la última expresión 999+j será la que de verdad se guarde en i, por tanto i=999+11 = 1010.

Resolviendo una ecuación de segundo grado

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <math.h>

int main()
{
  double a = 1;
  double b = -5;
  double c = 6;
  ddouble sq, x1, x2;

  x1 = (sq = sqrt(b*b-4*a*c), a=a*2, (-b+sq)/a);
  x2 = (-b-sq)/a;

  printf ("x1 = %lf\n", x1);
  printf ("x2 = %lf\n", x2);
  return 0;
}

En este código vemos cómo para calcular la primera solución, evaluamos varias expresiones seguidas:

  • sq = sqrt(b*b-4*a*c)
  • a=a*2
  • (-b+sq)/a

Y a la variable x1 le asignamos este último valor. En este caso, vemos que las tres expresiones deben ejecutarse en este orden ya que hay dependencias de unas sobre otras. Si cambiamos el orden puede ser fatal y no se ejecutará bien nuestro código.
Para compilar esto, se debe incluir la biblioteca matemática (en gcc es utilizando -lm).

Inicializando estructuras

Este ejemplo está pensado como algo más complejo. Imaginemos que hemos creado una lista enlazada, o una lectura desde archivo (primero tenemos que abrir el archivo antes de leer). Es decir, antes de poder obtener el valor, tenemos que llamar a una función:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int estructura = 20;

void inicializa(int **a)
{
    /* Aquí iría un malloc(), metemos datos en la estructura, etc */
    *a = &estructura;
}

int main()
{
    int *a = NULL;

    int valor = (inicializa(&a), *a);

    printf ("valor = %d\n", valor);
  return 0;
}

Es más, fijaos que inicializa() es de tipo void y no devuelve ningún valor. El compilador podía quejarse al querer dar ese valor a una variable de tipo entero, pero como en realidad el valor que se le da es el de *a, no hay ningún problema.

O con ficheros:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main()
{
    FILE *f;
    int valor;
    int ok = (f = fopen("valor.txt", "r"), fscanf(f, "%d", &valor), fclose(f));
   
    printf ("valor = %d\n", valor);
  return 0;
}

Hay que tener en cuenta que esto son sólo ejemplos, en la práctica puede que todo no sea tan fantástico y debamos hacer comprobaciones de error. Por ejemplo, en el ejemplo anterior (de ficheros), sería más conveniente utilizar && en lugar de , así cuando falla la expresión de más a la izquierda, no se ejecutan las siguientes.

Comas dentro de un bucle for

Muchos de los que empiezan a programar en C, separan las expresiones del bucle for con comas, cuando en realidad es con punto y coma. Es decir:

1
2
3
4
for (inicialización ; finalización ; seguimiento)
{
  ...
}

Pero utilizar comas aquí tiene utilidades bien distintas, por ejemplo cuando intervienen varias variables en el bucle, cuando debemos inicializar dos variables, en lugar de inicializar una variable y luego hacer el for, podemos hacer:

1
2
3
4
5
  int i, j;
  for (i=0, j=0 ; i< 10; ++i)
  {
     ...
  }

Para complicar esto, podemos contar 20 con dos variables, una desde 0 a 19 y otra desde 19 hasta 0:

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main()
{
    int i, j, total=20;

    for (j=total-1, i=0; i<total; ++i, --j)
        printf ("i = %d - j = %d\n", i, j);

  return 0;
}

Comas dentro de un bucle while

Vamos, con otro pequeño ejemplo. Un típico ejercicio de adivinar un número:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    srand(time(NULL));
    int numero=1+rand()%10;
    int input=0;

    while (input!=numero)
        {
            printf ("Introduce un número: ");
            scanf("%d", &input);
        }

    printf("Has acertado!\n");
  return 0;
}

Que podemos escribir de la siguiente forma:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
  int numero=(srand(time(NULL)), rand()%10), input=0;

  while (printf ("Introduce un número: "), scanf("%d", &input), input!=numero);

  printf("Has acertado!\n");
  return 0;
}

En este caso, dentro del while, hemos incluido varias expresiones:

  • printf (“Introduce un número: “)
  • scanf(“%d”, &input)
  • input!=numero

Siendo la última de éstas la que en realidad sirve como condición del while.

Leyendo un archivo (Unix)

Una lectura de fichero utilizando la biblioteca (unistd), podemos escribirla así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int f;
    char c;
    int ok;
    f = open("coma.c", O_RDONLY);
    while ((ok = read(f, &c, 1))>0)
        printf ("%c", c);
   
  return 0;
}

Aunque podemos escribirla también así, utilizando el operador coma:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int f;
    char c;
    int ok;
    f = open("coma.c", O_RDONLY);
    while (ok = read(f, &c, 1), ok>0)
        printf ("%c", c);
   
  return 0;
}

Pero, por ejemplo, si queremos que el bucle pare cuando encontremos un carácter punto y coma ‘;’, podemos hacer esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int f;
    char c;
    int ok;
    f = open("coma.c", O_RDONLY);
    while (ok = read(f, &c, 1), ok>0 && c!=';')
        printf ("%c", c);
   
  return 0;
}

Comas en condicionales

En este caso, estaremos evaluando alguna expresión o ejecutando una función por ejemplo, antes de preguntar por la condición. Por ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <stdlib.h>

int pregunta_edad()
{
    int res = 0;

    while (printf ("¿Cuántos años tienes? "),
                 scanf("%d", &res),
                 res<1)
        {
            if (res<1)
                printf ("No me mientas!!\n");
        }
   
    return res;
}

int main()
{
    int edad;

    if (edad=pregunta_edad(), edad<18)
        printf ("Espera %d años antes de volver\n", 18-edad);
    else if (edad==18)
        printf ("Perfecto, tienes 18\n");
    else
        printf ("Sabes que podias haber entrado hace %d años?\n", edad-18);
  return 0;
}

Aunque es verdad que el condicional también podía haberse expresado como:

1
  if ((edad=pregunta_edad())<18)

evitando así repetir la variable. Aunque con la coma podríamos incluir más expresiones para ejecutar, incluyendo operaciones y varias asignaciones:

1
  if (precio = calcula_coste_pedido(&pedido), financiacion = calcula_financiacion(precio, usuario), financiacion.ok)

En este ejemplo, podemos ver cómo evaluar si el usuario de una tienda online puede optar por financiación de su pedido. Para ello, utilizamos la función calcula_coste_pedido, a la que le pasamos un struct (por ejemplo) con información del pedido y calcula su precio total. Luego la variable financiacion (que es otro struct) se rellenará con datos gracias a calcula_financiacion() a la que le pasamos el precio y el usuario (nuestra tienda ofrece condiciones especiales a ciertos usuarios) y luego devolvemos financiacion.ok (un campo de nuestro struct).

Dentro de un return

Utilizar este operador dentro de un return es de los usos más comunes, y es que muchas veces, antes de salir de una función debemos realizar pequeñas tareas, llamar a otras funciones, liberar memoria y cosas del estilo.
En este ejemplo, vamos a utilizar strtok(), una función conocida por arruinar las cadenas originales que le pasamos, es decir, cuando utilizamos strtok() la cadena original se modifica. Por tanto, si queremos que ésta no cambie, debemos hacer una copia y aplicar strtok() a la cadena copiada, luego podremos hacer lo que queramos con ella:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int cuenta_palabras(char* cadena)
{
   const char s[2] = " ";
   char *token;
     char *copia=(char*)malloc(strlen(cadena)+1);
     strcpy(copia, cadena);
     
     int tokens=0;
   token = strtok(copia, s);
   
   while( token != NULL )
   {
         tokens++;    
         token = strtok(NULL, s);
   }
     
     return free(copia), tokens;
}

int main()
{
   char str[] = "Poesía Binaria. http://totaki.com/poesiabinaria Aprendiendo a utilizar el operador coma.";
     printf ("Cuenta palabras: %d\n", cuenta_palabras(str));

     printf ("Str: %s\n", str);
   return 0;
}

Como vemos, en el mismo return de la función cuenta_palabras(), hacemos free(copia) para liberar memoria de la cadena copiada y luego devolvemos tokens. Podíamos hacerlo en dos líneas, pero lo hacemos en una. Es más free() es void.

Para evitar tener que abrir bloques

Esto es más pereza que otra cosa. Mientras en varios manuales de estilo (depende de las aplicaciones o del grupo que vaya a programar) se recomienda abrir y cerrar llaves siempre que estemos ante un bloque aunque sólo sea de una línea (cosa que en C es opcional), otros prefieren no usar llaves si no es necesario para así evitar que el número de líneas crezca.
Aunque hay veces que vamos a realizar acciones comunes, y podemos pensar que son un poco tontas, como por ejemplo mostrar un mensaje de error en pantalla y devolver un código (de error):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int analiza_datos(int a, int b)
{
    if (a==b)
        return printf("Son iguales\n"), 0;
    else if (a<b)
        return printf("a<b\n"), 1;
    else
        return printf ("a>b\n"), 2;
}

int main()
{
    printf ("=%d\n", analiza_datos(1, 2));
    printf ("=%d\n", analiza_datos(2, 2));
    printf ("=%d\n",analiza_datos(2, 1));
    return 0;
}

Si miramos la función analiza_datos(), vemos que en lugar de abrir llaves y poner un printf() y return x lo ponemos todo en la misma línea.

Llamadas a funciones

Bueno, llegamos a un punto peliagudo, porque tal vez tomemos las cosas muy a la ligera en ocasiones. Tenemos que tener especial cuidado en este punto, cuando toque pasar valores a funciones y queramos meter el operador coma para modificar ciertos valores. Lo que está claro es que cuando vayamos a utilizar el operador, debemos poner las expresiones entre paréntesis , porque de otro modo la coma actuará como separador. Por ejemplo si tengo esta función:

1
2
3
4
int funcion(int a, int b)
{
    printf ("a = %d\nb = %d\n", a, b);
}

No puedo hacer lo siguiente cuando vaya a llamarla:

1
funcion(a, b+=3, b);

Porque estaré diciendo que hay tres argumentos, y la función sólo admite dos.

Lo que sí podemos hacer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int funcion(int a, int b)
{
    printf ("a = %d\nb = %d\n", a, b);
}

int main()
{
    int a=3;
    int b=2;
    funcion (a, (b+=a, b));
    printf ("a en main = %d\n", a);
    printf ("b en main = %d\n", b);
}

En este caso:

a = 3
b = 5
a en main = 3
b en main = 5

Si hemos estado atentos no habrá sido muy difícil intuir el resultado.

Cuidado con este caso!!

Aunque, ¿qué pasaría si utilizo a en todos los valores?

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int funcion(int a, int b)
{
    printf ("a = %d\nb = %d\n", a, b);
}

int main()
{
    int a=3;

    funcion (a, (a+=3, a));
    printf ("a en main = %d\n", a);
}

Podemos pensar que se llamará a la función con los valores 3 y 6, pero depende del compilador, porque los dos argumentos, al fin y al cabo son a. Si el compilador, a medida que va haciendo las operaciones va recopilando los argumentos, sí sucederá así, se llamará a la función con 3 y 6. Pero si por el contrario primero se hacen las operaciones, y luego se van enviando los resultados como los diferentes argumentos, terminaremos enviando dos 6, ya que primero se hace el a+=3 y luego se llama a mi_funcion(a, a). Es cierto que la coma tiene la menor preferencia posible, pero cuando encontramos la coma (separadora de argumentos) normalmente estaremos hablando de cosas distintas, por lo que contarían como instrucciones aparte y en cierto modo se reinician las preferencias.

¿Se te ocurren más ejemplos?

Si tienes más ejemplos, o alguna cuestión relacionada, ¡no dudes en poner un comentario!

Foto: Providence Doucet

The post Operador coma. Cómo incorporarlo a nuestro día a día con muchos ejemplos en C appeared first on Poesía Binaria.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 260

December 05, 2016 07:55 AM

Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET

ASP.NET

.NET Core / ASP.NET Core

Azure / Cloud

Conceptos/Patrones/Buenas prácticas

Data

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Cross-platform

Otros

Publicado en Variable not found

» Leer más, comentarios, etc...

Koalite

Los Patrones de Diseño Hoy: Patrones Creacionales

December 05, 2016 05:06 AM

Todo desarrollador que se precie debería conocer los patrones de diseño, y especialmente los clásicos de la GoF. Aunque vivieron su momento de hype, siguen siendo útiles a la hora de desarrollar, sobre todo porque facilitan mucho la comunicación entre desarrolladores al poder estandarizar el nombre las cosas.

Teniendo en cuenta que el libro que originó todo esto es de 1994 y que en estos últimos 22 años los lenguajes y estilos de programación han tenido su evolución, he pensado que podría ser entrenido ver qué tal ha aguantado el paso del tiempo cada patrón de los 23 que aparecían en el catálogo original. Como son unos cuantos, voy a dividirlo en 3 posts, siguiendo las categorías que aparecen en el propio libro: patrones creacionales, patrones estructurales y patrones de comportamiento.

Todo esto es bastante personal y depende mucho del estilo de programación de cada uno y de los lenguajes que utilice, así que no te lo tomes como algo excesivamente serio. De hecho, en este post hay un claro sesgo hacia lenguajes orientados a objetos porque, como todos sabéis, en programación funcional todos los problemas de diseño se solucionan con funciones ;-)

No voy a entrar en detalle a describir cada patrón porque para eso ya hay miles de páginas en internet. Si no los conoces, te recomiendo que hagas una búsqueda rápida porque merece la pena que, por lo menos, te suenen.

Empezamos con los patrones creacionales.

Abstract Factory

Si necesitas tener distintas implementaciones de una factoría para generar distintas familias de clases, probablemente tu arquitectura sea demasiado complicada. En serio, tener un AbstractMembershipProviderFactory que sirve para abstraer las distintas implementaciones de factorías capaces de crear distintas implementaciones de MembershipProvider es como para detenerse a pensar si realmente te hacen falta tantos grados de indirección.

Ojo, no hay que confundir este patrón con el patrón factory (sin el abstract), donde tenemos un objeto (la factoría) que es capaz de crear distintos de objetos o incluso distintas configuraciones de un mismo objeto. Este patrón tiene muchos más usos y es rara la aplicación medianamente compleja en la que no aparece varias veces.

Aplicando el patrón factory (sin el abstract) en un par de puntos concretos de la aplicación, muchas veces te puedes ahorrar montar todo el sistema completo de inyección de dependencias con un contenedor y conseguir resultados similares con un código mucho más sencillo de seguir.

Utilidad hoy en día: 2 con abstract, 5 sin abstract.

Builder

Un patrón al que me costó mucho tiempo verle la utilidad real, pero que ha encontrado un hueco muy importante en mi estilo de programación a la hora de escribir tests.

Otro escenario en el que se utiliza bastante es al diseñar interfaces fluidos de esos que estaban tan de moda hace 8 años. Me gusta especialmente cuando se usa para preparar la construcción de la configuración que se usará luego en tiempo de ejecución, al estilo de lo que se hace con Fluent NHibernate o con el IAppBuilder de OWIN.

Saliendo de esos dos escenarios, tests e interfaces fluidos, la verdad es que no lo uso demasiado. Es raro que construya tantas veces un mismo tipo de objeto y con tantas configuraciones diferentes como para que me compense montar un builder.

Utilidad hoy en día: 3.

Factory Method

La definición original de factory method nunca me ha acabado de convencer. De hecho, la diferencia con template method es realmente sútil (esto pasa con más patrones), ya que consiste en tener un método abstracto o virtual en una clase base para construir algo, y dejar que las clases derivadas decidan exactamente qué y como implementar.

Aunque eso tiene sus usos, hay otra forma de ver el factory method que sí utilizo más y me parece más práctica: tener un método estático que construye objetos. A diferencia de un factory, que es una clase entera dedicada a construir cosas, aquí tenemos uno o más método estáticos para construirlas, y estos métodos residen generalmente en la clase base de la jerarquía de clases que estamos construyendo. Un ejemplo es SymmetricAlgorithm.Create o WebRequest.Create.

Lo utilizo bastante para poder simular “constructores con nombre” y que quede más claro lo que estoy creado. Por ejemplo, Color.FromRGB y Color.FromHexString, o Result.Success(value) y Result.Error(exception).

Utilidad hoy en día: 2 (el factory/template method original), 4 (el factory method as named constructor).

Prototype

Si nos ceñimos únicamente a clonar objetos, que es lo que dice el patrón original, la cosa se queda un poco triste. Si ampliamos la idea a construir objetos a partir de otros con las modificaciones que queramos, se hace más interesante. Puede parecer que no se usa mucho, y tal vez en C# sea así, pero hay otros lenguajes en lo que resulta muy habitual.

En Javascript se utiliza continuamente, y no me refiero a la herencia prototípica que casi nadie aprovecha conscientemente, sino a esto:

var opts = Object.assign({}, defaultOpts, customOpts)

Clonando el objeto defaultOps y modificándolo con el contenido de customOpts creamos las opciones reales.

También es habitual verlo en lenguajes que favorecen el uso de estructuras de datos inmutables, donde partiendo de una estructura que sirve de base, se “clona” (en realidad se reutiliza, aprovechando su inmutabilidad) y sirve de base para crear la siguiente versión de la estructura.

Utilidad hoy en día: 3.

Singleton

El pobre singleton. Creo que fue el primer patrón de diseño que conocí y entendí (al igual que mucha gente). De ahí al abuso… bueno, ya sabemos todos como acabó el singleton.

Pese a su mala fama, sigue teniendo su uso y, al igual que ocurre con los métodos estáticos, se pueden salvar muchos de sus problemas. Aun así, su utilidad es limitada y suelo preferir separar la gestión del ciclo de vida de la clase de la propia clase, dejando que sea otro el que lo gestione.

En general, antes de utilizar un singleton prefiero utilizar una fachada estática. Pierdes la parte de la inicialización perezosa, pero te ahorras algo de código al no tener que andar poniendo el Instance o getInstance() por todas partes.

Utilidad hoy en día: 2.

Conclusión

En este post hemos repasado los 5 patrones creacionales clásicos y, en conjunto, podríamos decir que gozan de una salud bastante razonable, y más teniendo en cuenta que vienen de una época en la que no existía ni Java.

Algunos de ellos como AbstractFactory y Singleton han caído más en desuso, en parte por sus propios defectos (excesiva complejidad o excesivo acoplamiento), pero también porque cuando los contenedores de inversión de control se hicieron mainstream parte de las problemas que solucionaban estos patrones quedaban resueltos por el propio contenedor.

Las factorías (no abstract) y los factory methods (como constructores estáticos) son dos patrones que utilizo con mucha frecuencia y creo que aportan bastante en forma de abstracción y legibilidad al tratar con jerarquías de clases, o incluso con una única clase cuando queremos resaltar muy bien las características de la instancia que estamos construyendo.

Builder y Prototype son dos patrones de uso más limitado. Cuando son útiles, resultan muy útiles, pero lo cierto es que no los utilizo con tanta frecuencia.

Posts relacionados:

  1. Patrones de Reutilización de Código entre Componentes de ReactJS
  2. Parece lo mismo pero…
  3. Diseño por Contrato

» Leer más, comentarios, etc...

Una sinfonía en C#

Xamarin Dev Days Buenos Aires 2016

December 04, 2016 07:17 PM

El viernes 2 de Diciembre he tenído el honor de participar en #XamarinDevDays en Buenos Aires tanto como organizador como speaker, el evento tuvo lugar en las oficinas de Microsoft de Argentina en Buenos Aires desde las 9hs hasta las 16hs.

Gracias!

Lo primero que quiero decir es gracias a quienes me dieron la oportunidad de organizar este evento Jayme, Diana y a los que ayudaron desde Microsoft Argentina Soledad y Carolina, sin ellas hubiera sido imposible; todo el tiempo que duró la organización así como durante el evento cada una de ellas dio una gran mano.

A todos los asistentes por tomarse todo un día para compartir con nosotros.

También quiero agradecer a los speakers, además de mí estuvieron Alex Pestchanker y Sebastián Pérez, ambos dieron excelentes charlas.

El evento

El evento contó con tres charlas y un Hand on lab después del almuerzo en el cual los asistentes desarrolaban su primera aplicación con Xamarin Forms conectada a Azure y todo salió más que bien.

Lo más importante de todo fue la convocatoria, éramos más de 40 personas que llegaron bien temprano y de ellos más de 30 estuvieron hasta el final y simpre mostrando un gran interés en el tema y muy buena predisposición.

Dejo algunas fotos del evento.

XamarinDevDays-5XamarinDevDays-7XamarinDevDays-18XamarinDevDays-8XamarinDevDays-15XamarinDevDays-34

Quiero agradecer especialmente a Meri y Ale por ayudarnos con la promoción, para los que no vieron hicimos un par de videos:

Nos leemos.

» Leer más, comentarios, etc...

PHP Senior

PHP 7.1, para tener en cuenta

December 04, 2016 07:11 PM




  • Try/catch: poder atrapar en un solo catch varias excepciones
  • Soporte HTTP/2 en push de curl
  • Visibilidad en las constantes 
  • Poder definir en el retorno de un método que este es de tipo void
  • Warning por strings inválidos en operaciones matemáticas
  • Se depreca y remueve mcrypt()
  • y más
Un buen resumen en: https://dotdev.co



» Leer más, comentarios, etc...

Blog Bitix

Introducción al JavaScript de ECMAScript 6

December 04, 2016 12:30 PM

Con ECMAScript 6 se han incorporado al lenguaje varias novedades como nuevas palabras reservadas para definir variables y constantes, símbolos, interpolación de variables en cadenas, desestructuración, forma abreviada para declarar funciones, nueva sintaxis más sencilla para definir clases, objetos de tipo Map y Set, Promises como alternativa a callbacks, el protocolo Iterator y generadores, además de algunas otras cosas que si como yo no habías dedicado tiempo a aprender mejor JavaScript aún te resulten novedosas.

JavaScript

Hasta ahora como desarrollador web durante prácticamente toda mi vida laboral no había dedicado tiempo a conocer en más detalle el lenguaje de programación JavaScript usado en los navegadores web. Mucho de lo que necesitaba me era suficiente con librerías como jQuery o underscore. Ahora algunas páginas web tienen un peso importante en el lado cliente y ante esta necesidad el lenguaje JavaScript está evolucionando e incorporando nuevas características como las definidas en sus especificaciones de ECMAScript.

Para aprender en mucho más en detalle lo poco que conocía de JavaScript he leído el libro Learning JavaScript que cubre las novedades de ECMAScript 2015 también conocido como ECMAScript 6 (ES6). Después de leerlo diré que es un libro que me ha gustado mucho y considero que es adecuado tanto para alguien que pueda estar aprendiendo a programar como para alguien que ya conoce otros lenguajes de programación explicando los conceptos sin complicaciones.

Las últimas versiones de los navegadores Chrome y Firefox ya soportan todo lo que describo a continuación y que está más detalladamente explicado en el libro. Para los navegadores que aún no soportan todo como en los dispositivos móviles hay compiladores o transpilers que traducen ECMAScript 6 a ECMAScript 5. En un entorno en el que sepamos se usa solo Chrome o Firefox como en una intranet o una aplicación de uso interno en una organización podemos utilizar estas novedades y si es una aplicación accesible por cualquier usuario desde internet podemos hacer la conversión de ECMAScript 6 a ECMAScript 5 con gulp o grunt.

Estas son gran parte de las novedades que he anotado al leer el libro Learning JavaScript. Para profundizar sobre JavaScript la documentación de Mozilla Developer Network está muy bien como manual de referencia donde hay más ejemplos y comentarios más extensos de los que hago en cada sección.

Definición de variables

Para solventar las deficiencias de las variables declaradas con var hay dos nuevas palabras reservadas let para declarar variables que cambian de valor y const para constantes. También se pueden declarar símbolos que son identificadores de tipos únicos e inmutables.

El problema de las variables declaradas con var está en que tienen ámbito de función con let no existe hasta que es declarada. Las variables con var son declaradas al principio del ámbito de la función o en el ámbito global.

Interpolación de variables en cadenas

La interpolación de variables en cadenas facilita la construcción de strings y hace el código más legible. Las plantillas se definen con comillas de acento grave `.

Desestructuración

Se ha incorporado la asignación desestructurada pudiendo hacer cosas como las siguientes en las asignaciones y en las llamadas a las funciones.

Operador spread

El operador spread permite a una expresión se expandida en lugares donde se esperan múltiples argumentos como en llamadas a funciones, múltiples elementos para literales de arrays o múltiples variables para asignación desestructurada.

Bucles con in y of

Usando el iterador in en un bucle recorremos las propiedades de un objeto y con el iterador of podemos recorrer cualquier objeto iterable. Cualquier objeto que definamos podemos hacerlo iterable cumpliendo el protocolo Iterable.

Funciones

En JavaScript definir funciones es una parte muy importante de la esencia del lenguaje, ahora hay una forma corta de definir funciones.

Arrays

El tipo Array tiene muchos métodos y funciones adecuadas para la programación funcional como map, filter o reduce y también push, pop, shift, unshift, forEach, slice, splice, fill, copyWithin, findIndex, lastIndexOf, indexOf, reverse, sort, some, every, join o concat. Funciones que antes no estaban presentes y para suplir su ausencia usábamos la librería underscore.

Métodos de la clase Function

Teniendo en una variable de tipo Function podemos llamarla con call incluyendo un parámetro que se considerará el valor de la referencia this dentro de la función. Con apply los argumentos serán los definidos en un array aunque con la sintaxis spread esta función puede caer en desuso. Con bind podemos asociar a la función la referencia que siempre se tomará como this.

Nueva sintaxis para clases

Anteriormente en JavaScript ya se podían definir clases haciendo uso de la propiedad prototype aunque su sintaxis ahora se ha simplificado y hecho más parecida a otros lenguajes además de definir propiedades con su método getter y setter.

Objetos Map y Set

Los objetos pueden ser utilizados como mapas pero a veces utilizar un objeto no es deseable como contenedor de datos, para ello se definen los Map que son clases que a través de una clave se accede a un valor y Set para colecciones sin elementos repetidos.

Algunas funciones de la clase Map son get, set, has, size, keys, values, entries, forEach, delete, clear y size. Algunas de la clase Set son add, has, forEach, delete y size.

Operadores instanceof y typeof

Con instanceof se puede comprobar si una variable es de un cierto tipo, si su cadena de prototipos incluye la función indicada. Con typeof se puede conocer el tipo de dato de una variable.

Excepciones

JavaScript soporta gestionar ciertas circunstancias de error con excepciones y con la construcción try catch finally similar a la existente en lenguajes como Java.

Callback y Promise

Algunas tareas las manejamos usando funciones callback, funciones que se pasan como argumento y que son llamadas en algún momento. La programación con callback se hace complicada en la programación asíncrona cuando se anidan varias funciones. Con los objetos Promise el código de la programación asíncrona es más legible.

Generators

Los objetos Generator que se basan en el protocolo Iterator pueden establecer una comunicación entre el generador y el código que lo llama con la palabra reservada yield que retorna el valor del generador y la función next() del iterador que puede proporcionar una parámetro usable en el generador. Las funciones generadoras se declaran poniendo un * después de la palabra function.

Otros métodos nuevos de la clase Object son freeze que impide añadir nuevas propiedades al objeto, eliminar existentes o modificar sus valores haciendo al objeto inmutable. Con seal se previene únicamente añadir nuevas propiedades.

Misc

Declarando el modo esctricto con ‘use strict’; evitamos algunos de los errores que podemos cometer al usar JavaScript como declarar una variable en un ámbito global cuando no es nuestra intención. Con el método toString() de los objetos podremos proporcionar una representación de un objeto más descriptiva.

Manipulación DOM

Es raro que para manipular el árbol DOM que representa el HTML cargado en el navegador no usemos la librería jQuery pero para casos básicos o cuando no podemos usar esa librería o queremos esa dependencia podemos hacer uso de las funciones incorporadas en el propio navegador y algunas funciones declaradas en el objeto Document. Algunos métodos del objeto Documento son getElementById, getElementsByClassName, getElementsByTagName, querySelector y querySelectorAll.

Para manipular el texto de un nodo se usa la propiedad textContent de la interfaz Node y para incluir en el nodo contenido HTML la propiedad innerHTML de la interfaz Element.

Con createElement de Document mediante código podemos crear nuevos elementos y con appendChild o insertBefore de Node insertarlos en el árbol DOM. Con la propiedad classList y los métodos add y remove podemos añadir clases a un nodo y con dataset acceder a los atributos data- de la etiqueta.

Eventos

Los navegadores definen más de 200 eventos ante los que podemos reaccionar, uno de los más típicos es el click en un botón. A un Element de la página y con el método addEventListener() se pueden asociar eventos.

Eventos como el click en algunos elementos tienen definido un comportamiento por defecto, para evitar ejecutar ese comportamiento por defecto disponemos de la función preventDefault.

Los manejadores de eventos se van recorriendo primero en modo captura desde la raíz hasta el nodo del árbol DOM donde se ha producido el evento y posteriormente en modo burbuja desde el nodo donde se ha producido el evento hasta la raíz. Con stopPropagation se puede cancelar la propagación del evento, realmente la propagación se sigue realizando pero el evento se marca como cancelado. Con stopImmediatePropagation se puede parar la propagación completamente, parando incluso la propagación con el evento cancelado.

Todos estos ejemplos funcionan en los navegadores Firefox y Chrome pudiendo probarlos en la consola JavaScript que incorporan para los desarrolladores. En la página es6-features hay una lista completa de todas las nuevas características de ECMAScript 6.

» Leer más, comentarios, etc...

Blog Bitix

Introducción a JavaScript de ECMAScript 6

December 03, 2016 11:00 AM

Con ECMAScript 6 se han incorporado al lenguaje varias novedades como nuevas palabras reservadas para definir variables y constantes, símbolos, interpolación de variables en cadenas, desestructuración, forma abreviada para declarar funciones, nueva sintaxis más sencilla para definir clases, objetos de tipo Map y Set, Promises como alternativa a callbacks, el protocolo Iterator y generadores, además de algunas otras cosas que si como yo no habías dedicado tiempo a aprender mejor JavaScript aún te resulten novedosas.

JavaScript

Hasta ahora como desarrollador web durante prácticamente toda mi vida laboral no había dedicado tiempo a conocer en más detalle el lenguaje de programación JavaScript usado en los navegadores web. Mucho de lo que necesitaba me era suficiente con librerías como jQuery o underscore además de las similitudes de sintaxis con el lenguaje Java. Ahora algunas páginas web tienen un peso importante en el lado cliente y ante esta necesidad el lenguaje JavaScript está evolucionando e incorporando nuevas características como las definidas en sus especificaciones de ECMAScript.

Para aprender en mucho más en detalle lo poco que conocía de JavaScript he leído el libro Learning JavaScript que cubre las novedades de JavaScript 2015 también conocido como ECMAScript 6. Después de leerlo diré que es un libro que me ha gustado mucho y considero que es adecuado tanto para alguien que pueda estar aprendiendo a programar como para alguien que ya conoce otros lenguajes de programación explicando los conceptos sin complicaciones.

Las últimas versiones de los navegadores Chrome y Firefox ya soportan todo lo que describo a continuación y que está más detalladamente explicado en el libro. Para los navegadores que aún no soportan todo hay compiladores o transpilers que traducen ECMAScript 6 a ECMAScript 5. En un entorno en el que sepamos se usa solo Chrome o Firefox podemos hacer uso de estas novedades y si es una aplicación accesible por cualquier usuario desde internet podemos hacer la conversión de ECMAScript 6 a ECMAScript 5 con gulp o grunt.

Estas son gran parte de las novedades que he anotado al leer el libro Learning JavaScript. Para profundizar sobre JavaScript la documentación de Mozilla Developer Network está muy bien como manual de referencia donde hay más ejemplos y comentarios más extensos de los que hago en cada sección.

Definición de variables

Para solventar las deficiencias de las variables declaradas con var hay dos nuevas palabras reservadas let para declarar variables que cambian de valor y const para constantes. También se pueden declarar símbolos que son identificadores de tipos únicos e inmutables.

El problema de las variables declaradas con var está en que tienen ámbito de función con let no existe hasta que es declarada. Las variables con var son declaradas al principio del ámbito de la función o en el ámbito global.

Interpolación de variables en cadenas

La interpolación de variables en cadenas facilita la construcción de strings y hace el código más legible.

Desestructuración

Se ha incorporado la asignación desestructurada pudiendo hacer cosas como las siguientes en las asignaciones y en las llamadas a las funciones.

Sintaxis spread

La sintaxis spread permite a una expresión se expandida en lugares donde se esperan múltiples argumentos como en llamadas a funciones, múltiples elementos para literales de arrays o múltiples variables para asignación desestructurada.

Bucles con in y of

Usando el iterador in en un bucle recorremos las propiedades de un objeto y con el iterador of podemos recorrer cualquier objeto iterable. Cualquier objeto que definamos podemos hacerlo iterable cumpliendo el protocolo Iterable.

Funciones

En JavaScript definir funciones es una parte muy importante de la esencia del lenguaje, ahora hay una forma corta de definir funciones.

Arrays

El tipo Array tiene muchos métodos y funciones adecuadas para la programación funcional como map, filter o reduce y también push, pop, shift, unshift, forEach, slice, splice, fill, copyWithin, findIndex, lastIndexOf, indexOf, reverse, sort, some, every, join o concat. Funciones que antes no estaban presentes y para suplir su ausencia usábamos la librería underscore.

Métodos de la clase Function

Teniendo en una variable de tipo Function podemos llamarla con call incluyendo un parámetro que se considerará el valor de la referencia this dentro de la función. Con apply los argumentos serán los definidos en un array aunque con la sintaxis spread esta función puede caer en desuso. Con bind podemos asociar a la función la referencia que siempre se tomará como this.

Nueva sintaxis para clases

Anteriormente en JavaScript ya se podían definir clases haciendo uso de la propiedad prototype aunque su sintaxis ahora se ha simplificado y hecho más parecida a otros lenguajes.

Objetos Map y Set

Los objetos pueden ser utilizados como mapas pero a veces utilizar un objeto no es deseable como contenedor de datos, para ello se definen los Map que son clases que a través de una clave se accede a un valor y Set para colecciones sin elementos repetidos.

Algunas funciones de la clase Map son get, set, has, size, keys, values, entries, forEach, delete, clear y size. Algunas de la clase Set son add, has, forEach, delete y size.

Operadores instanceof y typeof

Con instanceof se puede comprobar si una variable es de un cierto tipo, si su cadena de prototipos incluye la función indicada. Con typeof se puede conocer el tipo de dato de una variable pudiendo ser … .

Excepciones

JavaScript soporta gestionar ciertas circunstancias de error con excepciones y con la construcción try catch finally.

Callback y Promise

Algunas tareas las manejamos usando funciones callback, funciones que se pasan como argumento y que son llamadas en algún momento. La programación con callback se hace complicada en la programación asíncrona cuando se anidan varias funciones callback. Con los objetos Promise el código de la programación asíncrona es más legible.

Generators

Los objetos Generator que se basan en el protocolo Iterator se puede establecer una comunicación entre el generador y el código que lo llama con la palabra reservada yield que retorna el valor del generador y la función next() del iterador que puede proporcionar una parámetro usable en el generador. Las funciones feneradoras se declaran poniendo un * después de la palabra function.

Otros métodos nuevos de la clase Object son freeze que impide añadir nuevas propiedades al objeto, eliminar existentes o modificar sus valores haciendo al objeto inmutable. Con seal se previene únicamente añadir nuevas propiedades.

Misc

Declarando el modo esctricto con ‘use strict’ evitamos algunos de los errores que podemos cometer al usar JavaScript como declarar una variable en un ámbito global cuando no es nuestra intención. Con el método toString() de los objetos podremos proporcionar una representación de un objeto más descriptiva.

Manipulación DOM

Es raro que para manipular el árbol DOM que representa el HTML cargado en el navegador no usemos la librería jQuery pero para casos básicos o cuando no podemos usar esa librería o queremos esa dependencia podemos hacer uso de las funciones incorporadas en el propio navegador y algunas funciones declaradas en el objeto Document. Algunos métodos del objeto Documento son getElementById, getElementsByClassName, getElementsByTagName, querySelector y querySelectorAll.

Para manipular el texto de un nodo se usa la propiedad textContent de la interfaz Node y para incluir en el nodo contenido HTML la propiedad innerHTML de la interfaz Element.

Con createElement de Document mediante código podemos crear nuevos elementos y con appendChild o insertBefore de Node insertarlos en el árbol DOM. Con la propiedad classList y los métodos add y remove podemos añadir clases a un nodo y con dataset acceder a los atributos data- de la etiqueta.

Eventos

Los navegadores definen más de 200 eventos ante los que podemos reaccionar, uno de los más típicos es el click en un botón. A un Element de la página y con el método addEventListener() se pueden asociar eventos.

Algunos eventos como el click en algunos elementos tiene definido un comportamiento por defecto, para evitar ejecutar ese comportamiento por defecto disponemos de la función preventDefault.

Los manejadores de eventos se van recorriendo primero en modo captura desde la raíz hasta el nodo del árbol DOM donde se ha producido el evento y posteriormente en modo burbuja desde el nodo donde se ha producido el evento hasta la raíz. Con stopPropagation se puede cancelar la propagación del evento, realmente la propagación se sigue realizando pero el evento se marca como cancelado. Con stopImmediatePropagation se puede parar la propagación completamente, parando incluso la propagación con el evento cancelado.

Todos estos ejemplos funcionan en los navegadores Firefox y Chrome pudiendo probarlos en la consola JavaScript que incorporan para los desarrolladores.

» Leer más, comentarios, etc...

Poesía Binaria

Pasa tu web a HTTPS utilizando Let’s encrypt manual o automáticamente, tú decides

November 29, 2016 12:22 PM

photo-1461685265823-f8d5d0b08b9b

La web no fue diseñada pensando en la seguridad, es decir, la comunicación se realiza de forma plana y cualquiera que pueda pinchar la línea puede ver los mensajes que pasan, el origen y el destino, y no hace falta ser un crack, sólo instalar un programa como Wireshark. Afortunadamente ahora tenemos HTTPS, es el mismo protocolo web, pero utilizando una capa de seguridad que cifra la comunicación entre las dos partes (nuestro navegador y el servidor) y hace que sea muy complicado que alguien que pueda interceptar la comunicación sepa qué estamos hablando.

La seguridad es muy importante hoy en día, ya que en casi todo tipo de páginas se intercambian datos sensibles, ya sean usuarios y contraseñas, direcciones de correo, datos personales, datos bancarios, o incluso datos que no queremos que sepa alguien (alguna foto comprometida, análisis clínicos, conversaciones, etc). Y actualmente, es muy cómodo transmitirlo todo sobre HTTP, ya que hacemos que un navegador sea capaz de tratar con los datos haciendo posible que muchos tipos de aplicaciones (móviles y de escritorio) puedan acceder fácilmente a la información. Antes se creaban aplicaciones específicas y protocolos propietarios cada vez que se trataba un tipo de información, y por supuesto, la seguridad había que programarla aparte. Ahora simplemente, los programadores incluyen una biblioteca de comunicación HTTP(s).

Google lleva tiempo amenazando con bajar el prestigio de webs sin HTTPS

Google empezó hace unos años penalizando un poco a páginas que no utilizaban HTTPS y pedían datos sensibles (tenían campos password, básicamente). Ahora mismo, las páginas que incluyen una capa de seguridad tienen premio en los posicionamientos. El problema es que HTTPS al mismo tiempo que cifra la comunicación, crea una verificación y da confianza al usuario dando validez al servidor al que accedemos diciendo que somos quien decimos ser. Por ejemplo, podemos hacer una página de phising con el aspecto de la página de un banco, pero el certificado no podrá nunca decir que somos ese banco (¿quién mira el certificado?). En este caso el navegador nos suele avisar, y no debemos aceptar los certificados a la ligera.
El tema, es que hasta el año pasado, tener un certificado para cifrar la conexión costaba dinero, un certificado que estuviera autorizado, claro. Es verdad que los hay muy baratos (4€/año), pero es un coste que si gestionas muchas webs se va multiplicando. Aunque también existen certificados que cuestan miles de euros, y todo tiene un motivo. Por supuesto, nos podíamos crear un certificado nosotros mismos, aunque todos los navegadores verían advertencias, porque nadie dice que nosotros seamos de confianza, y no hemos pagado por nuestra confianza.

Cuando pides un certificado, normalmente la empresa a la que lo pides realiza unas pruebas verificando quién eres, y que no haces cosas ilegales con tu sitio. Dependiendo del coste del certificado el examen puede ser más exhaustivo y tardar más. Los certificados más sencillos, sólo verifican tu IP, tu dominio y poco más. Los hay que te piden documentos de empresa para certificar quién eres, incluso identificación de empleados, responsables, documentos firmados que hay que remitir por correo y ellos guardarán bajo llave. Hay certificados como los EV (Extended Validation, validación extendida), que son los que solemos ver en los bancos, en los que la barra de direcciones aparece en verde y aparecen en el certificado más datos sobre el nombre de la organización, con el fin de dar confianza al usuario, ¡Eres quien dices ser!
Además, cuanta más verificación haya en ese certificado, mayor será la indemnización en caso de haber un problema. Dicha indemnización es al usuario afectado, por ejemplo, si han suplantado su identidad o le han robado información y es culpa del certificado o de que no se podía confiar en la empresa que han verificado (ellos no habrían hecho bien su trabajo diciendo que eres quien dices ser y que tienes un sitio legítimo). Esto no cubriría en principio fugas de información de la empresa.

También tenemos los certificados Wildcard que valen para cubrir un subdominio completo, por ejemplo todos los subdominios que haya bajo totaki.com (loquesea.totaki.com , privado.totaki.com , nube.totaki.com, etc) y suelen ser bastante caros aunque no tengan validación extendida. Pero suele ser más barato que comprar un certificado para cada uno de tus subdominios (si necesitas cierto nivel de confianza).

¿Qué diferencia hay entre Let’s Encrypt y un certificado de pago?

Let’s Encrypt es un certificado cuya intención es cifrar la comunicación. Por ejemplo si tienes un blog, o un pequeño sistema de usuarios y quieres que los datos se transmitan de forma segura, o dar un poco de confianza al usuario están muy bien. No son de validación extendida, ni lo pretenden, porque es un sistema automático sin intervención humana por parte de Let’s Encrypt. Pero conseguimos una conexión cifrada, gratuita y Google no nos penaliza tanto (aunque puede que algún navegador o S.O. antiguo sí lo haga, pero no nos debería quitar el sueño). Eso sí, Let’s Encrypt verifica que el dominio que estamos certificando corresponde con el servidor en el que estamos.

Los certificados de pago, normalmente nos dan algo de soporte técnico por chat, o por teléfono, y nuestros datos suelen ser archivados por un humano (no siempre, los de 4€ ni eso).

Si no tienes acceso SSH al servidor

Si no dispones de conexión SSH a tu servidor. Tendrás que decirle a tu proveedor de hospedaje que te instale el certificado para tu web. De todas formas, Let’s encrypt está empezando a ser bastante famoso y muchos proveedores lo ofrecen de forma gratuita en sus paneles de control. Es cuestión de probarlo en tu web y con tu configuración actual, porque tal vez no haya ningún problema y lo puedas activar.

Eso sí, tienes que tener cuidado con la versión HTTP. Es interesante hacer que la versión HTTP redirija a HTTPS para que no haya contenidos duplicados, y sobre todo para que no haya ninguna cookie perdida que haga que un usuario identificado deje de estarlo al entrar en otra versión de la página. Debemos controlar dónde apuntan todos nuestros enlaces, pero muchas veces es casi imposible.

Instalación de certbot

Dependiendo de nuestra distribución, la instalación o el nombre del paquete varía. En muchos sitios lo veremos como certbot, en otros python-certbot, en otros se llama python-letsencrypt, por lo que podemos buscar el paquete por esos nombres. Por ejemplo en Debian 8, tenemos que buscar en los backports, añadiendo:

deb http://ftp.fr.debian.net/debian jessie-backports main
deb-src http://ftp.fr.debian.net/debian jessie-backports main

En /etc/apt/sources.list o en un archivo dentro de /etc/apt/sources.list.d/

Para ver la instalación detallada, podemos ir a esta página donde seleccionamos la distribución y el servidor web, porque aquí pondré un ejemplo directo para Apache sobre Debian Jessie (Debian 8):

sudo apt-get install python-certbot-apache -t jessie-backports
; …
; …
; Decimos que sí. Y después de instalar muchos paquetes y ver muchas letras…
; …
; …

Modo automático con certbot

Yo no soy muy fan de estos métodos automáticos que cambian cosas milagrosamente en el servidor. Creo que muchas veces estos sistemas tocan cosas que no deben y, aunque los buenos sistemas mantienen copias de lo archivos originales, nos suelen dar más de un susto. De hecho, Let’s Encrypt me ha dado ya algún susto en un servidor que gestiono.

Pero claro, si acabas de instalarlo todo en el servidor, sólo tienes una web o no te importa que ocurra un susto y con ello problemas de downtime o de certificados en tu sitio, puedes probar este método.

sudo certbot

o

sudo certbot --apache

Listo! Él ya se encarga. Nos hará ciertas preguntas e instalará el certificado donde corresponde. En teoría, aunque los ficheros de configuración los dejará un poco feos (sin anidados ni nada), además, aunque incluye configuraciones recomendadas para muchos escenarios, puede que machaque algunas configuraciones que ya tenemos.
En realidad certbot nos ahorra todo el tema de creación de claves, sign requests, envío a la autoridad para que lo firme, instalación de certificado y configuración de seguridad lo que muchas veces es de agradecer.

Pero la cosa no termina aquí, deberás mirar también el apartado de auto-renovación, ya que los certificados caducan a los 3 meses.

Certbot, con configuración manual

Para ello, tenemos que ejecutar certbot con los siguientes argumentos:

sudo certbot --apache certonly -d [dominio]

O si es la primera vez que lanzamos un certificado, tendremos que aceptar la licencia y dar una dirección de correo para incidencias, todo eso nos lo puede pedir de forma interactiva, pero si queremos automatizar el proceso no puede ser interactivo, por ello ejecutaremos lo siguiente:

sudo certbot --apache --agree-tos --email [mi_direccion@de_correo] certonly -n -d [dominio]
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for [dominio]
Waiting for verification…
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem

Adicionalmente se pueden añadir dominios con todos los -d [dominio] que queramos. Dichos dominios serán VirtualHosts que tengamos hechos y se obtendrán a partir del ServerName. Por supuesto, los certificados pueden ser para un subdominio o un sub-sub dominio.

Con esto, hemos creado los certificados necesarios para correr el sitio web. Ahora, en Apache, debemos ir a nuestro virtualhost que se llamará por ejemplo certest.totaki.com y estará en el archivo /etc/apache2/sites-available/certest.totaki.com.conf (el archivo puede llamarse como quieras, pero me gusta poner nombres coherentes):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<VirtualHost *:80>
    # The ServerName directive sets the request scheme, hostname and port that
    # the server uses to identify itself. This is used when creating
    # redirection URLs. In the context of virtual hosts, the ServerName
    # specifies what hostname must appear in the request's Host: header to
    # match this virtual host. For the default virtual host (this file) this
    # value is not decisive as it is used as a last resort host regardless.
    # However, you must set it for any further virtual host explicitly.
    ServerName certest.totaki.com

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
    # error, crit, alert, emerg.
    # It is also possible to configure the loglevel for particular
    # modules, e.g.
    #LogLevel info ssl:warn

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # For most configuration files from conf-available/, which are
    # enabled or disabled at a global level, it is possible to
    # include a line for only one particular virtual host. For example the
    # following line enables the CGI configuration for this host only
    # after it has been globally disabled with "a2disconf".
    #Include conf-available/serve-cgi-bin.conf
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>

Las últimas líneas de Rewrite son las que debemos añadir, haciendo que cuando alguien se conecte desde HTTP le redirija automáticamente a la versión HTTPS del sitio. Ahora bien, en otro fichero aparte dentro de /etc/apache2/sites-available/ (podemos llamarlo certest.totaki.com-ssl) o, si lo preferimos, podemos añadirlo en el mismo archivo: /etc/apache2/sites-available/certest.totaki.com debemos crear el virtualhost seguro, añadiendo lo siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<IfModule mod_ssl.c>
        <VirtualHost *:443>
                # The ServerName directive sets the request scheme, hostname and port that
                # the server uses to identify itself. This is used when creating
                # redirection URLs. In the context of virtual hosts, the ServerName
                # specifies what hostname must appear in the request's Host: header to
                # match this virtual host. For the default virtual host (this file) this
                # value is not decisive as it is used as a last resort host regardless.
                # However, you must set it for any further virtual host explicitly.
                ServerName certest.totaki.com

                ServerAdmin webmaster@localhost
                DocumentRoot /var/www/html

                # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
                # error, crit, alert, emerg.
                # It is also possible to configure the loglevel for particular
                # modules, e.g.
                #LogLevel info ssl:warn

                ErrorLog ${APACHE_LOG_DIR}/error.log
                CustomLog ${APACHE_LOG_DIR}/access.log combined

                # For most configuration files from conf-available/, which are
                # enabled or disabled at a global level, it is possible to
                # include a line for only one particular virtual host. For example the
                # following line enables the CGI configuration for this host only
                # after it has been globally disabled with "a2disconf".
                #Include conf-available/serve-cgi-bin.conf

                #   SSL Engine Switch:
                #   Enable/Disable SSL for this virtual host.
                SSLEngine on

                # Include certificate file and key
                SSLCertificateFile /etc/letsencrypt/live/certest.totaki.com/fullchain.pem
                SSLCertificateKeyFile /etc/letsencrypt/live/certest.totaki.com/privkey.pem

                # intermediate configuration, tweak to your needs
                SSLProtocol             all -SSLv3
                SSLCipherSuite          ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
                SSLHonorCipherOrder     on
                SSLCompression          off
                SSLOptions +StrictRequire

                Header always set Strict-Transport-Security "max-age=15768000"
        </VirtualHost>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
</IfModule>

Si ponemos la configuración del virtualhost seguro junto con la del inseguro será más fácil activar y desactivar webs con un sólo a2ensite/a2dissite. Es también una buena práctica, siempre que tengamos tiempo, verificar las nuevas configuraciones SSL gracias a Mozilla SSL Configuration Generator. Aquí tendremos muchas combinaciones de Servidores y versiones de software que nos ayudarán a mantener nuestro servidor seguro. Eso sí, cuanto más actualizado esté el servidor, mejores algoritmos de cifrado tendremos disponibles.

Auto renovación del certificado

Estos certificados duran unos tres meses. Y esto es bueno, normalmente los certificados pagados suelen durar un año, y cuando ocurren cosas como el bug Heartbleed, que nos obligó a renovar todos los certificados que teníamos, se nos fastidiaron todos los planes a los que trabajamos en seguridad. De hecho, puede suceder que haya vulnerabilidades no conocidas por los desarrolladores o por los administradores de sistemas que puedan ser explotados si nuestros certificados están demasiado tiempo sin cambiarse. Además, ya que han desarrollado un método automático para la renovación de estos certificados, ¿por qué no aprovecharlo?

Para ello tenemos que ejecutar el comando:

sudo certbot renew --dry-run

Incluso podemos poner un cron para que cada semana verifique esto, renovando todos los dominios que tengamos a punto de expirar (certbot considera por defecto que está a punto de expirar cuando faltan 10 días). Y si hemos tenido algún problema con esto, recibiremos un correo, adicionalmente, yo me envío también el resultado de esta tarea cron con MAILTO=:

sudo crontab -e

Así editamos las tareas de root y añadimos:

# m h dom mon dow command
30 4 * * 1 certbot renew –dry-run

Para ejecutar todos los lunes a las 04:30 (suponemos que a esa hora no hay nadie que pueda ver un posible microcorte en el servicio).

Buenas prácticas

Aquí detallo algunas buenas prácticas que van surgiendo con los años y que considero interesantes.

Renovando certificados

Certbot permite la ejecución de scripts antes, durante y después de las renovaciones. Es decir, antes de pedir un certificado, podremos ejecutar un programa, tras cada renovación (imaginad que renovamos varios certificados) ejecutaremos otro programa y al final, ejecutaremos otro. Para ello, nos proporciona los siguientes modificadores:

sudo certbot renew --dry-run --pre-hook “/usr/local/bin/renew_antes” --post-hook “/usr/local/bin/renew_final” --renew-hook “/usr/local/bin/renew_entre”

Con esos scripts podemos hacer un log, enviar correos, establecer notificaciones o incluso recargar la configuración de servicios. Por ejemplo, cuando el certificado lo utilice también NodeJs o Nginx podemos hacer:

sudo certbot renew --dry-run --post-hook “npm restart”

Aunque lo suyo es crear un pequeño script que cargue el servicio por si tenemos que ejecutarlo con un determinado usuario o ejecutarlo en una determinada ruta.

Configuración de SSL común

Algo que nos puede ayudar a la hora de mantener Apache es crear una configuración propia y común para todos los sitios alojados en el servidor. En lugar de modificar los ficheros de configuración de Apache, podemos crear una configuración propia en la que podemos incluir ajustes sobre SSL, seguridad y demás. Además, a la hora de llevarnos la configuración a otro servidor (o por si tenemos que hacer una actualización grande), no nos afectaría mucho, ya que ese fichero nadie lo va a tocar.

Para ello, debemos crear un fichero en /etc/apache2/conf-available/ y lo llamamos, por ejemplo, poesia.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<DirectoryMatch "/\.svn">
   Require all denied
</DirectoryMatch>
<DirectoryMatch "/\.git">
   Require all denied
</DirectoryMatch>
ServerToken Prod
ServerSignature Off
Header set X-Content-Type-Options: "nosniff"
Header set X-Frame-Options: "sameorigin"
Header set X-XSS-Protection "1; mode=block"
# OCSP Stapling, only in httpd 2.3.3 and later
SSLUseStapling          on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLStaplingCache        shmcb:/var/run/ocsp(128000)
# intermediate configuration, tweak to your needs
SSLProtocol             all -SSLv3
SSLCipherSuite          ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder     on
SSLCompression          off
Timeout 180
TraceEnable Off
FileETag MTime Size
#FileETag None

Y podemos incluir muchas cosas más. Por ejemplo, la configuración de protocolo SSL podemos incluirla en ese fichero y quitarla de los VirtualHosts. Además, podemos activar y desactivar con a2enconf/a2disconf.

Verificar datos de nuestro certificado

Está bien saber cómo está el certificado de vez en cuando, así que:

sudo  openssl x509 -noout -text -in /etc/letsencrypt/live/certest.totaki.com/cert.pem

Nos va a dar mucha información útil.

Utilizar sólo recursos seguros

Todas las URLs que carguemos desde nuestra web deberán ser HTTPS, imágenes, scripts, estilos, tipos de letra, etc. Por eso tenemos que asegurarnos de ello. Y por eso es una mala idea meter las URLs a mano en el código de la web. Debemos tener en cuenta también los recursos que utilicemos desde CDN, por ejemplo jquery, y scripts por el estilo, cuya URL debería empezar ahora por https:// o simplemente por // (donde aprovechará el protocolo desde el que accedemos a la web principal).
El objetivo es evitar el candado naranja que nos indica que hay recursos no seguros. Además, aunque redirijamos a HTTPS todos los HTTP, no es plan de hacer que el navegador acceda a cada URL por HTTP y luego por HTTPS gracias a la redirección, porque tendríamos el doble de hits y estaríamos desperdiciando recursos de nuestro servidor.

Probar la seguridad de tu certificado

Es muy importante probar desde fuera que todo va bien, haciendo algo de auditoría a nuestra web. Para ello podemos utilizar los siguientes servicios:

Estos sitios suelen estar al día en cuanto a vulnerabilidades de cifrado y negociación y nos darán pistas de cómo hacer más segura la comunicación con nuestro servidor.

Más información

Instalando el certificado SSL en el blog, para instalarlo en nginx.
Let’s Encrypt, certificados SSL libres y gratis para asegurar tu web con HTTPS, con consejos para utilizarlo en WordPress y cambiar tu web a HTTPs.
Foto: Matthew Henry

The post Pasa tu web a HTTPS utilizando Let’s encrypt manual o automáticamente, tú decides appeared first on Poesía Binaria.

» Leer más, comentarios, etc...

Picando Código

Jugando en Linux – Comunidad de jugadores en Linux/SteamOS

November 29, 2016 11:00 AM

Siempre es bueno escribir sobre un sitio en español con buenos contenidos. En esta ocasión les cuento sobre Jugando en Linux:

Estamos creando una nueva comunidad de jugadores Linuxeros en Español. Nosotros queremos ser un sitio de referencia con noticias, análisis, artículos… en Español. Sed Bienvenidos a nuestro/vuestro proyecto.

Jugando en Linux

El soporte para nuestro querido sistema operativo de grandes empresas como Valve, AMD, Nvidia, Feral Interactive, y cientos de estudios independientes ha tenido un crecimiento exponencial. Pasamos de tener unos pocos juegos a un catálogo que ya no nos va a dar la vida para completar. Por esto, se agradece la existencia de sitios y comunidade online con contenidos en nuestro idioma.

En Jugando En Linux pueden leer sobre juegos nuevos, títulos que son portados, campañas en Kickstarter, noticias de drivers en Linux, rebajas en distintas tiendas, reseñas y otras novedades del mundillo de aquellos que jugamos en Linux. Cuentan con una sección nueva llamada apt-get, con un resumen semanal de cosas que encuentran por la red. También cuentan con su propio foro, así que dense una vuelta si están en esto de Linux y los videojuegos 🙂

» Leer más, comentarios, etc...

Variable not found

Cómo saber si un nivel de traza está activo en aplicaciones ASP.NET Core/MVC

November 29, 2016 07:55 AM

ASP.NET CoreComo vimos hace algún tiempo, ASP.NET Core viene equipado de serie con una potente infraestructura de logging que ofrece una fórmula sencilla para registrar trazas de lo que va ocurriendo en nuestra aplicación en tiempo de ejecución.

A la hora de registrar las trazas es posible indicar uno de los niveles definidos en la enumeración LogLevel, cuyos miembros son Trace, Debug, Information, Warning, Error y Critical. Estos miembros definen jerárquicamente la "importancia" de los acontecimientos que registramos, de forma que luego podemos configurar los proveedores para que sólo muestren o persistan mensajes a partir de un nivel determinado.

Por ejemplo, fijaos en el siguiente código de una acción MVC, en la que estamos capturando las posibles excepciones que se produzcan para registrar una traza de nivel LogLevel.Trace, de forma que dispongamos de información técnica de calidad cuando esto ocurra:
public IActionResult SomethingImportant()
{
try
{
// Hacer algo importante aquí
}
catch (Exception ex)
{
// Obtenemos información detallada del contexto del error...
var user = _userServices.GetCurrentUserInfo();
var tenant = _tenantServices.GetCurrentTenantInfo();
var context = _contextServices.GetCurrentContextInfo();

// La formateamos para poder enviarla al logger...
var msg = FormatMessage(ex, user, tenant, context);

// Y finalmente registramos el detalle con nivel "Trace"
_logger.LogTrace(msg);
}
return View();
}
Observad que en el código estamos llamando a métodos del modelo, que podrían ser costosos, para obtener información detallada sobre el contexto de la ejecución, como el usuario actual, el tenant u otros datos con objeto de registrarlos en la traza.

Sin embargo, puede haber ocasiones en las que nos interese hacer una serie de operaciones sólo si sabemos que un determinado nivel de logging está activo en alguno de los proveedores que hemos configurado en el arranque de la aplicación.

Por ejemplo, en el ejemplo anterior, si en la aplicación no existe ningún logger configurado para registrar trazas con un nivel LogLevel.Trace,  la llamada a LogTrace() no servirá absolutamente para nada y el coste de preparar la información detallada del contexto habrá sido en vano.

Para estos casos, el interfaz ILogger dispone del método IsEnabled(), mediante el cual podemos consultar si alguno de los loggers configurados en la aplicación está dispuesto a registrar los mensajes del nivel que le pasemos como parámetro. Así, el código anterior podríamos reescribirlo de la siguiente manera:
public IActionResult SomethingImportant()
{
try
{
// Hacer algo importante aquí
}
catch (Exception ex)
{
if (_logger.IsEnabled(LogLevel.Trace))
{
// Obtenemos información detallada del contexto del error...
var user = _userServices.GetCurrentUserInfo();
var tenant = _tenantServices.GetCurrentTenantInfo();
var context = _contextServices.GetCurrentContextInfo();

// La formateamos para poder enviarla al logger...
var msg = FormatMessage(ex, user, tenant, context);

// Y finalmente registramos el detalle con nivel "Trace"
_logger.LogTrace(msg);
}
else
{
_logger.LogDebug($"Exception in SomethingImportant {ex.Message}");
}
}
return View();
}
Como podéis ver, si es posible se registrará el mensaje detallado con nivel LogLevel.Trace, y en caso contrario se registraría un simple mensaje con nivel LogLevel.Debug para dejar constancia de que algo extraño ocurrió.

Publicado en Variable not found.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 259

November 28, 2016 08:05 AM

Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

.NET

ASP.NET

.NET Core / ASP.NET Core

Azure / Cloud

Data

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Otros

Publicado en Variable not found

» Leer más, comentarios, etc...

Koalite

Mitos y leyendas sobre métodos estáticos

November 28, 2016 05:06 AM

El Aquellarre

En los últimos años he notado que cada vez utilizo más los métodos estáticos cuando desarrollo en C# (seguramente en su primo Java me pasaría lo mismo). No es que los busque de forma intencionada, sencillamente hay muchas ocasiones en las que me resulta la opción más natural.

Esto no sería tan extraño si no fuese porque durante mucho tiempo viví bajo la impresión (bastante generalizada) de que los métodos estáticos son evil. No es ni la primera ni la última vez que evoluciona mi opinión con respecto a algo, y siempre está bien analizar los motivos.

Cuándo utilizo métodos estáticos

Ya he dicho que no es algo que busque explícitamente, y de hecho en mi código conviven sin problemas partes en las que se utilizan más métodos estático, dando lugar a un código más funcional (o procedural), con partes mucho más orientadas a objetos.

Lo único que me lleva a decidir entre un estilo u otro es la comodidad a la hora de implementar (y testear, y mantener, etc.) una funcionalidad. Hay cosas que (creo) se modelan mejor desde un punto de vista de objetos, y otras desde un punto de vista de funciones.

Porque eso es lo que son los métodos estáticos: funciones en un lenguaje en el que no tienes más remedio que empaquetar todo en clases.

Hace diez años, Steve Yegge escribió un excelente post sobre verbos y sustantivos en el que se trataba este problema.

Cuando utilizamos un lenguaje como C# o Java en el que todo tiene que estar necesariamente dentro de una clase, acabamos diseñando a partir de sustantivos. Cada clase es un sustantivo. Tienes un Customer. Y un Order. Y un OrderProcessor, que sólo tiene un método, Process. Hay cosas que encajan muy bien en la filosofía de nombres, como Customer/ y Order, y otras que chirrían más, como el OrderProcessor.

Ante esto podemos mantenernos “dentro de los cánones establecidos por el lenguaje y la OOP”, o podemos revelarnos (muy poquito, tampoco nos engañemos) y asumir que parte de nuestro código es más sencillo y más bonito si lo modelamos directamente como funciones que, al final, se traducen en método estáticos.

En general, trato de evitar al máximo las clases que acaban en Manager, Service, Provider, Formatter, etc. Si puedo, aplico alguna de estas técnicas para pasar lógica hacia objetos con más peso, o intento convertirlos en método estáticos.

Por ejemplo, antes que tener esto:

public class OrderProcessor {
  public void ProcessAll(Order[] orders) {
    foreach (var order in orders)
      order.Process();
    DomainEvents.Raise(new OrderBatchProcessed(orders));
  }
}

Prefiero tener esto:

public class Order {
  // Todas las cosas que lleve un order

  public static void ProcessAll(Order[] orders) {
    foreach (var order in orders)
      order.Process();
    DomainEvents.Raise(new OrderBatchProcessed(orders));
  }
}

Si la clase Order llegase a crecer mucho, hay formas de tratar con clases grandes que también tienen sus ventajas.

Hay muchos escenarios en los que resulta cómodo recurrir a métodos estáticos.

En cuanto te alejas un poco del “dominio” (en el sentido más amplio de la palabra) de tu aplicación, y empiezas a necesitas funciones para convertir de un tipo de objeto a otro. O para formatear un objeto para mostrarlo en pantalla. O para serializarlo a XML o JSON de una manera específica.

Todo este tipo de operaciones suelen realizarse sin dependencias externas y son perfectos candidatos para implementar como métodos estáticos en lugar de colgarlos de alguna clase arbitraria solo para sentirte más OOP Master.

También suelo utilizarlos como fachadas para tratar con estado global. Es cierto que intento minimizar el estado global, pero a veces no queda más remedio que asumir la realidad, y tener una fachada estática para lanzar eventos de dominio, traducir recursos y cosas por el estilo ayuda a lidiar con él.

Cazando mitos

Muchos de los que piensan que los métodos estáticos son terribles acaban por crear objetos sin estado ni dependencias que contienen el método estático. Eso obliga a instanciar una clase para invocar un método que no depende para nada del resto de la clase.

¿Quién no ha visto este código en las típicas katas de TDD?

public class StringCalculator {
  public int Add(string numbers) {
    // Hacer algo con numbers 
  }
}

¿Por qué crear un clase como esa para tener dentro una función cuya salida depende únicamente de los parámetros de entrada?

Entre los argumentos que se usan para defender ese estilo está el de “las clases y métodos estáticos no son relamente orientación a objetos”.

Francamente, hoy en día no veo eso como un argumento válido. Para mi esto no va de poder aplicar al código una etiqueta de “100% OOP Certified” (o, para el caso, “100% FP Certified”), sino de sacarle partido a las herramientas que tenemos. Entiendo el argumento en un contexto didáctico, donde estás intentando aplicar al máximo un paradigma, pero en un entorno real hay que ser más pragmático.

También hay quien piensa que los métodos estáticos son más difíciles de testear, pero realmente no es así. De hecho, en el ejemplo anterior es (marginalmente) más sencillo testear StringCalculator.Add que new StringCalculator().Add y hay escenarios en los que la introducción de un método estático construido de la forma adecuada puede simplificar mucho la forma de testear, como explicaba en este post sobre cómo refactorizar tests unitarios para eliminar dependencias. Esa es una técnica que utilizo muy frecuentemente y me gusta mucho para aislar la parte que quiero testear de lo que no considero interesante. La clave para que algo sea fácil de testear no es si es estático o no, sino el tipo de dependencias que tiene y su relación con ellas.

En realidad, cuanto se habla de que los métodos estáticos son complicados de testear no es por el propio método estático: es por cómo testear aquello que depende del método estático. Normalmente cuando pasa es porque quieres (o necesitas) aislarte de la implementación real del método estático.

Si es porque consideras que los tests unitarios sólo pueden abarcar una clase y hay que aislarlos de todas sus dependencias, te invito a que reconsideres tu postura sobre qué constituye la unidad en un test unitario.

Si aun así no quieres invocar el método estático porque accede a recursos externos o es más lento, siempre tienes varias alternativas. Llegado el caso, podrías encapsular el método estático en una clase y usar esa clase como dependencia de lo que estás testeando. Yo no haría esto de forma especulativa, pero si fuera necesario refactorizar hacia ello es fácil. De todas formas, la solución más sencilla es inyectar el método estático como dependencia de lo que necesites testear.

Puedes pasar de esto:

public void SomeBigProcess() {
  var numbers = numberProvider.GetNumbers();
  var result = StringCalculator.Add(numbers);
  var mailBody = $"Result is {result}";
  mailSender.Send(mailBody);
}

A esto:

public void SomeBigProcess() {
  SomeBigProcess(StringCalculator.Add);
}

public void SomeBigProcess(Func<string, int> add) {
	var numbers = numberProvider.GetNumbers();
	var result = add(numbers);
	var mailBody = $"Result is {result}";
	mailSender.Send(mailBody);
}

Ahora tienes un método al que le puedes inyectar el método estático y testearlo como más te guste. Incluso en este caso es algo más fácil de testear que teniendo un StringCalculator porque en lugar de necesitar un mock/fake/stub, puedes crearte al vuelo al función que vas a usar en el test.

Algunos incluso podrían decir que no usar un método estático es un problema de eficiencia porque obliga a instanciar un objeto StringCalculator para nada y eso mete presión al GC. Vale, puede ser, pero no es mi caso. Es sumamente raro que tenga un código en el que me preocupe tanto el consumo de memoria y las pausas del GC como para que eso sea relavante.

Otro mito que arrastran los métodos estáticos es que no son seguros en un entorno multihebra.

Esta confusión puede venir motivada por el uso de variables estáticas. En un entorno multihebra, tener estado mutable estático es una receta segura para dolores de cabeza. Tenemos un punto global, del que dependen todas las hebras, que puede ser modificado por cualquiera y hace que las hebras queden acopladas entre si temporalmente (dependiendo de en qué orden se ejecuten y modifiquen el estado global, el resultado será uno u otro).

Sin embargo, cuando hablamos de métodos, este problema no existe. A menos que accedan a variables estáticas pero, claro, en ese caso da igual que el método lo sea o no: el problema es la variable, como veíamos antes.

Un método estático que depende sólo de sus parámetros de entrada es completamente seguro en un entorno multihebra. En realidad, es lo más seguro que puede haber porque no accede a estado global y ni siquiera accede a estado local a la instancia de la clase, puesto que no pertenece a ninguna instancia.

El problema es que, mal utilizados, los métodos estáticos suelen ir acompañados de variables estáticas y acaban dando lugar a situaciones un tanto desastrosas. Bueno, en realidad, mal utilizado, casi todo puede dar lugar a situaciones desastrosas.

Conclusión

Mezlar métodos estáticos (funciones) y clases no debería ser algo tan raro. A fin de cuentas, los que hayan programado en Javascript o Python estan acostumbrados a ello y seguro que han podido comprobar las ventajas de disponer de más herramientas a la hora de modelar la solución a un problema.

Parte de los problemas que se han atribuido tradicionalmente a los métodos estáticos son perfectamente salvable, y otros directamente no son problemas.

En mi opinión, parte del recelo hacia ellos viene de la época en la que la OOP no estaba tan extendida, había mucha gente que venía de programacíon estructurada clásica (C, Visual Basic), y se no se aprovechaban las características de los lenguajes orientados a objetos: seguían programando todo con funciones y estructuras de datos. No es que eso sea malo, pero cuando llevabas eso a un lenguaje que no estaba pensado para ello, y además lo hacía alguien sin experiencia, el resultado era catastrófico (todos hemos visto código así).

A día de hoy me gustaría pensar que no es tan necesario estar con el palo encima de la gente y que tenemos criterio suficiente para poder usar las herramientas que tenemos a nuestra disposición y sacarles partido. Tal vez estemos pegando a los monos equivocados.

Imagen: El Aquellare, de Francisco de Goya.

Posts relacionados:

  1. Recopilatorio sobre modelos de dominio

» Leer más, comentarios, etc...

Blog Bitix

Guardar contraseñas de forma segura con KeePassX

November 26, 2016 09:00 PM

KeePassX

La mayor parte de servicios usan aún como forma de autenticación el método de usuario y contraseña. Si la contraseña proporcionada conocida solo por su usuario es correcta el sistema confía en que el usuario es quien dice ser. Las contraseñas debería ser difíciles de averiguar, se recomienda que tenga una longitud mínima de 8 caracteres y que contenga letras en minúscula y mayúscula, números y símbolos, sin embargo, cuanto más fuerte y difícil sea de averiguar más difícil será recordarla. Además, idealmente se debe utilizar una contraseña distinta en cada servicio para evitar que descubierta la contraseña por un fallo de seguridad en cualquiera de en los que se use pueda accederse a todos los otros servicios que use ese usuario utilice, por lo que el número de contraseñas a recordar pueden ser numerosas de modo que muchos usuarios terminan usando la misma contraseña en varios servicios con el riesgo que conlleva. Dado que recordar una contraseña fuerte para cada servicio es difícil y mantenerlas guardadas en un archivo de texto o en un papel no es lo más recomendable podemos usar un programa que las almacene.

Uno de estos programas es KeePassX, básicamente es una base de datos de contraseñas que se almacenan de forma segura y cifrada y protegidas por una contraseña maestra. La información básica que podemos guardar es el nombre del servicio y su URL, el usuario que usamos en ese servicio y la contraseña. Con KeePassX podemos crear grupos de contraseñas que nos permitan buscarlas de forma más sencilla.

Instalado el paquete de KeePassX de nuestra distribución GNU/Linux o el binario para nuestro sistema operativo lo primero que deberemos hacer es crear una base de datos que protegeremos con una contraseña maestra, podemos guardar la base de datos en un archivo en la ubicación que deseemos.

Lo siguiente será crear una entrada con el usuario y contraseña de un servicio.

Una vez almacenada la credencial podemos copiar al portapapeles el usuario y contraseña de esa credencial para usarla en el servicio. También podremos ver la contraseña no protegida con asteriscos sino los caracteres originales.

KeePassX es una herramienta que no tiene más complejidad, podemos asociar alguna información más a la credencial con atributos adicionales y archivos adjuntos pero no es imprescindible.

Si somos nosotros los que implementamos un servicio con el método de autenticación de usuario y contraseña deberíamos almacenar las contraseñas de forma segura usando «password salted hasing».

Otras formas de guardar las contraseñas es en un archivo cifrado con GPG que desciframos cuando queramos usar alguna contraseña o en un sistema de archivos cifrado como con EncFS que lo montamos para acceder a archivo de texto con las contraseñas.

KeePassX posee una utilidad para generar contraseñas únicas para cada servicio con cierta complejidad, podemos variar la longitud, si incluye símbolos, y mayúsculas y minúsculas. StrongPassowrdGenerator en una página web con la que podemos generar contraseñas usando estas mismas preferencias desde el navegador.

» Leer más, comentarios, etc...

Jesús Perales

Jackson y @Transient

November 25, 2016 10:29 PM

Comúnmente cuando estamos desarrollando en Java necesitamos que nuestra entidad tenga propiedades que NO deben estar mapeadas a la base de datos usamos la anotación @Transient.

El problema surge cuando queremos que esa propiedad sea serializada por Jackson para enviarla en forma de JSON (en mi situación) en respuesta a una petición de un Rest Controller de Spring.

Para resolverlo será necesario sobrescribir el objeto que mapea nuestras clases de Java, tal cual como se hizo para evitar los errores al serializar propiedades Lazy Load en este post.

Pero en esta ocasión deshabilitaremos esta funcionalidad ya que, como se dijo antes, queremos que el mapeo ignore la propiedad, pero no queremos que la serialización la ignore.

Las clases relacionadas a esta configuración son Hibernate4Module, el cual tiene un ENUM dentro con las funcionalidades que podemos deshabilitar.

Al final deberá quedar así

package com.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;

public class HibernateAwareObjectMapper extends ObjectMapper{

private static final long serialVersionUID = 1L;

public HibernateAwareObjectMapper() {
Hibernate4Module module = new Hibernate4Module();
module.disable(Hibernate4Module.Feature.USE_TRANSIENT_ANNOTATION);
registerModule(module);
   }
}

No debemos olvidar que este clase debe estar en nuestro XML de configuración de Spring.

<mvc:annotation-driven>
    <mvc:message-converters>
        <!-- Use the HibernateAware mapper instead of the default -->
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="ruta.a.tu.clase.HibernateAwareObjectMapper" />
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

Hay que tener en cuenta que si deshabilitamos esta funcionalidad la única forma en que podremos hacer que se ignoren propiedades de una clase en el momento de la serialización será utilizando la anotación @JsonIgnore.

Fuentes

» Leer más, comentarios, etc...

Blog Bitix

Instalar programas con Homebrew en macOS

November 25, 2016 09:30 PM

Para no tener que descargar binarios e instalarlos manualmente y estar pendiente de nuevas versiones que se publiquen en un futuro en macOS está Homebrew. Homebrew es un gestor de paquetes similar a los existentes en las distribuciones GNU/Linux con el que podremos buscar software, instalar, actualizar, ver que hemos instalado, cuales están desactualizados, iniciar y parar servicios y desinstalar los paquetes o programas. Esta es una guía básica sobre como instalar software en macOS con Homebrew y como instalar iTerm2 que es una mejor terminal que la propia del sistema con iterm.

Apple
macOS

Como nuevo usuario de mi primer mac he tenido que empezar instalando los programas que voy a usar. Una de las cosas buenas de las distribuciones GNU/Linux es la forma de obtener e instalar programas. Cada distribución de GNU/Linux tiene su repositorio de paquetes y programas de los que el gestor de paquetes obtiene e instala. Los gestores paquetes se encargan de instalar, actualizar y desinstalar cada paquete junto las dependencias que requiera. Con el gestor de paquetes y desde la terminal es posible instalar múltiples programas rápidamente con un comando. En Windows y macOS los programas se instalan descargando un binario y ejecutándolo que inicia un asistente. Instalar programas de esta forma en Windows y macOS tiene los inconvenientes de que hay que hay que ir a la página oficial de programa y descargar el último binario disponible, además cuando se publique una nueva versión hay que descargar el nuevo binario y volverlo a instalar, también es una fuente de introducción de virus si se descarga e instala el software de fuentes no confiables. En GNU/Linux el gestor de paquetes se encarga de actualizar los paquetes y programas que estén desactualizados cuando haya nuevas versiones.

En macOS existe un gestor de paquetes similar a los existentes en GNU/Linux, Homebrew se define así mismo como el gestor de paquetes que le falta a macOS. Con Homebrew podemos instalar los programas y mantenerlos actualizados sin tener que estar observando cuando se publica una nueva versión de cada programa. Con Homebrew también podremos instalar muchos de los comandos que están disponibles en GNU/Linux como wget, cmus, gimp, … Hombrew Cask es un añadido que proporciona los mismo para los binarios de los programas de macOS. Con estas dos herramientas podemos instalar y mantener actualizado la mayor parte del software que utilicemos.

Para instalar Hombrew ejecutamos el siguiente comando en la terminal:

El siguiente comando nos permitirá instalar versiones anteriores a las últimas, por ejemplo, Java 7:

Lo siguiente será buscar los programas que queramos:

Para instalar Firefox, Google Chrome, VirtualBox, Docker, Java 8 y Java 7, Atom e iTerm2:

Algunos otros programas que podemos instalar si programamos son:

Con jenv podemos cambiar entre las versiones de Java 8 y Java 7:

Los servicios como MySQL o Redis podemos iniciarlos y pararlos, además de ver cuales hemos instalado:

También podemos listar que paquetes y programas tenemos instalados:

Para ver que programas y paquetes tenemos desactualizados:

Para actualizar todos los paquetes desactualizados o actualizar uno individualmente:

Si queremos mantener desactualizado un paquete podemos fijar la versión que tengamos instalada:

Y para desinstalar paquetes:

La terminal incluida de serie en macOS es muy básica por ello mucha gente suele instalar una más avanzada como iTerm2. iTerm2 añade funcionalidades como pestañas y podemos dividir una terminal horizontal y verticalmente. También se puede instalar oh-my-zsh que permite gestionar la configuración del intérprete de comandos zsh pudiendo añadir temas para modificar el prompt del sistema o cambiarlo según la información del directorio actual, por ejemplo, si estamos en un directorio de git veremos en que rama estamos y si hay cambios realizados.

Terminal iTerm2

» Leer más, comentarios, etc...

Blog Bitix

Mi primer Mac, yo usuario de GNU/Linux

November 25, 2016 09:00 PM

Hace ya más de un lustro pase de usar Windows a usar GNU/Linux incluso en el trabajo, ahora por motivos laborales no me queda opción que usar un Mac, el primer Mac que usaré. En casa a nivel personal seguiré usando la distribución Arch Linux y antes de empezar a usar un Mac seguirá siendo así, ¿usar un Mac me hará cambiar de opinión y usaré un producto de Apple incluido a nivel personal en un futuro?

Apple
macOS

Hasta el momento en el trabajo podía usar GNU/Linux como sistema operativo, concretamente la distribución Arch Linux con GNOME y Docker para el entorno de desarrollo. Sin embargo, algunos cambios han hecho que tuviese que elegir entre Windows que no uso desde hace ya más de un lustro o macOS que usaría por primera vez. Dado que macOS es más similar a GNU/Linux por seguir ambos la filosofía Unix al final opté por un Mac como prácticamente la totalidad de mis compañeros de trabajo. Una razón es que muchas de las herramientas y comandos que están disponibles en GNU/Linux lo están también en macOS.

Usar un Mac por primera vez es algo relevante desde el punto de vista tecnológico para alguien que le gusta la tecnología. Este artículo lo escribo para mi yo futuro de dentro de unos años para ver si la preferencia del software libre y GNU/Linux que tengo ahora no se ve doblegada en parte por Apple y morderé la manzana más después de escribir cosas como Sobre los ínfimos impuestos que paga Apple o Como sería si Microsoft, Apple y Linux… .

Nunca he usado un producto de Apple salvo tocarlos un poco en las tiendas y es que convencido del software libre y el alto precio que tienen nunca he estado atraído por la marca de la manzana mordida, así que comienzo completamente desde cero empezando por tener que aprender de nuevo muchos de los atajos de teclado y combinaciones de teclas. Simplemente por curiosidad conseguí usar macOS en una máquina virtual con VirtualBox que es posible tanto en Windows como en GNU/Linux.

Una de las cosas que me gustaba de Arch Linux es su modelo rolling release de modo que en cada actualización del sistema con pacman -Syu tenía las últimas versiones de cada programa y paquete, esto hace que no necesite reinstalar cada nueva versión ni tuviese que preocuparme de las versiones de los programas, lo único que sabía es que siempre tenía la última versión. Hasta ahora iba por 3 años desde que instalé Arch Linux por última vez. Por lo poco que me he informado en los Mac existe Homebrew y Homebrew Cask que es un gestor de paquetes similar a la forma de distribuir software con los gestores de paquetes de las distribuciones GNU/Linux. Casi todo el software que he necesitado está disponible en Homebrew incluyendo Java 8, Java 7, Firefox, Google Chrome, MySQL, Docker, VirtualBox, Git o atom incluidos programas como vim, gimp, cmus o meld.

El Mac que usaré no es de los últimos con panel táctil en la parte superior del teclado ese que ha eliminado una tecla física tan importante también para los desarrolladores como la tecla escape. El precio del modelo de principios de 2015 está valorado en unos $2000 junto con otros $120 en adaptadores y periféricos, tiene buenas especificaciones siendo un producto de gama alta con sobre todo SSD, pantalla y touchpad y aunque 16 GiB son suficientes es extraño que en ningún modelo de MacBook Pro aún no haya opción de instalar 32 GiB para los usuarios más exigentes. Aún así por ese precio uno adquiere varios portátiles como los Slimbook y el último pasados unos años tendrá mejores especificaciones en varios aspectos que cualquier Mac actual.

En mis primeras horas de uso de un Mac destacaré la pantalla retina, su gran resolución de 2560x1600 hace que el texto y las imágenes se vean muy bien sin notar los píxeles, teniendo un monitor de 23” con resolución 1920x1080 o una pantalla de portátil de 14” de resolución 1600x900 las diferencias son claras. Aún así esto es a costa de que la resolución equivalente en un PC sea aproximadamente de 1280x800 en la configuración por defecto haciendo que parezca que entran pocas cosas en la pantalla, otras resoluciones equivalentes seleccionables son 1680x1050, 1440x900, 1280x800 y 1024x640. El touchpad también parece ser otra característica diferenciadora y destacable aunque aún no conozco muchos de los gestos que permite. La interfaz de escritorio de macOS y de GNOME es similar en muchos aspectos con la barra superior, el lanzador de aplicaciones Launchpad, la vista de ventanas Dashboard y la vista de actividades de GNOME.

Yo futuro, ¿habrás caído en la tentación? ¡Resiste! No olvides y piensa por que empezaste a usar GNU/Linux y por que seguiste usando Arch Linux… por aprender, por el software libre, por la privacidad, por no pagar costosas licencias de software privativo o usar cracks, por no tener software espía, por ser el dueño del equipo y no de la marca cuando decida dejar de darle soporte…

Por lo menos ahora podré hablar con un poco más de criterio cuando lo haga sobre Apple y sus productos, como macOS, los MacBook, los adaptadores y periféricos como el Magic Mouse. El siguiente paso es cómo instalar software en macOS con Homebrew.

Información del sistema y escritorio de macOS

» Leer más, comentarios, etc...

proyectos Ágiles

Agile White Book de AXA liberado

November 24, 2016 06:18 PM

AXA (EMEA-LATAM Emerging Markets) ha liberado su Agile White Book, descargable en el siguiente enlace : http://www.slideshare.net/AXAEMEALA/documents

awb-axa-emeala

Este libro es una guía de Agile que cubre los conceptos fundamentales y proporciona una terminología común para los diferentes países de la región EMEA-LATAM (aspecto importante dados sus diferentes niveles de madurez en Agile). Sirve como punto de entrada para futuros Scrum Masters que van a empezar a trabajar en Agile en AXA y esperamos que pueda servir también a otras organizaciones que están comenzando en este camino basado en personas y trabajo en equipo“.

Algunos ejemplos de contenido:

readiness-criteria

metrics-balanced-scorecard

También cuenta con varios checklists que puede ser útil consultar:

PBL-Refinement-checklist.jpg


» Leer más, comentarios, etc...

Jesús Perales

Gitlab, configurar backups automaticos

November 24, 2016 05:00 PM

Para configuración de los backups de Gitlab y que se ejecuten de forma automática, es necesario configurar crons de GNU/Linux para que ejecuten las tareas en la hora y la frecuencia deseada.

Los comandos son los siguientes para configurar o cambiar la generación de respaldos en Gitlab en Ubuntu Server.

Entramos como súper usuario:

  • sudo su -

Abrimos el editor de los jobs(crons) que se ejecutaran:

  • crontab -e

Seleccionamos el editor de nuestra preferencia, se recomienda seleccionar NANO que es la opción numero 2, por ser mas sencillo.

Agregamos la siguiente linea al final del archivo.

  • 1 22 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create CRON=1

Recordemos que la configuración de los crons tiene la siguiente estructura.

| minutos | horas | días | meses | años.

En nuestro caso elegimos que corra a las 10:01 pm todos los días.

Si esto se nos hace complejo siempre podremos recurrir a un generador de crons:

http://www.crontab-generator.org/

También debemos respaldar los archivos de secretos de Gitlab, así que agregaremos 2 crons mas.

1 22 * * * cp /etc/gitlab/gitlab.rb /var/opt/gitlab/backups/gitlab.rb.backup.$(date --iso-8601=seconds) CRON=1

1 22 * * * cp /etc/gitlab/gitlab-secrets.json /var/opt/gitlab/backups/gitlab-secrets.json.backup.$(date --iso-8601=seconds) CRON=1

Al final nuestro archivo de crons se debe ver así.

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command

## Generacion del resplado de gitlab todos los dias a las 10 pm(22 horas)
## Ver la documentacion https://gitlab.com/gitlab-org/gitlab-ci/blob/master/doc/raketasks/backup_restore.md
1 22 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create CRON=1
1 22 * * * cp /etc/gitlab/gitlab.rb /var/opt/gitlab/backups/gitlab.rb.backup.$(date --iso-8601=seconds) CRON=1
1 22 * * * cp /etc/gitlab/gitlab-secrets.json /var/opt/gitlab/backups/gitlab-secrets.json.backup.$(date --iso-8601=seconds) CRON=1

Podemos encontrar la ejecución de los crons con el siguiente comando:

grep CRON /var/log/syslog

Fuentes:

» Leer más, comentarios, etc...

Jesús Perales

Migrar Gitlab a otro servidor

November 23, 2016 03:48 PM

En un articulo anterior ya hablamos de que es y como instalar Gitlab, ahora toca hablar de como migrar lo a otro servidor.

Para poder migrar toda nuestra información de Gitlab (Issues, MR, Snippets, Usuarios, Proyectos, Grupos, etc) a otro servidor tendremos que cumplir con los siguientes requisitos, al menos para este tutorial.

  • Servidor de Gitlab actualizado.

  • El servidor nuevo deberá tener la misma versión de Gitlab del anterior servidor.

  • Acceso directo por ssh de un servidor a otro.

Manos a la obra.

Primero debemos generar un respaldo de nuestro servidor actual con el siguiente comando:

sudo gitlab-rake gitlab:backup:create

Esto generara un archivo con este formato xxxxxxxxx_gitlab_backup.tar

Toca pasar el backup,comúnmente se encuentra en /var/opt/giltab/backups/ con scp.

sudo scp /var/opt/giltab/backups/xxxxxxxxx_gitlab_backup.tar user@otherserver:/home/user

Algo muy importante este que también debemos pasar los archivo gitlab.rb y gitlab_secrets.json (minimamente) de forma manual

Estos archivos se encuentran en /etc/gitlab, también usaremos scp para enviarlos al nuevo servidor.

sudo scp /etc/gitlab/gitlab.rb user@otherserver:/home/user

sudo scp /etc/gitlab/gitlab_secrests.json user@otherserver:/home/user

Al llegar este punto ya tendremos toda la información en el nuevo servidor, solo queda montarla en los directorios correctos.

Primero acomodaremos los archivos gitlab.rb y gitlab_secrets.json.

sudo cp gitlab* /etc/gitlab/

El siguiente es el respaldo con el comando:

sudo cp xxxxxxxx_gitlab_backup.tar /var/opt/gitlab/backups/

Cambiamos el usuario al que pertenece el respaldo con el comando:

sudo chown -R git /var/opt/gitlab/backups/

Para montar el respaldo corremos este comando:

sudo gitlab-rake gitlab:backup:restore BACKUP=1476213812

Y escribimos yes cada vez que nos lo pida.

Por ultimo re-configuramos Gitlab y lo reiniciamos con los siguientes comandos:

sudo gitlab-ctl reconfigure

sudo gitlab-ctl stop

sudo gitlab-ctl start

En este punto ya deberíamos poder entrar a revisar que toda nuestra información se encuentra allí.

Fuentes

» Leer más, comentarios, etc...

Jesús Perales

Como instalar Gitlab

November 23, 2016 03:47 PM

Gitlab es una herramienta al estilo Github, pero a diferencia de este ultimo tiene una licencia que permite instalarlo en servidores propios y gestionarlos desde una interfaz web.

Es posible administrar Personas, Grupos y permisos en los proyectos.

Es posible instalar Gitlab en cualquier plataforma UNIX, aunque solo tiene soporte oficial para algunas distribuciones.

En nuestro caso haremos la instalación en un servidor Ubuntu 16.04 (que es el recomendado en esta fecha), el proceso de instalación es muy sencillo.

Actualizamos nuestro servidor:

sudo apt-get update && sudo apt-get upgrade -y

sudo apt-get dist-upgrade

Instalamos algunos paquetes necesarios, aparecerá una pantalla y allí utilizaremos la configuración de Sitio de Internet de Postfix, en ingles Internet Site:

sudo apt-get install curl openssh-server ca-certificates postfix

Agregamos el repositorio de Gitlab:

curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh|sudo bash

Instalamos Gitlab:

sudo apt-get install gitlab-ce

sudo gitlab-ctl reconfigure

Al terminar el ultimo comando ya deberíamos poder acceder a Gitlab
desde la dirección IP de nuestro servidor.

Fuente:

» Leer más, comentarios, etc...

Poesía Binaria

Primeras decisiones para crear tu tienda online con WooCommerce

November 23, 2016 09:19 AM

photo-1441984904996-e0b6ba687e04_2
Hoy en día, si queremos montar una tienda online tenemos un mundo de posibilidades. Lo primero será decidir si la vamos a montar nosotros o vamos a recurrir a una empresa o a personal especializado para ello. Todo depende del tiempo, dinero y conocimientos que tengamos para ello y de lo sinceros que hayamos sido con nosotros mismos en esos tres factores.
Como primera posibilidad, empezaré por la más dura, programar nuestra tienda, a mano, como unos valientes que somos y llevamos toda la vida programando o al menos el número de horas que hemos programado en nuestra vida se acerca a las 6 cifras (10h al día durante unos 11 años), aún así, seguramente nos basemos en algún framework para nuestro lenguaje de servidor preferido. Lo mejor y lo peor de este método es que si tenemos un problema, los únicos culpables somos nosotros, y puede que surjan muchos problemas. Otro factor positivo es que si nos embarcamos en un proyecto así vamos a aprender muchísimo y eso siempre es bueno. Lo malo, es que también vamos a tardar mucho, además, vamos a entrar en tiendas de la competencia que van a tener muchas cosas chulas, las querremos tener y podemos tardar mucho tiempo en implementarlas.

Otra posibilidad es utilizar un software de tienda online ya hecho y aquí soy siempre partidario de utilizar software libre o de código abierto, como Magento[1], Prestashop, OpenCart u otros muchos. Vamos a ir algo más rápido, todo el núcleo de nuestra tienda estará ya programado y es algo que tienen en común todas las tiendas. Gestión de categorías, productos, páginas estáticas, clientes, carro de la compra, envíos, pagos, facturación y más. Prácticamente tendremos que elegir un tema, buscar algunos plugins útiles (los hay gratis y de pago) y meter nuestros productos… Lo malo es que nos va a tocar programar, da igual cómo nos pongamos, pero al menos una línea de código tendremos que editar y lo malo es que para editar ese código tendremos que aprender un poco cómo funcionan dichas tiendas en línea por dentro. En mi caso particular, he utilizado Magento y al principio es un poco lioso cómo está programado.

He querido separar otra opción más, relacionada con la anterior: utilizar WordPress + WooCommerce[2]. Además, es la opción que recomiendo si no te quieres calentar mucho la cabeza. Primero porque es ligero, como WordPress y segundo porque es fácil de programar y de gestionar. Si has utilizado WordPress sabrás categorizar y gestionar productos, envíos, clientes y demás; y si has tocado alguna vez algo de código en WordPress, habrás visto que es muy fácil y además podrás aprovecharte del ecosistema WordPress, es decir, podrás utilizar shortcodes en los productos, utilizar plugins de WordPress y utilizar WP-CLI[3] para automatizar el proceso. Ni que decir tiene que a estas alturas toda tienda en línea que se precie tiene también un blog, y ya que tenemos WordPress instalado podemos utilizar éste para todo, y así tendremos el mismo look&feel sin que nos cueste mucho.

La ventaja de usar una solución libre o de código abierto

Personalmente creo que una solución libre siempre será más segura ya que, al estar su código disponible, todo el mundo puede ver sus fallos, y cualquiera puede aportar soluciones a muchos de los problemas que puedan surgir. Al mismo tiempo, muchas personas podrán colaborar en el desarrollo y la documentación de la plataforma. Con lo que tendremos en nuestras manos una aplicación muy robusta y muy probada.
Aunque pueda parecer contradictorio, las soluciones privativas (no nos permiten ver su código, ni mucho menos mejorarlo, suele ser ilegal hacer copias de ellas…), no suelen ser más seguras porque el número de personas que mire es mucho menor; es más, a veces suele haber problemas conocidos que tardan años en solucionarse.

Por otro lado, tenemos que tener presente el hecho de que libre no significa gratis. Aunque mucho software libre nos lo podemos descargar y utilizar sin restricciones, en ocasiones puede que tengamos que pagar por él (no es el caso de WordPress + WooCommerce, pero sí de algunos plugins); en muchos de los casos los plugins serán nuestros y podremos hacer lo que queramos con ellos, tal vez hayamos pagado por un periodo de soporte en el que recibiremos actualizaciones de los mismos. También puede darse el caso de que tengamos que pagar por WordPress + WooCommerce + plugins + configuración, en ese caso estaremos pagando por el trabajo de la persona que nos monta la tienda en línea, es decir estamos pagando por el tiempo invertido y los conocimientos de la persona que nos da el producto listo para utilizar y a nuestro gusto y no por el software.

Sobre Woocommerce

¿Quieres instalar un WordPress con Woocommerce en un tiempo récord? Contamos con que el directorio www que vamos a crear es donde nuestro servidor lee la web, accedemos por SSH a nuestro server y nos ponemos a teclear:

# Creamos base de datos y contraseña para mi base de datos
mysql -uroot -p
CREATE SCHEMA MyShop;
Query OK, 1 row affected (0.01 sec)
GRANT ALL PRIVILEGES ON MyShop.* TO ‘shopdbuser’@’10.1.1.%’ IDENTIFIED BY ‘internalpassword';
QUIT
Bye
# Descargamos e instalamos WordPress
wp core download --path=www --locale=es_ES
Creating directory ‘/var/www/myshop.com/www/’.
Downloading WordPress 4.6.1 (es_ES)…
Success: WordPress downloaded.
wp core config --dbname=”MyShop” --dbuser=”shopdbuser” --dbpass=”internalpassword” --dbhost=”localhost” --dbprefix=”shop_” --locale=es_ES
Success: Generated ‘wp-config.php’ file.
wp core install --url=”http://myshop.com/” --title=”Mi tienda online” --admin_user=admin --admin_password=”contraseña” --admin_email=”mi@correo.com”
Success: WordPress installed successfully.
# Instalamos y activamos WooCommerce
wp plugin install woocommerce
wp plugin activate woocommerce
# En muchos proveedores, es necesario establecer los permisos correctos para que todo vaya bien
sudo find -type d -exec chmod 775 {} \;
sudo find -type f -exec chmod 664 {} \;
sudo chown -R www-data *

Lo primero que hemos hecho ha sido crear una base de datos y un usuario (muchos proveedores ya nos dan esto), lo siguiente es configurar WordPress con dicha base de datos y establecer un usuario de administración (admin y contraseña no son buenas credenciales de acceso, sed originales). Lo siguiente será entrar en nuestro panel de administración dentro de nuestrodominio.com/wp-admin e identificarnos. Desde el minuto cero, Woocommerce nos guiará en la configuración:
Screenshot 17-11-2016-191140

Ya sólo nos quedará ponernos a insertar productos, para lo que nos puede ayudar un plugin como woocommerce-csvimport[4] y configurar las pantallas y textos de nuestra web (quiénes somos, política de cookies, envíos y demás textos legales). Ya que estamos sobre WordPress, y es muy fácil de manejar, podremos conseguirlo en muy poco tiempo y además podremos utilizar todas las ventajas de edición que nos proporciona WordPress: inserción de shortcodes en las páginas, inserción de vídeo, tweets y mucho más de una forma muy visual y atractiva. Además, disponemos de un gran catálogo de extensiones que podemos configurar tanto para WooCommerce (para el caso de productos, envíos, pagos, etc) como para WordPress (por si queremos botones sociales, cajas de Twitter, Facebook, caché de páginas, seguridad, etc).

Por si fuera poco, si te apetece o necesitas escribir algo de código, aprender cómo hacerlo es muy fácil y tenemos mucha documentación en los codex de WordPress[5] y de WooCommerce[6]. Admás, si quieres empezar a crear plugins para WordPress puedes empezar por aquí[7].

Alojamiento para tu tienda

Todo proyecto online necesita un alojamiento. Esto será un equipo informático conectado a Internet de alta velocidad las 24h, generalmente estos ordenadores suelen estar en centros de datos que realmente cuidan los equipos que mantienen controlando tanto temperatura, humedad y acceso físico entre otros. Además, los equipos suelen ser grandes y tener servicios de alimentación alternativa (por si se va la luz o hay variaciones en la línea), servicios de Internet alternativos (por si se desconecta de la red) y mantenimiento (personal que cambia los equipos si fallan, vigila ataques, hace copias de seguridad, etc); por eso no es buena idea alojar una web en un ordenador de casa (para hacer experimentos está bien, pero no para nuestro negocio).

Todo aquel que monta un negocio online, quiere que vaya bien, empieza con muchísima ilusión y considera su tienda como si fuera un hijo. Y como tal, no queremos que le falte de nada, y que tenga siempre buena salud, y cuando se pone malo, nos desesperamos y somos capaces de movilizar a medio Internet para recuperarlo. El hosting WooCommerce de SiteGround está aquí para ayudarnos. Por un lado, nos proporcionan tres planes que se adaptan a nuestras necesidades: tal vez al principio no tengamos muchas visitas, pero con el tiempo iremos creciendo, así nuestro hospedaje se adaptará a nosotros. Además:

  • Nos proporcionan un certificado SSL (recuerda que Google lleva un año penalizando webs no seguras y Chrome 56, en 2017, marcará las webs que no sean HTTPS como inseguras[8]).
  • Seguridad y actualizaciones de parte de SiteGround: Ellos se encargan de que tengamos todo actualizado, no entren intrusos y nuestro servicio se encuentre online todo el tiempo. Nosotros sólo tendremos que preocuparnos de vender, actualizar stock y ¡dar mucha guerra en redes sociales para que nuestros clientes conozcan que tenemos Black Friday!)
  • Si tenemos algún problema, les podemos llamar a cualquier hora (24×7) o contactar por chat. Por mi experiencia siempre que he hablado con ellos han sido muy amables y muy rápidos.
  • ¡¡Tenemos SSH!! Yo sin una terminal no sé vivir y si de verdad aprecias tu tiempo, te lo recomiendo, gracias a WP-CLI se pueden realizar muchísimas tareas de mantenimiento sobre WordPress en un tiempo récord. Además tener SSH nos puede ayudar a hacer algunos tipos de importaciones, descargas masivas de imágenes y automatizar procesos que a golpe de ratón serían eternos.
  • Almacenamiento SSD, PHP7 y mucho más para que tu web vuele.
  • Y mucho más…

Referencias

Al ser un post patrocinado, he decidido incluir todos los enlaces al final. Así los enlaces a la marca van primero, que seguro que le gusta a los buscadores.

Foto: Clark Street Mercantile

The post Primeras decisiones para crear tu tienda online con WooCommerce appeared first on Poesía Binaria.

» Leer más, comentarios, etc...

Navegapolis

4 "tweet-conceptos" para orientarnos en la gestión de proyectos.

November 22, 2016 01:53 PM

encaje

proyectoProyecto

Conjunto de actividades necesarias para lograr un resultado único y definible.

Proyecto delimitado1.- Proyecto delimitado

El que tiene como objetivo conseguir un resultado inicialmente acotado, claramente definido, y sin previsión de modificaciones sustanciales de la definición inicial durante la ejecución. Ejemplo: Construcción de una casa.

proyecto progresivo2.- Proyecto progresivo

El que tiene como objetivo conseguir un resultado partiendo de su idea general, que se desarrolla y perfila durante la ejecución del proyecto. Ejemplo: Construcción de una plataforma de servicios TIC on line.

 

gestion proyectosGestión de proyectos

Conjunto de las actividades organizativas de un proyecto con las que se gestiona la ejecución para lograr el mayor grado de éxito.
El éxito de los proyectos delimitados se basa en conseguir el resultado definido, con los recursos previstos y sin incumplir la fecha de fin prevista, mientras que en los proyectos progresivos consiste en la entrega temprana del mayor valor posible, y su incremento continuo y frecuente.

predictivo icon3.-Gestión predictiva

Aplicación de métodos y prácticas para lograr el éxito en los proyectos delimitados.

scrum icon4.- Gestión evolutiva

Aplicación de métodos y prácticas para lograr el éxito en los proyectos progresivos.

 

programaPrograma

Conjunto de proyectos que comparten o colaboran en el logro de un objetivo común. Los programas se pueden clasificar en delimitados o progresivos, siendo delimitados a aquellos que comienzan con la definición detallada del resultado, un tiempo de ejecución conocido y acotado. Los programas progresivos, comienzan con una definición general e incompleta del resultado final, que se desarrolla durante la ejecución; también pueden no  tener especificada la fecha de fin, de forma que se ejecutarán hasta que se decida concluirlos, o reemplazarlos.

 

» Leer más, comentarios, etc...

Meta-Info

¿Que es?

Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

rss subscripción

Sponsors

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

Idea: Juanjo Navarro

Diseño: Albin