Noticias Weblogs Código

Variable not found

Enlaces interesantes ¡200!

May 25, 2015 08:59 AM

Enlaces interesantesSeguimos de fiesta, esto es un no parar :) Si la semana pasada celebrábamos el noveno aniversario del blog, hoy celebramos el post número 200 de estas recopilaciones de enlaces, que muchos de vosotros seguís y me habéis comentado que de verdad os resultan interesantes.

De nuevo, muchas gracias a todos por estar ahí :)

Y dicho esto, vamos al turrón…

.Net

ASP.NET

Azure / Cloud

Conceptos/Patrones/Buenas prácticas

Data access

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Otros

Publicado en Variable not found

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

Poesía Binaria

Servidor web seguro (HTTPS) en C usando openSSL (pruebas)

May 25, 2015 08:03 AM

Hace unos días veíamos un ejemplo de un cliente web SSL con ayuda de openSSL. Ahora vamos a hacer un servidor al que se pueda conectar. Se trata sólo de una prueba de concepto, nada que podamos utilizar en el mundo real, pero está bien para ver cómo funciona la biblioteca.

Creando un certificado auto-firmado

Lo primero que vamos a hacer es crear una llave y un certificado para utilizarlos. Como estamos probando y no vamos a gastar dinero ni nada en un certificado, podemos crear un autofirmado, ya sabéis, los navegadores no nos detectarán como fuentes de confianza pero tendremos una conexión segura.

Para ello, nos ponemos en un directorio de confianza (vamos a colocar ahí archivos sensibles, al menos vamos a crearlos ahí… por lo menos que no sea una carpeta compartida en emule) y en nuestra consola pondremos:

$ openssl genrsa -out itsme.key 2048

Podremos hacer las claves más complejas, he puesto 2048 porque lo suelo utilizar en muchos casos, y muchas autoridades certificadoras piden claves de este tamaño.
Si queremos cifrar esta clave, o como practican algunos, el famoso y antiguo arte de encerrar datos en una cripta (encriptar), podemos utilizar el argumendo (-des3, -aes256, entre otros), aunque en este caso, nos pedirá una contraseña para empezar a trabajar, y no está bien que un servidor nos pida una contraseña, aunque también podremos manejarla con un callback… bueno, eso ya es decisión vuestra.

Una vez creada la clave, queremos crear una petición de firmado (signing request) porque alguien tiene que dar fe de que soy quien digo que soy, aunque más tarde veremos que yo mismo voy a firmarme… y por eso mismo los navegadores no se fiarán de mí.

$ openssl req -new -key itsme.key -out itsme.csr

Este comando es interactivo, y nos preguntará una serie de datos que mandaremos cuando se conecten a nosotros, para que la gente sepa dónde se está metiendo.

Si no queremos poner un password, lo podemos dejar en blanco.

Tras la creación de la petición de firmado, sólo nos queda firmar, y listo, para ello

$ openssl x509 -req -days 365 -in itsme.csr -signkey itsme.key -out itsme.crt

El parámetro days lo podemos hacer más grande o más pequeño, según decidamos la validez de nuestra firma, podemos poner 1000 años y nadie nos dirá nada, aunque sería un milagro que nuestros datos sobrevivieran tanto.

Ya tenemos nuestros archivos itsme.key e itsme.crt para trabajar con ellos. Podéis visitar esta web para más info sobre creación de certificados.

Creando nuestro servidor

Es sólo una prueba, le pidamos lo que le pidamos, lo hagamos bien o lo hagamos mal, siempre nos devolverá la misma página (tengo en el horno un pequeño proyecto algo más completo al que ya le integraré también SSL).
El caso es que hacemos la conexión TCP, el handshake SSL, leemos la petición del usuario y enviamos una respuesta. Tal vez tenga un montón de bugs en el servidor, no es concurrente y su respuesta es fija, pero para el caso nos vale.

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/**
*************************************************************
* @file servtcp.c
* @brief Example web server using SSL connection.
*   It will always send the same web. It's just a test
*   to stablish a secure connection and send some data
*   This server cannot attend simultaneous connections
*
* @author Gaspar Fernández <blakeyed@totaki.com>
* @version 0.1
* @date 18 apr 2015
*
* To compile
*   $ gcc -o serverssl serverssl.c -lcrypto -lssl
*
*************************************************************/


#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

/** Port  */
#define PORT       1430

#define BUFFERSIZE 16384

#define CRLF       "\r\n"

#define RESPONSE "HTTP/1.1 200 OK" CRLF     \
  "Content-Type: text/html charset=utf-8" CRLF  \
  "Server: ServerTest" CRLF         \
  CRLF                      \
  "<html><head><title>Server Test</title></head><body>This is just a test</body></html>" CRLF


#define CERTFILE  "sslserverchain.pem"
#define KEYFILE   "sslserver.key"

/** sslc handles SSL and SSL_CTX and socket.
 The same as myssl.c */

typedef struct
{
  /** socket handler  */
  int skt;
  /** client socket handler  */
  int client_skt;
  /** error, if any  */
  int err;
  /** SSL handler  */
  SSL* ssl;
  /** SSL Context  */
  SSL_CTX* ctx;
} Sslc;

/**
 *
 * @param h    Our struct
 * @param port Por to listen to
 *
 * @return (0 if OK, else fail)
 */

int TCP_Server(Sslc* h, int port);

/**
 * Uses select to test if there is anything waiting to be read.
 * The same function as myssl.c
 *
 * @param h       Our structure. Only the socket will be used
 * @param timeout Timeout before giving up
 *
 * @return (0 timeout, 1 data waiting, <0 fail)
 */

int TCP_select(Sslc* h, double timeout);

/**
 * Initializes SSL connection and creates the SSL Context
 *
 * @param h     Our struct to store everything
 *
 * @return 0 if OK
 */

int SSL_init(Sslc* h);

/**
 * Loads certificates in the context.
 *
 * @param h     Our struct to store everything
 * @param cert  PEM certificate file or chain (we can store several
 *              certificates in one file, just concatenating them.
 * @param key   Encryption key
 *
 * @return 0 if OK
 */

int SSL_load_certificates(Sslc* h, char* cert, char* key);

/**
 * Accepts client and start dialog
 *
 * @param h     Our struct
 *
 * @return 0 if OK
 */

int TCP_acceptClient(Sslc* h);

/**
 * Just a test, replace SSL_clientDialog() in acceptClient() by
 * TCP_clientDialog() to create an insecure web server.
 *
 * @param h     Our struct
 *
 * @return 0 if OK
 */

int TCP_clientDialog(Sslc* h);

/**
 * It's everything we're here for. SSL dialog with the clients
 *
 * @param h     Our struct
 *
 * @return 0 if OK
 */

int SSL_clientDialog(Sslc* h);

/**
 * Prints a tragic error and exit
 *
 * @param msg   Error text
 *
 * @return void
 */

void panic(char* msg);

/**
 * ASCII clock to wait for clients
 *
 * @param loop  Just a number, when it changes, it draws a new character.
 *              If loop == 0, restarts
 *
 * @return void
 */

void aclock(int loop);

int main(int argv, char** argc){

  Sslc sslc;
  int activated=1;
  int loop=0;
  int sel_res;

  if (SSL_init(&sslc)<0)
    panic ("Couldn't initialize SSL");

  if (SSL_load_certificates(&sslc, CERTFILE, KEYFILE))
    panic ("Couln't load certificates");

  if (TCP_Server(&sslc, PORT)<0)
    panic ("Couldn't make a TCP Connection");

  while(activated)
    {
      aclock(loop);
      sel_res =TCP_select(&sslc, 1);
      if (sel_res<0)
    panic("Failed on selec()");
      else if (sel_res==1)
    {
      if (TCP_acceptClient(&sslc)<0)
        panic ("Tragic error accepting client");
      loop = -1;        /* Reset clock */
    }

      loop++;
    }

  /* Wont' reach this point as the server never ends... */
  close(sslc.skt);

  return 0;
}

int TCP_Server(Sslc* h, int port)
{
  struct sockaddr_in my_addr;

  h->skt = socket(AF_INET, SOCK_STREAM, 0);
  if(h->skt < 0)
    return -1;

  my_addr.sin_family = AF_INET ;
  my_addr.sin_port = htons(port);
  my_addr.sin_addr.s_addr = INADDR_ANY ;

  if( bind( h->skt, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 )
    return -2;

  if(listen( h->skt, 10) == -1 )
    return -3;

  return 0;
}

int TCP_select(Sslc* h, double timeout)
{
  fd_set fds;
  FD_ZERO(&fds);
  FD_SET(h->skt, &fds);
  fd_set *rset=&fds;
  fd_set *wset=NULL;

  struct timeval tv;
  tv.tv_sec = (int)(timeout);
  tv.tv_usec = (int)((timeout - (int)(timeout)) * 1000000.0);

  int ret = select(h->skt+1, rset, wset, NULL, &tv);
  return ret;
}

int TCP_acceptClient(Sslc* h)
{
  struct sockaddr_in client_addr;
  socklen_t size_addr = sizeof(struct sockaddr_in);

  if ((h->client_skt = accept( h->skt, (struct sockaddr*)&client_addr, &size_addr))!= -1)
    {
      printf("\nNew client connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), client_addr.sin_port);
      int r = SSL_clientDialog(h);
      if (r<0)
    {
      printf ("There was a problem with this client connection\n");
      ERR_print_errors_fp(stderr);
    }
      close(h->client_skt);
    }

  /* Returns 0 to avoid tragic fails, just display on screen*/
  return -6;
}

int TCP_clientDialog(Sslc* h)
{
  char buffer[BUFFERSIZE];
  int bytecount;

  memset(buffer, 0, BUFFERSIZE);
  if((bytecount = recv(h->client_skt, buffer, BUFFERSIZE, 0))== -1)
    return -7;

  if (send(h->client_skt, RESPONSE, strlen(RESPONSE), 0)<0)
    return -8;

  return 0;
}

int SSL_clientDialog(Sslc* h)
{
  char buffer[BUFFERSIZE];
  int bytecount;

  h->ssl = SSL_new(h->ctx);
  if (h->ssl == NULL)
    return -11;
  /* SSL_set_options(h->ssl, SSL_OP_ALL ); */

  if (SSL_set_fd(h->ssl, h->client_skt) == 0)
    return -12;

  /* Accept SSL connection and handshake */
  if (SSL_accept(h->ssl) < 1)
    return -13;

  memset(buffer, 0, BUFFERSIZE);
  if((bytecount = SSL_read(h->ssl, buffer, BUFFERSIZE)) < 1)
    return -7;

  if (SSL_write(h->ssl, RESPONSE, strlen(RESPONSE))< 1)
    return -8;

  SSL_free(h->ssl);     /* free mem */

  return 0;
}

int SSL_init(Sslc* h)
{
  SSL_library_init();       /* not reentrant! */

  SSL_load_error_strings();

  OpenSSL_add_all_algorithms();     /* load & register all cryptos, etc. */

  /* We can try SSLv23_server_method() to try several
   methods, starting from the more secure*/

  h->ctx = SSL_CTX_new(TLSv1_2_server_method());
  if (h->ctx == NULL)
    return -4;

  return 0;
}

int SSL_load_certificates(Sslc* h, char* cert, char* key)
{
  if ( SSL_CTX_use_certificate_chain_file(h->ctx, cert) < 1 )
      return -8;

  /* set the private key */
  if ( SSL_CTX_use_PrivateKey_file(h->ctx, key, SSL_FILETYPE_PEM) <= 0 )
    return -9;

  /* verify private key */
  if ( !SSL_CTX_check_private_key(h->ctx) )
    {
      printf("Private key doesn't match the public certificate\n");
      return -10;
    }

  return 0;
}

void aclock(int loop)
{
  if (loop==0)
    printf("[SERVER] Waiting for connections  ");

  printf("\033[1D");        /* ANSI code to go back 2 characters */
  switch (loop%4)
    {
    case 0: printf("|"); break;
    case 1: printf("/"); break;
    case 2: printf("-"); break;
    case 3: printf("\\"); break;
    default:            /* Nothing here */
      break;
    }

  fflush(stdout);       /* Update screen */
}

void panic(char *msg)
{
  fprintf (stderr, "Error: %s (errno %d, %s)\n", msg, errno, strerror(errno));
  /* Print SSL errors */
  ERR_print_errors_fp(stderr);
  exit(2);
}

Algunas notas finales

Puede que no tengamos sólo un certificado (puede que tengamos varios certificados intermedios), y debamos incluirlos todos en nuestra conexión segura. Gracias a que utilizamos SSL_CTX_use_certificate_chain_file() para cargar el certificado, podemos meter varios certificados concatenados, del tipo:

$ cat certificado1.pem certificado2.pem certificado3.pem > cadena_certificados.pem

Los archivos de certificado y clave pueden ser especificados en la parte superior del archivo, con las constantes CERTFILE y KEYFILE.

El método con el que trabajaremos será TLSv1_2_server_method(), aunque podemos utilizar cualquier otra versión de TLS, incluso SSLv3 (será insegura, pero para fines académicos vale, o para ver si hay servidores que aún pueden conectarte con este método… ¡¡no he dicho nada!!). Tenemos también otro método que es SSLv23_server_method(), que actúa igual que el método cliente compañero. OpenSSL no suele venir compilado ya con soporte SSLv2, y el SSLv3 está prohibido hasta la saciedad, pero si queremos SSLv23_server_method() puede no utilizar ningún SSLvX, y tirar directamente para los TLS si definimos SSL_set_options(SSL*, long options). La opción sería SSL_OP_NO_SSLv3 (es una constante, podemos ver más en el manual de SSL_CTX_set_options).

Foto principal: zoetnet (Flickr CC-by)

Foto cripta: Ismael Alonso (Flickr CC-by)

The post Servidor web seguro (HTTPS) en C usando openSSL (pruebas) appeared first on Poesía Binaria.

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

Koalite

Manejo de matrices en clojure con core.matrix

May 25, 2015 05:06 AM

Hace unas semanas escribí una introducción sobre Machine Learning usando numl, una librería para C#. Al empezar a profundizar en el tema, he visto que hay bastantes algoritmos de aprendizaje automático que se basan en el uso de matrices, y aunque hay lenguajes muy apropiados para eso, como matlab u octave (con el que ando también entretenido), no he podido resistirme a ver cómo se podría trabajar con matrices en clojure, el lenguaje que se ha convertido en mi lenguaje por defecto para jugar y experimentar.

OJO: si no te interesan clojure, ni las matrices, ni el álgebra lineal, éste es un momento excelente para que dejes de leer el post y te dediques a cosas más entretenidas.

clojure.core.matrix

La librería de referencia en clojure para trabajar con matrices es core.matrix. Pese a su nombre, no está incluida “de serie” en clojure, sino que se instala como cualquier otra dependencia.

core.matrix expone un API (que veremos dentro de poco) para trabajar con matrices y vectores. Aunque matemáticamente podemos incluir los vectores como un caso particular de matrices, core.matrix separa ambos tipos porque a nivel de programación hay escenarios en los que resulta más cómodo tratar los vectores de manera especial. En cualquier caso, en este post nos centraremos en el manejo de matrices.

Una característica interesante de core.matrix es que lo que realmente expone es un API “de alto nivel” que puede trabajar con distintas implementaciones de matrices.

Por defecto incluye algunas implementaciones básicas, como la basada en persistent-vectors de clojure, pero se pueden emplear otras implementaciones como vectorz-clj, basada en vectorz, una de las implementaciones más rápidas de matrices sobre la JVM, o clatrix, una librería con parte nativa que ofrece un rendimiento aún mayor para matrices grandes.

A lo largo de este post usaremos la implementación de vectorz-clj, por aquello de ahorrarnos tener una dependencia nativa y de paso evitar ciertos bugs en la implementación por defecto de core.matrix.

Cómo usar core.matrix

Lo primero que necesitamos es incluir los paquetes adecuados, en este caso el paquete principal de core.matrix, y el de la implementación de vectorz-clj. Podemos añadirlos a nuestro project.clj:

(defproject my-project
  ...
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [net.mikera/core.matrix "0.34.0"]
                 [net.mikera/vectorz-clj "0.29.0"]])

A partir de aquí los referenciamos y podemos empezar a jugar:

(ns my-namespace
  (:require [clojure.core.matrix :as m]))

Existe la opción de referenciar también el espacio de nombres clojure.core.matrix.operators, que redefine los operadores aritméticos típicos (+, -, *, /, etc.), pero personalmente prefiero hacer explícito que estoy usando operaciones operaciones sobre matrices.

A continuación, establecemos la implementación concreta de matrices que queremos usar y ya estamos listos para empezar a trastear:

(m/set-current-implementation :vectorz)

Podemos crear matrices a partir de vectores anidados, o con algunas funciones predefinidas:

;; Una matriz arbitraria
(def M (m/matrix [[1 2 3]
                [4 5 6]
                [7 8 9]]))

;; Matriz identidad 4x4
(def I4 (m/identity 4)) 

;; Matriz de 3x2 con 0 en todas las filas y columnas
(def Z3x2 (m/zero-matrix 3 x)) 

Podemos obtener y establecer los valores de una matriz (que por defecto es inmutable, así que al establecer devuelve una copia de la matriz original):

(m/get M 1 2) 
;; => 6

(m/set M 0 0 21) 
;; => [[21 2 3]
;; =>  [ 4 5 6]
;; =>  [ 7 8 9]]

A partir de una matriz, podemos obtener un parte:

;; Nos quedamos a partir de la fila 0 con 1 fila 
;; y a partir de la columna 1 con 2 columnas
(m/submatrix M 0 1 1 2) 
;; => [[2 3]]

;; Nos quedamos con las filas de la 0 y 2, y con todas las columnas
(m/select M [0 2] :all)
;; => [[1 2 3]
;; =>  [7 8 9]]

Por supuesto, podemos operar con matrices, tanto entre ellas como con escalares usando m/add, m/sub, m/mul (multiplicación entre matriz y escalar o multiplicaciones de matrices elemento a elemento), m/mmul (multiplicación típica de matrices), m/div, etc.

Cuando operamos con matrices, sus dimensiones tienen que ser compatibles. Si operamos con una matriz y un escalar, se realiza la operación entre el escalar y cada elemento de la matriz:

(m/add (m/matrix [[1 2] 
                [1 2]]) 
      (m/matrix [[5 5] 
                [7 7]]))
;; => operación con matrices:
;; => [[6 7]
;; =>  [8 9]]

(m/add (m/matrix [[1 2] 
                [1 2]]) 
       3)
;; => operación con matriz y escalar
;; => [[4 5]
;; =>  [4 5]]

Además de combinar matrices y escalares, podemos combinar matrices cuyas dimensiones no son compatibles a priori, pero que pueden convertirse en compatibles según las reglas de expansión (broadcasting) de core.matrix. Así, si sumamos una matriz de 3×3 con un vector fila 1×3, core.matrix sumará el vector a cada una de las filas de la matriz original.

Junto a estas operaciones aritméticas básicas, tenemos operaciones específicas sobre matrices, como m/transpose para obtener la matriz transpuesta, m/det para obtener el determinante, o m/inverse para obtener la inversa de una matriz.

Al ser clojure un lenguaje funcional, no podían faltar los equivalentes a map, reduce y compañía, que nos permiten aplicar estas operaciones a todos los elementos de una matriz como si de una secuencia se tratasen. En geneneral, estas funciones se denominan igual que sus equivalentes para secuencias, pero con el prefijo e (de element wise). Por ejemplo, tenemos e/map o e/reduce.

El API de core.matrix tiene un estilo muy funcional, haciendo un uso intensivo de matrices inmutables, pero a veces puede ser necesario utilizar estructuras de datos mutables por motivos de rendimiento. Si la implementación subyacente lo permite (y vectorz-clj lo hace), se puede emplear el equivalente mutable de (casi) todas las funciones que hemos visto ahora ahora. Estas versiones mutables tiene el sufijo ! y modifican la matriz que reciben como parámetro:

;; En su versión inmutable, set devuelve una copia de la matriz original
(m/set M 0 0 21)
;; La versión mutable modifica la matriz original
(m/set! M 0 0 21)

Resumen

Esta mini introducción de core.matrix nos permite hacernos una idea del tipo de operaciones que podemos hacer con esta librería. Si estás acostumbrado (como casi todos nosotros) a desarrollar las típicas aplicaciones de línea de negocio, todo esto de las matrices te parecerá una tontería inútil, pero hay bastantes campos en los que tienen su aplicación, y contar con una librería que nos ayude a implementar algoritmos basados en matrices resulta muy importante cuando empiezas a tocarlos.

Posts relacionados:

  1. Project Euler: Problema 4 con clojure
  2. Estructura de un proyecto con Clojure
  3. Project Euler: Problemas 1 y 2 con Clojure

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

Blog Bitix

10 razones para seguir usando Java

May 22, 2015 03:00 PM

Con ya dos décadas de vida y a lo largo de este tiempo Java se ha convertido en uno de los lenguajes más empleados para programar a día de hoy. En este periodo han surgido otros lenguajes en la propia plataforma de la JVM como Groovy, Scala o Clojure y fuera de ella como C#, Python, Ruby, PHP, Go o Dart ofreciendo algunas cosas adicionales o supliendo algunas carencias de Java. Aún con toda esta competencia esta es mi lista de 10 razones por las que creo que Java sigue siendo una de las mejores opciones.

Java

El sábado 23 de mayo de 2015 el lenguaje Java cumple 20 años de historia y aún hoy Java sigue siendo uno de los lenguajes de programación preferidos para desarrollar en un mundo tecnológico en el que unos pocos años pueden darse grandes cambios y en dos décadas ver surgir nuevas tecnologías y verlas languidecer. Algunas personas se jactan y hablan con un tono de desprecio y mofa nada agradable hacia Java mostrando su desconocimiento o prejuicios siguiendo algunos tópicos bastante difundidos la mayoría incorrectos. A otras personas quizá no les gusta Java no tanto por el lenguaje como por los proyectos que ha desarrollado en él, en consultoras cárnicas, para clientes con condiciones laborales paupérrimas, con tecnologías, librerías y frameworks obsoletos o códigos heredados programados por programadores aparentemente con poca experiencia que es un infierno mantener debido a una cantidad importante de errores, uso de tecnologías no adaptadas a la solución, malos funcionamientos y falta de documentación. Pero estas situaciones externas no tiene nada que ver con el lenguaje. Algunas otras personas quizá no les gusta porque no les ofrece el último azúcar sintáctico que han visto y usado en otros lenguajes o porque para propósitos específicos hay alternativas que permiten obtener una solución de una forma más sencilla.

Java 20 años (1995-2015)

En JavaWorld ha publicado varios artículos para celebrar el aniversario comentando su futuro, su pasado y presente o que notables características reunió en su momento para ser hoy uno de los lenguajes más usados.

Algún otros artículos interesantes son:

Aunque algunos parecen considerar ya hoy a Java el nuevo COBOL (y este último aún tiene futuro) y no sea lo habitual, en este artículo trataré de exponer algunos argumentos que posee Java para su defensa y por los que en mi caso aún no he tenido necesidad de buscar mayor felicidad programando en otra opción.

Java no es lento

Quizá en las primeras versiones de los 90 fuera así pero la realidad hoy con las mejoras introducidas en cada versión a la Java Virtual Machine (JVM) un programa Java es comparativamente igual de rápido que uno en C o C++, salvo para tareas muy específicas de cálculos intensivos no hay diferencia. Eligiendo las estructuras de datos adecuadas no tendría por qué haber una diferencia de rendimiento considerable y además para la mayoría de las tareas más importante que la rapidez es la legibilidad del código, su fácil desarrollo, mantenimiento o coste.

Javadoc

Java tiene una gran herramienta de documentación que permite embeber la misma en el código fuente de los archivos y generar una serie de documentos html para su posterior consulta. La documentación proporcionada en la API es extensa, completa y buena, siendo simple html puede ser alojada en cualquier servidor web y consultada en internet. Sin documentación la tarea de los programadores sería considerablemente más complicada, aún en el caso de falta de documentación javadoc el IDE con la asistencia de código puede ayudarnos gracias a la introspección incorporada en la plataforma.

Compilado, tipado estático

Las metodologías ágiles están siendo ampliamente adoptadas y algunos de sus defensores apuestan por lenguajes que consideran encajan con su metodología agilista confundiéndola con lenguajes dinámicos y menos verbosos, que puede ser acertado en ocasiones o circunstancias pero con Java también se puede ser ágil como el que más. Una de las buenas prácticas de las metodologías ágiles es tener teses unitarios del código al ser posible que lo cubra al 100%, sin embargo, la realidad es que nos será complicado tener el 100% del código cubierto con teses.

Con los lenguajes dinámicos hay que tener especial cuidado ya que por su propia naturaleza hace que algunos errores solo los encontraremos en la ejecución, por experiencia propia no será la primera vez (ni la centésima) que un error tan básico como de compilación por nombre de variable o método mal escrito es descubierto en producción. El IDE es la herramienta que en Java junto con el tipado estático y la ayuda al compilador permite detectar errores de compilación instantáneamente, por otra parte proporciona asistencia de código y a los programadores nos sirve como documentación de los tipos esperados en los argumentos de los métodos o propiedades de las clases. Los compiladores además de para traducir el código fuente a lenguaje máquina (o bytecode) están para capturar errores sintácticos y léxicos ante los cambios de una nueva característica, una refactorización o un merge con conflictos. Se puede pensar en el compilador como un test automatizado que cubre el 100% del código, con un IDE se obtienen los errores al instante después de escribir cada caracter ¿que hay mejor? ¡no lo desprecies!.

Escribir código menos verboso no hace que escribirlo sea más rápido ni necesariamente más legible, Java posee buenos IDEs con asistentes de código que con unas pocas pulsaciones permiten escribir el código igual o más rápido. Java es un lenguaje verboso y explícito en parte propiciado por su poco azúcar sintáctico pero las construcciones sintácticas pueden ser contraproducentes, un alto número de ellas y el código será muy críptico sin un conocimiento amplio del lenguaje. Uno de los éxitos de Java es su relativa simplicidad.

IDE

Con un IDE el código Java se ve de distinta forma, no como simple texto sino donde los métodos, clases y propiedades tienen entidad propia. La asistencia de código permite obtener métodos disponibles, ver los tipos y nombres de argumentos y retornos, las excepciones lanzadas, si el método es estático o de instancia y la visibilidad de acceso según escribimos. Con la ayuda de un IDE podemos encontrar todos los usos de un método o clase de forma totalmente exacta o cambiar un nombre por otro. Hay IDEs para lenguajes dinámicos como Groovy con IntelliJ IDEA o Python con PyCharm que proporcionan asistencia de código pero usando las características dinámicas de estos lenguajes el encontrar todos los usos de un método o variable no está garantizado.

Un IDE puede suponer la diferencia entre dedicar un tiempo considerable a tareas de bajo valor a ser mucho más productivo, o mejor aún, ayudando a evitar errores.

Refactorizaciones

Con la ayuda del compilador y de un IDE las refactorizaciones como renombrar una variable, propiedad, método o clase son más sencillas y con más garantías de no romper nada, además de poder realizarlo en unos pocos segundos y sin tener que buscar y sustituir las referencias como texto plano en todo el código del proyecto. En proyectos grandes en los que trabajan más de una persona y tienen un tiempo de vida y de mantenimiento de más de unos pocos meses hace que evitemos muchos problemas y programemos con más seguridad de que las modificaciones que hacemos no introducen errores por cosas tan básicas como la compilación.

Si el uso de un proyecto es prolongado en el tiempo este posiblemente tenga que adaptarse a necesidades inicialmente totalmente desconocidas, en estos casos será tarde o temprano necesario refactorizar. En un negocio en el que el tiempo es importante y en una tecnología en constante evolución realizar refactorizaciones pequeñas o grandes es una necesidad. La mayor certeza es el cambio y se dará en herramientas, frameworks, lenguajes, ideas de negocio, ….

Productividad y legibilidad

El compilador e IDE nos indican todos los errores léxicos y sintácticos después de escribir cada caracter sin tener que ejecutar el código o los teses unitarios para descubrirlos evitando que lleguen a producción en cuyo caso nos requerirá dedicar tiempo para corregirlos o con peores consecuencias para los usuarios de nuestro código y para el negocio. Que el IDE nos muestre sugerencias con la asistencia de código según escribimos o mediante refactorizaciones son un gran diferencia de productividad aunque algunos piensen que por ser el código más verboso o por escribir menos líneas de código se tarde en programar más la misma tarea, el compilador y el IDE son factores que permiten aumentar la productividad a pesar de la verbosidad.

Con la llegada de Java 8 y sus novedades se ha incorporado al lenguaje la programación funcional que permite expresar de una forma más natural para los humanos la tarea que se desea realizar, esto hace que el código sea más legible. Lo que en un lenguaje imperativo son varias líneas de código con una combinación de sentencias condicionales, bucles, asignaciones y llamadas a métodos con un objetivo poco claro sin un examen detallado del código ahora se puede expresar de forma funcional haciendo uso de los streams y expresiones lambda, también en menor número de líneas de código.

Software disponible

Java posee gran cantidad de software disponible, de gran calidad y en muchos casos con una licencia de código abierto o de software libre para cualquier tipo de necesidad en una aplicación de cualquier ámbito. A menudo hay no solo una opción sino varias disponibles y con la libertad de elegir la que más se adecue al proyecto o se prefiera. Ahí está la fundación Apache, Spring o JBoss con una buena colección de proyectos ampliamente utilizados.

Los cambios se producirán, por ello no te encadenes a una determinada tecnología que en un futuro te impida adaptarte a nuevas necesidades. En Java hay opciones para cada diferente aspecto de la aplicación (seguridad, persistencia, logging, framework web, …), por si en un futuro surge una nueva «cojoherramienta», y esto pasará tarde o temprano, diseña tu aplicación de tal forma que sea posible reemplazar una pieza por otra sin tener que reescribir la aplicación entera.

Ofertas de trabajo, desarrolladores

Dado que Java unos de los lenguajes más utilizados y es usado ampliamente en muchos ámbitos es más fácil encontrar a personas con conocimientos y expertos en Java. Por ello hay numerosas ofertas de trabajo para diversos ámbitos (web, escritorio, servidor, dispositivos móviles, …) algunas a considerar, aunque bastantes menos que ofertas.

Conservador, no anticuado

Java tarda en incorporar en el lenguaje algunas de las últimas técnicas de programación que un determinado momento tienen gran relevancia. No porque no pueda sino porque tienen una actitud conservadora, y esto no es malo ya que uno de sus principios hasta el momento es mantener la compatibilidad hacia atrás ¿qué lenguaje que ha ido incorporando nuevas características ha mantenido la compatibilidad de compilación en gran medida durante 20 años? Java pone gran énfasis en este aspecto en cada nueva versión. Esperando cierto tiempo asegura incorporar en el lenguaje aquellas nuevas posibilidades que realmente han demostrado ser útiles y no son simples modas pasajeras que más tarde dificultan la compatibilidad en futuras versiones. Esto no quiere decir que no evolucione, ya en Java 5 incorporó numerosas novedades como generics, … y en Java 8 programación funcional como streams para mejorar la legibilidad del código y aprovechar el procesamiento paralelo de los procesadores multinúcleo. Los métodos por defecto (default methods) en interfaces son una muestra del interés que hay en Java de mantener la compatibilidad hacia atrás. En el enlace está la evolución histórica durante estos años.

Propósito general

Java es un lenguaje de propósito general y multiplataforma ejecutable en cualquier dispositivo en el que haya una JVM disponible. No está restringido a un determinado ámbito o tipo de aplicación, el mismo conocimiento del lenguaje sirve para múltiples tipos de aplicaciones desde de escritorio, de servidor, procesamiento de datos, dispositivos móviles … incluso juegos, sí juegos. Hay muestras de algunos impresionantes con buen rendimiento, aunque alguno diría incorrectamente que no. Con jMonkeyEngine podemos hacer un juego que tiene poco que envidiar usando otro lenguaje ya que proporciona los mimbres comunes: bucle del juego, colisiones, física, 3D con OpenGL, sonido, entrada, …. Minecraft es una muestra, otras buenas muestras usando jMonkeyEngine son PirateHell, Hostile Sector, Imperii, Grappling Hook o 4089: Ghost Within y en la página de ejemplos hay alguno más.

Quizá en un futuro cambie pero hoy Java es el lenguaje en el que se programan las aplicaciones Android nativas y una de las plataformas móviles con mayor cuota de mercado. El lema “write once, run everywhere” sigue siendo aplicable hoy más que nunca haciéndole ideal para la nueva generación de dispositivos de la internet de las cosas (IoT, Internet of things).

Mi escala de preferencias para un lenguaje es de la siguiente forma de mayor a menor (aunque puede variar según la necesidad):

  • Ofertas de trabajo, alguna de Groovy, alguna de Python pero mucho menores que en Java, C# o PHP.
  • Propósito general, esto permite que el tiempo dedicado a aprender y convertirte en un experto en un lenguaje (que pueden ser de varios años) pueda ser aprovechado en el momento que el avance de la tecnología cambie las reglas de juego como la aparición de los dispositivos móviles. PHP es un lenguaje que fuera del ámbito de desarrollo web tiene poca presencia, dispone de buenas herramientas como Wordpress, Drupal o Symfony y hay ofertas de trabajo. En la plataforma Android Java es el lenguaje empleado.
  • Productividad, refactorizaciones y documentación disponible. Poder refactorizar el código de forma segura es un gran punto para la productividad y más importante aún evitar errores, por este motivo y a base de experiencia soy reticente a los lenguajes dinámicos. El tipado estático ayuda a evitar errores y servir como documentación, un buen IDE permite aumentar la productividad. Java es un lenguaje que está bien documentado con su Javadoc.
  • Software disponible, hay cantidad de lenguajes algunos de los más nombrados son Go o Dart pero en estos es probable que debiésemos desarrollar nosotros el software para una determinada necesidad que en otros lenguajes ya está implementado y más que probado pudiendo haber incluso varias opciones.
  • Legibilidad, cualquier añadido al lenguaje que haga más claro el propósito del código o en menos líneas es bienvenido pero como ves esto está abajo en esta lista según importancia.

Aunque no lo he puesto el divertirse y programar a gusto con un lenguaje también debería estar en esta lista pero esto en parte se consigue una vez que dominamos el lenguaje y su ecosistema sintiéndonos capaces de realizar cualquier tarea produciendo buen código, ya sea Java o cualquier otro.

Estas son otras listas de 10 razones por las que Java mola más que nunca y otras 10 razones para querer a Java y la JVM.

¡Larga vida a Java!

Referencia:
10 Reasons Why Java Now Rocks More Than Ever
10 Reasons to Love Java and the JVM

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

El blog de Adrián Arroyo

La gestión de la memoria en Rust

May 21, 2015 10:00 PM

Finalmente ha sido publicada la versión 1.0 de Rust. El lenguaje diseñado por Mozilla basado en 3 principios:

  • Seguridad
  • Concurrencia
  • Rendimiento

Hoy voy a hablar del primer principio, la razón principal para querer ser un sustituto de C++. Porque C++ está bien, pero puedes liarla mucho si no sabes lo que haces.

Rust

El concepto de dueño

En Rust todo tiene un dueño. No puede haber más de uno ni ninguno, debe ser uno exactamente.

fn main(){
	let A = 5;
    // El dueño de A es main()

}

Hasta aquí todo es sencillo. Ahora pasaremos la variable A a otra función.

fn sumar(a: i32, b: i32) -> i32{
	a+b
}
fn main(){
	let A = 5;
	let suma = sumar(A,4);
	println!("{}",suma);
}

El programa compila y nos da el resultado, que es 9. En los lenguajes de bajo nivel las variables pueden usar memoria del stack o del heap. Un pequeño repaso sobre sus diferencias.

Stack
  • Se reserva su espacio en RAM cuando el programa arranca
  • Son más rápidas de acceder
  • No se les puede cambiar el tamaño
  • Son más seguras
Heap
  • Se debe reservar manualmente la RAM cuando queramos
  • Son más lentas de acceder
  • Pueden cambiar su tamaño en tiempo real
  • Son menos seguras. Pueden dar lugar a fugas de memoria.

En este último caso, la variable A cuyo dueño es main() le pasa la membresía temporalmente a sumar(). La membresía se devuelve a main() rápidamente y esta garantizado que así suceda. El compilador lo permite. Veamos ahora un ejemplo más complejo.

Veamos ahora un código más complejo

struct Config{
	debug_mode: bool
}

struct App{
	config: Config
}

fn main(){
	let config=Config{debug_mode: true};
	
	let app=App{config: config};
	
	println!("OK");
}

Por supuesto el código compila pero este de aquí abajo no y solo he cambiado una línea.

struct Config{
	debug_mode: bool
}

struct App{
	config: Config
}

fn main(){
	let config=Config{debug_mode: true};
	
	let app=App{config: config};
	let backup=App{config: config}; // He añadido esta línea
	
	println!("OK");
}

La razón es que cuando creamos la estructura de App por primera vez le pasamos la membresía de config a la estructura app. Así la función main no le puede pasar la membresía a backup porque ya se la pasó a app.

Referencias

Para solucionar este problema Rust usa las referencias. Así el dueño de config seguirá siendo main() pero lo podrán usar las estructuras app y backup. Para usar referencias usamos el símbolo &.

struct Config{
	debug_mode: bool
}

struct App{
	config: &Config
}

fn main(){
	let config=Config{debug_mode: true};
	
	let app=App{config: &config};
	let backup=App{config: &config};
	
	println!("OK");
}

La estrucura ahora acepta &Config en vez de Config. Es de decir usa una referencia en vez de un valor. Sin embargo esto no compilará. El compilador normalmente deduce si es posible hacer una referencia a algo no existente, un fallo común en C++. En caso de tener dudas no compilará. Rust es bastante inteligente pero no es mágico. En el caso de la estructura App, es necesario indicar que la propiedad config vivirá el mismo tiempo que la estructura.

struct Config{
	debug_mode: bool
}

struct App<'a>{
	config: &'a Config
}

fn main(){
	let config=Config{debug_mode: true};

	let app=App{config: &config};
	let backup=App{config: &config};
	println!("OK");
}

He usado la anotación de tiempo llamada a. Puedes poner cualquier nombre pero a es muy corto.

Implementaciones y referencias

Voy a introducir un concepto de Rust que son las implementaciones. Para haceros una idea rápida, serían como clases de C++, pero solo alojan funciones.

impl<'a> App<'a>{
	fn isDebugMode(&self) -> (){
		println!("DEBUG MODE: {}",self.config.debug_mode);
	}
	
	fn delete(self) -> (){
		
	}
}

He creado dos funciones para implementar App. Son idénticas salvo por un pequeño detalle, una toma el valor self (como this en C++) por referencia y la otra toma el valor directamente.

let app=App{config: &config};
	app.isDebugMode();
	app.delete();

Compila y funciona. Cambiemos el orden.

let app=App{config: &config};
    app.delete();
    app.isDebugMode();

Ya no compila. La razón es que cuando llamamos a delete() estamos pasandole la membresía de app entera. Ahora delete() es la dueña de app y cuando salimos de la función eliminamos app porque si su dueña ha muerto, app también debe morir (no es tan sangriento como pensais). Rust lo detecta y delete() será la última función que podemos llamar de app. Por cierto si os preguntais como funcionan las implementaciones en Rust (que no son clases), este código haría lo mismo llamando a funciones estáticas. Quizá así veais mejor como se pasa el concepto de dueños y membresía.

let app=App{config: &Config};
    App::isDebugMode(&app);
    App::delete(app);

Diversión con punteros en el heap

Todo estas variables eran del stack que siempre es la manera más sencilla de operar. Vamos ahora a ver como funcionaría esto con punteros. Los punteros operan como variables en el stack que hacen referencia a partes de la memoria que están en el heap. En Rust podemos operar con punteros con máxima seguridad pues todo lo aplicable a variables en el stack sigue siendo válido. Solo hay un dueño y podemos hacer referencias, aunque quizá necesitemos marcar el tiempo de vida manualmente.

let puntero: Box<i32>=Box::new(42);

Ahora el valor 42 estará en el heap y con puntero podremos acceder a él. Sin embargo como es lógico, no podemos operar directamente con él.

puntero+1 //No funciona

Para operar el valor directamente tenemos que derreferenciarlo. Se usa *

*puntero+1 // Sí funciona, y será 43

Así que esta operación sería correcto. Nótese el uso de mut para permitir editar el valor. En Rust por defecto las variables no son mutables. Ese privilegio tiene que ser declarado por adelantado.

let mut puntero: Box<i32>=Box::new(41);
    *puntero+=1;
  	println!("La respuesta es: {}",*puntero);

Como curiosidad mencionar que la macro println! (en Rust si algo termina con ! es una macro) acepta puntero o *puntero indistintamente ya que se da cuenta si es necesario derreferenciar o no.

El problema final

¿Qué pasaría si copiamos un puntero en otro? Pues como un valor en el heap solo puede tener un dueño, la membresía será del último puntero.

let mut puntero: Box<i32>=Box::new(41);
    *puntero+=1;
    let puntero_inmutable=puntero;
    println!("La respuesta es: {}",puntero); // Esta línea no compilará pues el acceso a la respuesta última del universo ahora es propiedad de puntero_inmutable
    println!("La respuesta, ahora sí, es: {}",puntero_inmutable);

Como curiosidad, este es un curioso método para bloquear en un determinado momento el acceso de escritura a nuestro puntero aunque es fácil volver a obtener el acceso a escritura con un nuevo cambio de dueño.

Conclusiones

Podemos ver que es un lenguaje que presta mucha atención a la seguridad. C++ es mucho más liberal en ese sentido y Mozilla cree que es un problema a la hora de desarrollar grandes aplicaciones. ¿Qué te ha parecido? Si tienes alguna duda no titubees y pregunta.

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

Juanjo Navarro

Codificación de URLs

May 21, 2015 05:45 PM

En What every web developer must know about URL encoding se explica algo que resulta sorprendentemente difícil de hacer bien: Hacer encoding de URLs.

Algunas cosas destacables:

  • Las distintas partes de una url (el host, el path, el querystring) utilizan distintas codificaciones, por lo tanto no se puede hacer el encoding correctamente sin analizar la url (simplemente con un buscar y sustituir).
  • Sorprendente: La clase java.net.URLEncoder de Java no nos sirve para hacer encoding de URL (a pesar de su nombre). No solo eso, sino que la propia documentación oficial lo dice

Utility class for HTML form encoding. This class contains static methods for converting a String to the application/x-www-form-urlencoded MIME format.

  • Aparte de los parámetros de la query, existen los parámetros del path. Es más, cada segmento de path (lo que vendrían a ser cada uno de los directorios) pueden tener sus propios parámetros, que se separan del fragmento por “;”, como en este ejemplo que se me ocurre:
http://www.example.com/user;domain=main/6677/connections;start=0;count=20

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

Picando Código

Rebeldes de los Datos

May 20, 2015 03:23 PM

Terminado el Taller de Datos Abiertos de Gobierno en Uruguay, volví a casa con un montón de ideas, nuevos contactos, y muchas ganas de seguir en el tema.

La instancia tuvo una estructura determinada con grupos de trabajo abiertos entorno a 4 temas: Regulación y Normativa, Reuso, Salud y Medio Ambiente. Cada grupo tuvo varias sesiones de trabajo en distintas mesas en el local de la Agencia Española de Cooperación Internacional para el Desarrollo en Ciudad Vieja.

Mesa de Trabajo

Cada mesa de trabajo sacó sus conclusiones y las presentó al final del evento. Los grupos de trabajo estaban conformados por personas pertenecientes a entes gubernamentales, integrantes de la sociedad civil y los invitados especiales de UNDESA, entre otros.

La idea con lo hecho era planear la agenda de Datos Abiertos de Gobierno a futuro. Si bien cada grupo planteó aspectos específicos, hubieron dos temas importantes que creo que todos tuvieron en común:

  • Legizlación – una ley de Datos Abiertos para regular el tema desde el gobierno por defecto.
  • Grupo de trabajo consolidado – Un grupo de trabajo con referentes de distintos entes impulsado desde el Estado para ayudar a llevar adelante la agenda.

Seguramente habrán noticias desde el gobierno en estos aspectos eventualmente. Pueden ver más información sobre las presentaciones y conclusiones en el siguiente enlace: . También hay información resumida en el sitio web de AGESIC – Tenemos tema: cerró el taller de datos abiertos.

Trabajando

Más allá de los resultados, hubo un aspecto interesante del evento que fue la instancia de encuentro para varias personas de distintos entes con la sociedad civil. El “networking” es uno de los aspectos fundamentales de varios eventos y en este caso no fue la excepción. Quiero aprovechar este post para reconocer a los “rebeldes de los datos” que tuve la oportunidad de conocer. Se me ocurrió este nombre durante una charla en alguno de los cortes para café, conversando con empleados de varios entes.

En general -sobretodo en Uruguay- tenemos una imagen muy negativa de los empleados públicos trabajando en entes gubernamentales. En muchos casos justificada tal vez, pero instancias como éstas nos dejan ver que no todo es tan malo como se puede creer desde afuera. Hay mucha gente adentro muy preocupada por las personas, el aire, el agua, los animales, etc. Más allá del partido político en el gobierno de turno, estas personas están pendientes de temas importantes para el resto y se preocupan por hacer algo al respecto. Y también están peleando constantemente contra la burocracia, dónde se invierten los recursos, etc. Pero es bueno saber que están ahí.

Los Datos Abiertos son una de las herramientas que tenemos para equilibrar el poder a favor de los ciudadanos, y cuánto más se trabaje en esa dirección, mejor. Están en la agenda política del gobierno actual dentro del marco de Gobierno Abierto. Necesitamos más rebeldes haciendo algo, hay mucho trabajo por hacer en este aspecto, y los Datos Abiertos no sirven de nada si no los explotamos por el bien común.

Asistentes taller AGESIC

Si te interesa empezar con el tema, en Uruguay existe DATA, la Asociación Civil con la misión de la creación de herramientas para el accionar colectivo, participativo y colaborativo, apoyándose en la comunidad a través de las tecnologías de la información y comunicación y el uso de la información pública. Contacta a DATA para conocer cómo ser parte.

Fotos por Mónica Camerlati de IMPO.

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

Picando Código

Mini-truco: Crear un dump de base de datos Postgres en servidor por SSH y descargarlo

May 19, 2015 08:19 PM

PostgreSQLHace mucho que no publico nada bajo la categoría Mini-trucos: Cosas publico acá para compartir y tener de referencia.

En este caso de nuevo trabajando con PostgreSQL tuve que hacer un par de cosas bastante sencillas y probablemente comunes:

Crear un dump de la base de datos en el servidor remoto

Conectarse al servidor por SSH e ingresar:

pg_dump nombre_bd -U usuario_bd -W -h localhost -f ~/nombre_dump

-U para pasarle el usuario para acceder a la base de datos
-W para forzar que nos pida el password
-h localhost para evitar que intente autenticarse con el usuario actual en el sistema (que en mi caso era distinto al del de la base de datos por lo que el rol no existía)
-f archivo – Dónde guardarlo

Para descargarlo a nuestra computadora (desde el prompt de nuestra computadora):

scp usuario@servidor:/path/al/dump /directorio/local

Importar

psql bd_en_local < nombre_dump

Puede ser necesario crear archivo .pgpass para el usuario (en caso de una app Rails).

Actualización

¡Gracias Rodolfo por el aporte en los comentarios!

Fernando el ssh puede ejecutar el comando y la salida stdout es del lado del cliente (ssh), por lo que puedes colocarla dentro de un pipe:

ssh usuario@servidor pg_dump nombre_bd -U usuario_bd -W -h localhost | cat > /directorio/local/nombre_dump

con este único comando te evitas ocupar espacio en el servidor para el dump y el subsecuente scp.

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

Variable not found

9 años ya, esto parece que va en serio…

May 19, 2015 08:38 AM

9 años de variable not foundPues sí, parece mentira, pero han pasado ya nueve años desde Variable not found comenzó tímidamente su andadura intentando hacerse un pequeño hueco en este océano de información en que se había convertido internet.

Sinceramente, y ya lo he comentado en alguna otra retrospectiva anual, nunca pensé que esta aventura duraría tanto tiempo y me traería tantas satisfacciones. Y aunque he de reconocer que no es una tarea sencilla, el hecho de estar todavía aquí con ganas de seguir aprendiendo y compartiendo todo lo que puedo es para mí una compensación más que suficiente a la dedicación que esto requiere :)

Como manda la tradición, voy a comentar algunos detalles objetivos sobre la salud blog y sus visitantes, porque alguna vez me habéis comentado que os resultan interesantes estos datos.

En cuanto a visitas, el blog sigue manteniéndose en buena forma. Siguiendo la tónica habitual de los últimos años, se siguen incrementando las visitas, aunque sin aumentos espectaculares. Creo que estamos en una fase de leve crecimiento sostenido, como muestra la siguiente gráfica:


Alcanzamos en total más de un millón y medio de páginas vistas, con un promedio de tiempo en la página de 4 minutos, lo cual creo que no está nada mal.

En este último año, las estadísticas indican un total de 270.000 páginas vistas por un total de 140.000 visitantes, datos ligeramente superiores a los del año anterior. La página de Facebook ronda los 750 amigos (+15%), y en Twitter superamos los 1.250 seguidores (+25%).

Los suscriptores al RSS, en cambio, han caído drásticamente por el cambio de política de Google que ha afectado a todos los usuarios que usábamos Feedburner; de más de 1.500 del año pasado, ahora no llegan a 400 (!) Algún día tendré que sustituir este servicio por algo más decente, supongo :(

Feedburner stats

En cuanto a vosotros, estimados amigos, este es vuestro perfil medio según los algoritmos mágicos de Google. La mayoría sois hombres (90%), de entre 25 y 35 años (60%), tecnófilos, aficionados al cine y TV y a la fotografía, muy inclinados a la tecnología, dispositivos, software, programación y a muchos os gustan los deportes en general, el fútbol en particular.
Browsers
El 70% utilizáis Chrome, creciendo sobre el año  anterior. Firefox (20%) e Internet Explorer (10%), han bajado respecto al último periodo.

España sigue siendo la principal fuente de visitantes con un 24%, bajando ligeramente respecto al año anterior por la subida de otros países del otro lado del Atlántico. México se sigue aproximando, rozando ya el 21% de visitantes. Ya a algo más de distancia, siguen subiendo Colombia (11%), Argentina (9%), Perú (8%) o Chile (6%).

Los buscadores aportan el 85% de los visitantes, siendo Google el usado el 99% de las veces. El acceso directo, es decir, los usuarios que introducen directamente la URL o usan los favoritos en su navegador alcanzan el 10%. Sólo un 5% de visitas se deben a enlaces externos.

La parejitaY ahora hablemos de los beneficios obtenidos durante el periodo, que seguro que también os interesan :)

Ya hace años llegué a la conclusión de que los ingresos por tener Adsense en el blog no eran una leyenda urbana, pero poco después descarté hacerme rico con ellos. En este sentido, este año hemos seguido en la misma línea; un par de veces me llega una transferencia de Google suficiente como para irme a almorzar con la familia, y poco más. Tampoco han vuelto los tiempos en los que he escrito algún post patrocinado, siempre algo mejor recompensados.

Pero claro que hay beneficios, negarlo sería faltar a la verdad. Lo que ocurre es que muchos de ellos son indirectos y otros muchos intangibles: satisfacciones, mucho aprendizaje, visibilidad y oportunidades increíbles… Por ejemplo, ¿quién me iba a decir hace unos años que tendría la oportunidad de publicar un libro de alcance mundial, traducido ya al inglés y al japonés? ¿O que tendría ocasión de trabajar para empresas de primer nivel del país (e incluso, cada vez más, en el extranjero) en proyectos impresionantes? ¿Y la satisfacción de haber formado a centenares de desarrolladores en mis cursos de CampusMVP? Es sencillamente increíble.

Y todo ello os lo debo a vosotros, queridos amigos. Gracias por leerme. Gracias por citarme. Gracias por recomendarme. Gracias por decírmelo cuando me equivoco. Gracias por aportar vuestra visión. Y sobre todo, gracias por el apoyo y cariño que me habéis demostrado durante tanto tiempo.

Espero veros a todos por aquí al menos un año más, ayudándome a buscar esta esquiva variable ;)

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

Arragonán

Semana 362

May 18, 2015 01:14 PM

Semana muy movidita esta última respecto a posibles colaboraciones y proyectos (reuniones y emails a cascoporro), en la que finalmente hemos llegado un acuerdo con una empresa local con la que voy a estar colaborando una temporada. Vamos a empezar poco a poco, pero va a ir exigiendo bastante dedicación por mi parte tal y como pasen las próximas semanas y vaya cerrando los proyectos pendientes.

Tuvimos doble sesión de charlas en SenpaiDevs. El martes vino gimenete a hablar de javascript y a hacer una intro a node.js; mientras que el jueves Néstor preparó una sesión sobre DevOps (vagrant, ansible, packer.io, docker).

En otro orden de cosas, esta semana me he visto todos los capítulos de las 2 primeras temporadas de Black Mirror, una mini-serie que me habían recomendado en varias ocasiones, y con razón. Son historias que mezclan el lado oscuro de la naturaleza humana y el uso de la tecnología. Cada capítulo además es totalmente diferente e independiente del resto y cada uno deja, a su manera, sensaciones inquietantes. Muy recomendable.

Y volviendo a mis temas habituales, sobre proyectos actuales:

  • Tuvimos reunión de mhop, y el fin de semana estuve haciendo un par de pequeñas tarea. Posiblemente esta semana comunicaremos novedades.
  • Tras un par de cambios que me pidieron en One-step parece que está todo listo, a ver si esta semana concretamos el despliegue y lo damos por finiquitado.
  • En mosica estuve trabajando para tener una página de sala, modificando como se comparten los mensajes en redes sociales y terminé de implementar el buscador de conciertos en las aplicaciones móviles.
  • Continué con la importación de Bichomanía, acabé con la importación de usuarios y extendí algunas cosas de spree/devise para no tener que modificar las contraseñas de los clientes.
  • Seguimos con la negociación de colaboración de Minchador con otra compañía. A ver si esta semana se concreta el tema, o descartamos la colaboración.

Buena semana.

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

Variable not found

Enlaces interesantes 199

May 18, 2015 07:05 AM

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

.Net

ASP.NET

Conceptos/Patrones/Buenas prácticas

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Cross-platform

Otros

Publicado en Variable not found

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

Koalite

Lectura de Códigos de Barras con HTML5 y Javascript

May 18, 2015 05:06 AM

Hace poco explicaba cómo capturar vídeo usando Javascript y HTML5. Uno de los posibles usos de esta captura de vídeo es la lectura de códigos de barras. Tradicionalmente para “leer” un código de barras se ha utilizado hardware específico, pero de un tiempo a esta parte, la capacidad de proceso es suficiente como para utilizar algoritmos de visión artificial que nos permiten localizar el código de barras dentro de una imagen y decodificarlo.

Implementar este tipo de algoritmos no es una tarea trivial (aunque tampoco es imposible), así que para ver cómo funciona vamos a usar una librería que se encarga de (casi) todo: QuaggaJS.

La librería

QuaggaJS es una librería que nos permite decodificar códigos de barras utilizando Javascript. Soporta varios tipos de códigos de barras, de momento todos unidimensionales, como EAN, Code128 o Code39.

Se trata de una librería bastante reciente (su primera versión de principios de este año) y con un desarrollo activo, por lo que todavía puede que no esté todo lo pulida que a uno le gustaría, y seguramente con el tiempo se añadan nuevas funcionalidades.

Para usarla, sólo necesitamos irla alimentando con imágenes, y ella se encargada de detectar los códigos de barras que aparezcan en las imágenes. Podemos proporcionarle imágenes estáticas, o podemos utilizar directamente el stream de vídeo procedente de la cámara para decodificar los códigos de barras en tiempo real.

El ejemplo

Vamos a ver un ejemplo de cómo decodificar códigos de barrras usando el vídeo capturado en tiempo real.

Lo primero será instalar QuaggaJS, cosa que podemmos hacer a través de npm (si vamos a usarla con browserify) o descargando y referenciando el fichero js, como hacían nuestros mayores antes de que los gestores de paquetes dominasen el mundo.

En nuestro HTML necesitaremos algo así:

<p>Barcode: <span class="found"></span></p>
<div id="interactive" class="viewport"></div>

Es muy importante que el elemento donde vamos a ir mostrando el vídeo tenga como id interactive y como class viewport. Resulta extraño, pero ahora mismo no hay ninguna forma de indicarle a la QuaggaJS el elemento que vamos a utilizar y busca directamente por esos valores.

Ahora que tenemos el HTML mínimo para realizar la captura de vídeo, podemos pasar a la parte Javascript. Empezamos por inicializar QuaggaJS:

Quagga.init({
  inputStream: {
      name: "Live",
      type: "LiveStream",
      constraints: {
            width: 640,
            height: 480,
            facing: "environment"
        }
  },
  locator: {
    patchSize: "medium",
    halfSample: true
  },
  numOfWorkers: 4,
  locate: true,
  decoder : {
      readers: ["code_128_reader", "ean_reader"]
  }
}, function() {
  Quagga.start();
});

El método init nos permite inicializar la librería estableciendo el origen del vídeo, que en este caso marcamos como LiveStream para indicar que queremos capturarlo de la cámara, los parámetros de captura, y varios parámetros del algoritmo de identificación de código de barras.

Es especialmente importante añadir en la colección de decoder.readers aquellos tipos de códigos de barras que queramos intentar decodificar, por si queremos limitar la lectura a algún tipo determinado (cosa que además acelerará ligeramente el proceso de decodificación).

Por último, podremos pasar la típica funcción callback que se invocará cuando la inicialización se haya completado. En este caso lo que haremos será iniciar el proceso de reconocimiento invocando el método Quagga.start().

Para ser notificados cuando se detecte un código de barras debemos emplear el método Quagga.onDetected(callback):

Quagga.onDetected(function(result) {
  var code = result.codeResult.code;
  document.querySelector(".found").innerHTML = code;
});

Además, podremos recibir información de cómo va el proceso de decodificación usando el método Quagga.onProcessed(callback), del cual podéis encontrar un ejemplo en el repositorio oficial.

Podéis ver el ejemplo funcionando y jugar con él en este jsfiddle.

Las pegas

Poder utilizar este tipo de funcionalidades en una aplicación web está muy bien, pero la realidad es que tiene unas cuantas limitaciones, algunas propias de la librería que hemos usado en el ejemplo y otras tal vez más ligadas a la plataforma.

En lo que respecta a QuaggaJS, se nota que todavía está un poco verde. La documentación es escasa e incompleta, y hay algunas cosas que resulta dificilmente justificables, como la obligatoriedad de identificar el elemento que va mostrar el video con un id y una clase determinada (cosa que además no he encontrado documentada en ningún sitio y me hizo perder un buen rato).

Por otra parte, su desarrollo está bastante vivo, por lo que cabe esperar que estas cosas se vayan resolviendo poco a poco.

Otro problema es el rendimiento a la hora de reconocer códigos de barras. Entiendo que el proceso que tiene que realizar es costoso porque necesita localizar el código dentro de la imagen antes de decodificarlo, pero la verdad es que no es demasiado rápido. Para leer un código de barras de vez en cuando está bien, pero si pretendes hacer una aplicación que realice una lectura intesiva de códigos de barras (por ejemplo una aplicación de inventario, de entrada de mercancía, de picking, etc.), es muy lento.

No sé hasta qué punto es culpa de los algoritmos elegidos, de la forma en la que están implementados, del rendimiento “puro” del motor de Javascript, o de la potencia del teléfono con el que he hecho las pruebas. Aun así, supongo que como todo lo que está relacionado con rendimiento será algo que vaya mejorando a lo largo del tiempo.

Posts relacionados:

  1. Cómo Generar Códigos QR en C#
  2. Captura de vídeo con HTML5
  3. La Vida en un Canvas de HTML5

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

Bitácora de Javier Gutiérrez Chamorro (Guti)

Al principio fue el libro

May 17, 2015 06:43 PM

Parafraseando el título del libro de Neal Stephenson, en el principio fue el libro. Parece ya lejano el tiempo en que la mayoría de software, bien fuera especializado como de propósito general, se vendía acompañado de manuales impresos. Además multitud de autores y editoriales, complementaban dicha bibliografía con títulos dedicados a complementar dicho material. Desde MS-DOS 3.30, GW-BASIC 3.23, Lotus 1-2-3 2, IBM PC-DOS 5 o Windows 2, hasta herramientas más especializadas como Turbo C++ 1.0 o Visual BASIC 3, todos se hacían acompañar de sus recursos en papel. En algunos casos, el motivo era por la documentación y ayuda insuficiente en el propio paquete de software. Recordemos que en MS-DOS, no existía ni HELP, no la forma de uso de algunos de sus comandos. Otros como Quick BASIC 4.5 o el mencionado Visual BASIC, a pesar de incluir una excelente documentación en linea, usaban el papel como soporte adicional. [...]

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

Blog Bitix

Nuevo diseño en Blog Bitix

May 16, 2015 10:00 AM

Hugo

En diciembre de 2013 pasé de utilizar Blogger a usar Octopress creando la bitácora Blog Bitix. Octopress fue una gran mejora a la hora de editar el contenido y gestionar las imágenes o trozos de código con gist. Hace relativamente poco que he pasado a utilizar Octopress pero desde hace un tiempo quería personalizar mucho más el diseño de la bitácora. Estaba esperando a ver como avanzaba el desarrollo de la siguiente versión sin embargo va lentamente por mucho que hayan dicho ya en el 15 de enero que Octopress 3 de está en camino, aún en mayo no hay ninguna nueva noticia desde entonces.

Posiblemente usando Jekyll directamente (Octopress está basado en Jekyll) podría conseguir el nivel de personalización que quería. Sin embargo, revisando otras opciones dí con otra plataforma de generación de sitios estáticos, Hugo. De Hugo me han gustado varias cosas que en Octopress no tenía:

  • Ejecutable: Hugo es un único binario, basta descargar este único archivo. Está desarrollado en el lenguaje go (Jekyll y Octopress en Ruby). No hay dependencias que descargar que «ensucien» el sistema, esto también tiene la ventaja de que la actualización a una nueva versión es sencilla.
  • Temas: crear un tema para Hugo es sencillo y hay una documentación básica pero suficiente.
  • Rapidez: el lenguaje go y Hugo alardean de rapidez y mis sensaciones coinciden con ello, la bitácora completa se genera en unos pocos segundos, los cambios en un artículo son casi instantáneos y el servidor web local arranca muy rápido.
  • Taxonomía: con Hugo al contenido se le puede aplicar una taxonomía muy versátil que por ejemplo permite crear series de artículos. Con Octopress tenía que modificar cada artículo de la serie para incluir uno nuevo, con Hugo basta que lo defina en el front matter y el resto de artículos de la serie se actualizarán incluyéndolo.

Con Hugo también he tenido que hacer algún hack y es que en los diferentes artículos de la bitácora suelo incluir enlaces a un montón de herramientas, para no estar repetirlos constantemente y en el caso de que uno cambie no tener que modificar los artículos individualmente tengo un archivo de enlaces comunes que incluyo en cada artículo, y en esta inclusión está el hack, usando algunas de las funciones que proporciona Hugo. También he tenido que crear un script para subir los cambios al alojamiento que uso con GitHub Pages cosa que Octopress proporciona de serie, usar Grunt para generar el archivo de estilos css a partir de un archivo Less o reescribir las urls de los feeds para que sean absolutas.

Entre las cosas de diseño que quería cambiar estaba la cabecera intentando que fuese pequeña verticalmente para que según se cargue la página se vea la mayor parte posible de contenido, con esto he quitado la descripción de la bitácora de la cabecera y la he puesto en el pié de página. En el menú he puesto enlaces a las secciones de las que suelo hablar: Java, GNU/Linux, JavaScript y Apache Tapestry. Los usuarios podrán encontar más fácilmente el contenido de los temas principales que escribo y quizá Google averigüe un poco mejor de que trata la bitácora. Entre otras cosas he cambiado el tema a uno basado en el color blanco, reorganizado los bloques de anuncios de publicidad Adsense, eliminado Karmacracy por nulo uso para compartir contenido y dejando solo Share This para este propósito, he situado los enlaces de sindicación al lado del logotipo para darles más visibilidad, cambiada la visualización de los thumbnails de las imágenes ahora se podrán ver en un tamaño mucho más grande y mejor, la página de inicio ahora solo incluye un resumen de los artículos en vez del artículo completo con lo que espero que esta página se cargue mucho más rápido, un fondo que varía de forma aleatoria en cada carga de página (lo mismo que hago en Blog Stack), añadidos algunos estilos para poner pies en las imágenes y algunas correcciones y modificaciones más en el pie y en la barra lateral.

Diseño de Blog Bitix ahora con Hugo y antes con Octopress

Las urls del contenido no han variado, sí algunas del archivo y de las etiquetas pero como tengo bloqueadas estas con el archivo robots.txt Google no me indicará errores 404. Probablemente si me informe de algún 404 en el contenido aunque espero que no muchos, si ocurre los corregiré en los próximos días o cualquier otra cosa de la que vaya dándome cuenta.

El código fuente completo del tema que he creado y del blog realizado con Hugo puedes encontrarlo en el siguiente repositorio de GitHub.

¿Que te parece el nuevo diseño?

Referencia:
Hola nuevo mundo

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

Variable not found

Variables de sesión en MVC6 / ASPNET5

May 13, 2015 09:36 AM

ASP.NET MVC
Seguimos hablando de novedades que acompañarán la próxima versión de MVC y ASP.NET, y esta vez le toca el turno a otra de los grandes ausencias que podemos notar cuando creamos desde cero una aplicación utilizando estos frameworks: las variables de sesión.

Bueno, en realidad no se trata tanto de una ausencia como de un desplazamiento de esta característica. Resumidamente, las variables de sesión seguirán existiendo, pero no son parte del core de ASP.NET 5, como ocurría desde la primera versión de ASP.NET, sino un componente totalmente opcional implementado en forma de middleware que deberá ser instalado y configurado de forma independiente.

Pero antes de continuar, recordad que tanto MVC6 como ASP.NET 5 siguen estando en proceso de desarrollo, por lo que algunas de las cosas que contaremos podrían cambiar en las versiones definitivas, aunque espero que no demasiado.

Y dicho esto, vamos al lío: ¿cómo utilizamos variables de sesión en aplicaciones basadas en ASP.NET 5?

1. Descarga e instalación del middleware proveedor de sesión

Siguiendo la nueva filosofía modular de ASP.NET 5, los mecanismos de almacenamiento y recuperación de variables de sesión son ahora un componente que podemos añadir a nuestras aplicaciones de forma opcional.

Como es habitual, la descarga e instalación la realizaremos a través del interfaz de Nuget en Visual Studio, o bien añadiendo manualmente la referencia al archivo project.json. El nombre del paquete que nos interesa es Microsoft.AspNet.Session, como se muestra en la siguiente captura de pantalla:

Reference session package

Una vez hecho esto, ya tenemos en nuestro proyecto los componentes básicos que necesitamos para poder usar variables de sesión. Continuamos el proceso…

2. Añadir el middleware al pipeline

Session middleware in the pipelineEl estado de sesión es proporcionado por el middleware SessionMiddleware, presente en el paquete que acabamos de descargar. Este middleware, insertado en el pipeline de proceso de las peticiones, ofrecerá a los frameworks o componentes posicionados tras él la capacidad de usar variables de sesión.

El hecho de posicionarse en el pipeline y ser “atravesado” por la petición brinda a este middleware la posibilidad de establecer la cookie de sesión que distinguirá de forma única al usuario, preparar el acceso a sus datos y almacenar los cambios producidos durante el proceso de la petición.

Y ojo, que esto es importante: hay que añadir el middleware que proporciona el estado de sesión antes que el propio framework MVC. De no ser así, la petición será procesada por MVC antes de el middleware de sesión sea ejecutado, por lo que desde nuestras aplicaciones no tendremos acceso a las variables de sesión.

El siguiente ejemplo muestra cómo introducir el middleware en el pipeline, utilizando la memoria como almacenamiento para el estado de sesión:

UseInMemorySession

En aplicaciones pequeñas y sin demasiadas aspiraciones, almacenar las variables de sesión en memoria es una solución efectiva y razonable. Sin embargo, cuando la aplicación debe crecer a varios servidores o se necesita una solución menos volátil, podemos usar otros mecanismos de persistencia, utilizando el extensor UseDistributedSession() en lugar de UseInMemorySession() visto anteriormente. No entraremos en más detalle en este post, lo dejaremos para más adelante, pero es muy interesante el hecho de que esto descanse sobre el sistema de caching de ASP.NET, del que ha hablado el gran Unai hace poco.

Como suele ser habitual a la hora de añadir módulos al pipeline, es posible indicar opciones de configuración:

Middleware options

3. Establecer, obtener y eliminar variables de sesión

En primer lugar, es importante tener en cuenta que los pasos anteriores son obligatorios si queremos utilizar variables de sesión. Cualquier intento de utilización de las mismas sin haber instalado y configurado previamente los componentes que las proporcionan provocarán la aparición de un error:

Error trying to use Session vars without installing or configuring the middleware

El acceso a las variables de sesión se realiza utilizando la propiedad Context.Session, es decir, la clase Controller no proporciona ya una propiedad Session como en versiones anteriores de MVC, aunque obviamente siempre podríamos crearnos un atajo (por cierto, fijaos qué limpio queda usando las nuevas expresiones lambda en miembros de función de C# 6):

Session property
Los que ya habéis usado antes variables de sesión, seguro que os sorprende esos métodos GetInt() y SetInt() de la propiedad Session. Pues sí, esto otro cambio importante sobre las versiones anteriores del framework.

Hasta ahora podíamos introducir cualquier tipo de objeto en variables de sesión, y el abuso de esta capacidad ha generado muchísimos problemas. He llegado a ver incluso contextos de datos o conexiones a bases de datos mantenidas en memoria de esta forma, creando unos problemas terribles en tiempo de ejecución. También ha sido tradicionalmente un limitante de la posibilidad de escalado de las aplicaciones (aunque puede solventarse usando algunos trucos de balanceado), y un problema para la fiabilidad  de los sistemas (recordad que un reseteo del servidor, de IIS o incluso un reciclado del pool limpia la memoria).

Session vars are byte arraysPara evitar esto, a partir de ASP.NET 5/MVC 6 sólo podremos guardar en variables de sesión objetos serializados, y esto se manifiesta en el tipo de dato que es ahora el diccionario Session: un array de bytes. Con esto, se acabó el establecer o leer objetos completos directos como hemos hecho siempre, tendremos que serializarlos a un array de bytes para guardarlos el almacén de sesión, así como deserializarlos para poder acceder a ellos. De esta forma, simplificamos el uso de almacenamientos distintos a la memoria local para esta información, facilitando la escalabilidad y mejorando la fiabilidad.

El framework nos proporciona métodos extensores para facilitar las tareas de serialización y deserialización en escenarios comunes, como el almacenamiento y recuperación de variables de sesión de tipo entero y cadenas de texto, mediante los métodos GetInt(), SetInt(), GetString() y SetString(), como se muestra en el siguiente ejemplo:

Session extensions

Si por cualquier motivo queremos guardar un objeto o grafo complejo, tendremos que crear nuestro propio mecanismo de serialización. Aunque la primera tentación puede ser crear un serializador binario usando la clase BinaryFormatter de toda la vida, resulta que la serialización binaria no está soportada en .NET Core, supongo que debido al carácter cross platform de este framework.

Pero sí podríamos, por ejemplo, serializarlo a JSON y guardarlo como string en la variable de sesión y realizar el proceso inverso al recuperar el valor, o bien crear nuestras propias funciones extensoras para facilitarnos la vida en el futuro:

Serialization helpers

Así, ya podríamos usar construcciones más sencillas como las siguientes:

Helper usage

Nota: existen conversaciones en Github sobre la inclusión de métodos genéricos Set<T>() y Get<T>() que permitan indicar un componente de serialización como Protobuf o Bond, así que posiblemente las versiones finales de ASP.NET 5/MVC 6 encontremos algo de ello.

Por otra parte, para eliminar variables de sesión podemos seguir utilizando el método Remove(), al igual que hemos hecho siempre:

Context.Session.Remove()

4. Otros cambios respecto a versiones anteriores

Por último, vamos a comentar un par de detalles que han sido modificados respecto a versiones anteriores de ASP.NET.

Comenzaremos diciendo que en ASP.NET 5 no existe (al menos de momento) un método Abandon(). En cambio, se añade un método Clear() que permite eliminar toda la información de sesión del usuario conectado.

Y una última cosa interesante a tener en cuenta es que ya no están disponibles los eventos Session_Start() y Session_End() que podíamos capturar en el Global.asax en versiones anteriores del framework.

Bueno, pues de momento lo dejaremos aquí. Espero que lo visto os sea de utilidad para continuar interiorizando los cambio que se avecinan con las nuevas plataformas y que la transición a ellas sea un poco menos dolorosa ;)

Publicado en Variable not found.

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

Picando Código

Datos Abiertos de Gobierno en Uruguay

May 13, 2015 01:55 AM

Datos AbiertosLos días 12 a 14 de mayo se está realizando en Montevideo el Taller de Desarrollo de Capacidades Datos Abiertos de Gobierno en Uruguay, evaluación y planificación estratégica. Es un nombre muy largo, pero de gran importancia para los uruguayos y la movida de Datos Abiertos en general.

Hoy martes 12 de mayo, tuvo una primera parte que consistió en una actividad cerrada para las autoridades de alto nivel. La idea de todo el evento es de sensibilizar a las nuevas autoridades con el tema y conectar actores clave del ecosistema de datos abiertos y empezar a preparar la política entorno a los Datos Abiertos para los próximos años.

Entre los asistentes se encontraban ciudadanos, organizaciones de la sociedad civil (DATA, CAINFO) y agencias como AGESIC, UNDESA y DPADM, funcionarios de distintos entes y más.

Estuve sacando algunas notas así que a continuación comento un poco sobre el primer día:

La segunda actividad de la tarde estaba abierta a mandos medios y referentes técnicos. Empezó con una presentación de Virginia Pardo, Directora del Área de Ciudadanía Digital de AGESIC. Contó sobre la primera etapa ya concluida en la agenda de Datos Abiertos 2011-1025, y que el objetivo con este taller era empezar a construir la nueva agenda 2016-2020. Las Naciones Unidas se involucrarían en esta nueva etapa con apoyo conceptual y capacitación.

Las Naciones Unidas, Datos Abiertos de Gobierno y Uruguay

La siguiente oradora fue Arpine Korekyan, Oficial de Gobernanza y Administración Pública en DPADM, UNDESA, básicamente centrada en Datos Abiertos de Gobierno con las Naciones Unidas.

UNDESA

En la encuesta Mi Mundo 2015, más de 7.5 millones de personas en el mundo decidieron cuáles eran los aspectos que más le importaban. Después de Educación, Salud y Trabajo como primeros tres temas en los resultados, un Gobierno honesto y receptivo tomó el cuarto lugar. En la conferencia Rio +20 también apareció como interés un gobierno efectivo y capaz de representar las voces e intereses de todos.

De esto se desprende que es un tema importante promover el acceso a la información de gobierno, promover sociedades pacíficas e inclusivas construyendo instituciones efectivas, responsables e inclusivas en todos los niveles.

Los Datos de Gobierno son información producida o recogida por entidades gubernamentales. Pasan a ser datos abiertos cuando pueden consultarse fácil y rápidamente y pueden ser reusadas por cualquiera con acceso (licencia libre y estructurados de forma que puedan ser procesados). Antes cualquier dato de gobierno era confidencial por defecto a menos que se especifique lo contrario. Ahora la tendencia es a hacerlos abiertos a menos que se especifique lo contrario.

Los beneficios de promover los Datos Abiertos de Gobierno para las Naciones Unidas y diría que en general:

  • Transparencia y confianza en el gobierno
  • Incentivar participación ciudadana en diseño de políticas y servicios
  • Mejorar efectividad y eficiencia
  • Oportunidade de negocios y trabajo
  • Innovación e investigación

¿Por qué Uruguay?

Habían varios factores a tener en cuanto cuando la ONU eligió los 4 países con los que colaboraría en la iniciativa de Datos Abiertos. El interés en este tipo de iniciativas, la infraestructura disponible, parámetros técnicos y apoyo en el área (contraparte de los gobiernos, etc.).

Esto deja muy bien parado a Uruguay en materia de Datos Abiertos, porque ha habido un trabajo importante desde el gobierno y varios de sus entes, y también la contraparte (hola DATA <3) en forma de sociedad civil. Necesitamos más involucrados :)

Los logros esperados son la capacitación de los cargos superiores de gobierno para formular políticas en conjunto con actores relevantes de la sociedad civil.

Qué, Por Qué y Cómo de los DAG para el desarrollo sustentable

Siguió Daniel Dietrich, consultor internacional DPADM y asesor en políticas de Datos Abiertos de Gobierno. Comentar que Daniel es alemán pero habló en un español casi perfecto. También fue el que nos informó del hashtag oficial del evento que pueden seguir en Twitter: #openUY.

Los Datos Abiertos crean valor social y económico en la sociedad. Traen consigo un cambio cultural en cómo el gobierno y los ciudadanos interactúan y cooperan. Citó la célebre frase de Abraham Lincoln sobre un gobierno ” del pueblo, por el pueblo y para el pueblo”. Si bien es una frase del siglo 19, ahora tenemos las herramientas y la tecnología para hacerlo una realidad.

Habló de la definición de Datos Abiertos (no lo voy a repetir, pero: Datos Abiertos: Qué son y por qué debería importarte), razones para usarlos y la implementación de un programa de Datos Abiertos. Mencionó ejemplos exitosos como en el tema ambiental Info Amazonia (noticias y reportes de la región en peligro del Amazonas) y en Estados Unidos la Energy Data Initiative (esfuerzo para liberar datos de gobierno y voluntarios para crear valor, trabajos y emprendimientos en la transición a una economía de energía limpia).

En materia de salud, comentó el caso de Sir Bruce Keogh, cirujano que convenció a sus colegas en de publicar los datos de los resultados de su trabajo, y 7 años más tarde se encontraron mejoras en los índices de supervivencia. También comentó como muchas veces los gobiernos mismos gastan dinero buscando datos necesarios para sus trabajos.

Casos de éxito con Datos Abiertos en Uruguay

Le tocó la palabra a Daniel Carranza, Consultor Nacional de DPADM y asesor en políticas de Datos Abiertos de Gobierno, y colega de DATA. Daniel comentó sobre el ecosistema en Uruguay con un diagrama que mostraba la intersección entre tres conjuntos: el gobierno, la sociedad civil y la empresas como los principales actores.

Habló de varios casos en Uruguay y el impacto que tuvieron interna y externamente (aportando valor a la sociedad y más). Comentó el caso de la Dirección Nacional de Catastro, donde se trabajó internamente en la gestión de datos y se terminaron liberando. También mencionó los Datos Abiertos de Compras Estatales, que ya tenía una buena gestión de datos interna, pero se trabajó para publicarlos. Aparentemente no hay un consumo externo ni participación ciudadana con los datos pero sí empresas que basan su negocio en ellos.

En el Municipio de Maldonado (¡mis pagos! \o/) se creó la aplicación ABREDATOS, que permite la gestión de datos abiertos por defecto. ¡Esta aplicación está siendo usada por la Ciudad de México para gestionar sus datos! También habló del caso de precios.uy y el trabajo entre AGESIC con su hackatón “Dateidea”, Defensa del consumidor y el grupo de trabajo que ejecutó el proyecto.

También se mencionó AtuServicio, proyecto del cual hablé por acá:
AtuServicio – Proyecto de Datos Abiertos con DATA

Hacia un estado más cercano

AGESICVolvió a tomar la palabra Virginia Pardo de AGESIC, comentando sobre las líneas de acción 2011-2015, normativas y buenas prácticas, tecnología y apropiación y fomento de uso. Comentó los hitos de AGESIC en la agenda de Gobierno Abierto y entre hackatones, proyectos y varios éxitos más, anoté que hoy en día hay 4 medios de prensa que trabajan con datos abiertos. AGESIC ya tuvo talleres de periodismo orientado a Datos Abiertos con investigación. Una lástima que la prensa uruguaya no sea participante más activa de este tipo de iniciativas.

Sesiones de trabajo

Tras las charlas se hizo un breve corte para tomar café y empezar las sesiones de trabajo en grupos. Hubo una separación en cuatro grupos para enfrentar temas distintos: Regulación y normativa, Reuso, Salud y Medio Ambiente. Ahí nos separamos en los 4 grupos con facilitadores y se discutieron ideas entorno a cada tema. Mañana se seguirá trabajando en los distintos temas y habrán conclusiones y más notas después. Ya les contaré qué tal al finalizar el evento.

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

El blog de Adrián Arroyo

Crea tu propio lenguaje de programación

May 12, 2015 10:00 PM

Esta entrada la escribí en DesdeLinux hace ya un tiempo y la quiero conservar aquí. La entrada no es la original sino que la he modificado para que siga vigente - MAYO DE 2015

Lenguajes de programación

Después de escribir el primer artículo sobre cómo crear tu propio sistema operativo, alguien me dijo que si podía hacer un artículo sobre cómo crear un lenguaje de programación. Al principio no hice mucho caso, pero ahora y por otros caminos he aprendido bastante más sobre la creación de los lenguajes de programación. Así pues, vamos a hacer un lenguaje de programación básico, fácilmente empotrable en otros programas y que funcione con una máquina virtual que también diseñaremos. Hoy nos toca hacer la máquina virtual más básica.

Probablemente te preguntes: “¿una máquina virtual? ¿Pero eso no es muy difícil y además ralentiza los programas?” Al contrario, una máquina virtual simple es muy sencilla y relativamente rápida. He elegido Rust como lenguaje para la máquina virtual. Pero, ¿qué es Rust?

Rust es un lenguaje de programación que está enfocado en la seguridad en las ejecuciones, así que utilizándolo será prácticamente imposible que alguien consiga cerrar la máquina virtual. Es un lenguaje compilado en desarrollo creado por Mozilla. Servo, el sustituto de Gecko, se está desarrollando en él. Todavía puede cambiar su sintaxis pero el código que voy a usar va a mantenerse hasta la primera versión estable.

Rust se instala en Linux de manera sencilla. Antes se podía usar un PPA pero ahora el script de RustUp es muy bueno y se encarga de todo.

curl -s https://static.rust-lang.org/rustup.sh | sudo sh

###¿Cómo funciona una máquina virtual?

Si sabes como funciona el mundo en ensamblador es exactamente igual, con el stack o la pila. Si no, te lo explico. Imaginémonos el siguiente código:

print 2+3

El ordenador no entiende lo que significa 2+3, ni tampoco sabe qué orden hay que seguir. Los ordenadores funcionan con pilas o stacks en los que se van acumulando datos y se van sacando continuamente. Ese código en nuestra máquina virtual debería ser algo parecido a esto:

PUSH 2
PUSH 3
ADD
PRINT

Básicamente, pondríamos el 2 en la pila en lo alto, el 3 también. ADD sacaría (es decir, lo elimina de la pila y obtiene su valor) los 2 últimos elementos de la pila y añadiría el resultado en lo alto de la pila. PRINT cogería el último elemento de la pila y lo usaría para mostrárnoslo. Ahora hagamos eso en Rust.

Ahora es cuando deberías descargarte el código fuente que está en GitHub. Voy a empezar por el archivo vm.rs

Primeramente deberemos definir un lenguaje para el Bytecode, podríamos usar uno ya existente como el de Java o el CLR de .NET/Mono, pero vamos a crear nosotros uno más básico.

Usamos notación hexadecimal para cada instrucción. Para hacer la traducción entre el código hexadecimal y la instrucción voy a usar la librería (crate en el argot de Rust) de enum_primitive. Antes se podía usar #[derive(FromPrimitive)] pero en Rust 1.0 no está disponible.

Ahora debemos hacer una función que ejecute cada una de esas instrucciones. Para ello debemos leer un byte y compararlo con las instrucciones que tenemos en la enumeración. Si se encuentra alguna que exista se debe ejecutar su acción.

Eso hacemos para leer cada byte individualmente y para ejecutarlas:

Como ven, diferenciamos si antes se nos dio la orden de PUSH (nuestra orden INTEGER), el siguiente byte será llevado completamente a la pila. Ahí estamos usando dos funciones que no les he enseñado, self.pop() y self.push(), que se encargan obviamente de manejar el stack.

No son muy complejas, pero la función de pop tiene mecanismos de detección de errores. De hecho, en Rust, si quitásemos esos mecanismos nos daría un error de compilación. Ahora simplemente debemos llamar en un programa a Perin (nuestra máquina virtual) y que ejecute un bytecode.

Ese bytecode puede ser leído de un fichero, pero aquí para simplificar lo he almacenado en una variable. Si lo ejecutamos nos dará el resultado esperado:

Perin v0.1
Perin VM executes FlopFlip bytecode
Starting PerinVM instance
PerinVM v0.1.0
Integer value 5

Todo el código está disponible en GitHub bajo la Apache License 2.0: https://github.com/AdrianArroyoCalle/perin. Para compilar deben tener Cargo instalado y poner:

cargo run

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

Arragonán

Semanas 360 y 361

May 12, 2015 01:49 PM

Vuelta a acumular semanas sin resumen, que la anterior ya cuando me planté a mitad decidí dejarlo para esta.

Durante estas dos semanas en SenpaiDevs tuvimos visitas de José Luis Lizano y Guillermo Latorre que nos hablaron de diseño y maquetación, también se vino Francho Joven a hablar de Rails y de cómo trabaja él. Además presentamos por fin el proyecto en el que veníamos trabajando con los kohais, un calendario de eventos tecnológicos en Zaragoza.

El pasado jueves tuvimos reunión mensual de Zaragoza.rb (la de abril que traíamos retrasada por el festivo del 1 de mayo), en la que hablamos a modo de comparativa de Middleman y Jekyll.

Estas semanas han llegado bastantes contactos para posibles nuevos proyectos, veremos si se van concretando o van cayéndose.

En cuanto a los actuales:

  • Retomando Bichomanía acabé con la importación de productos y sus respectivas imágenes, y me encontré con un problema con la codificación de caracteres que aún está a medio solucionar. También empecé a trabajar en la compatibilidad de las urls de la actual tienda para no romper los enlaces existentes.
  • Dejé ya casi cerrado One-step. Implementé una gestión de informes, finiquité la parte del frontend y estuve resolviendo un problema de integración. Ahora queda ver las cuestiones de despliegue y poco más.
  • Tuvimos un primer contacto para una posible colaboración de Minchador con otra compañía, veremos si llegamos a un acuerdo.
  • En Mosica nos dio por montar un grupo de telegram para ir a conciertos y estuve haciendo alguna mejora en la versión móvil. Además por fin tenemos publicadas las aplicaciones móviles en la app store y en play.

Buena semana.

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

Variable not found

Enlaces interesantes 198

May 11, 2015 08:52 PM

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

.Net

ASP.NET

Azure / Cloud

Data access

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Otros

Publicado en Variable not found

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

Picando Código

Del Dicho al Hecho – ¿Cuánto cumplen los políticos de su discurso?

May 11, 2015 06:35 PM

En Uruguay terminó ayer domingo el período de elecciones 2014-2015 que pareció durar siglos. Durante este tiempo, mucha gente se pone la camiseta de su partido político cual cuadro de fútbol, para después de elegido el gobierno de turno se olvide que existe la política hasta las siguientes elecciones.

En los medios hay que escuchar peleas, discusiones, demagogia, y ante todo promesas, muchas promesas de los candidatos. Y así como la gente se olvida de su bandera y la camiseta de su partido por unos años, también se olvida de lo que hizo y prometió cada candidato. Pero la Tecnología Cívica llega al rescate.

Del Dicho al Hecho

En Chile, a la gente de Fundación Ciudadano Inteligente (Fundación Ciudadano Inteligente – Quiénes son, y por qué Google les donó 1/4 millón de dólares ), creó Del Dicho Al Hecho: proyecto que fiscaliza el cumplimiento de las promesas del Programa de Gobierno. En su momento escribí al respecto en el blog, y ahora contamos con una nueva instancia de la aplicación en Uruguay de la mano de UYCheck:

Del Dicho al HechoDel Dicho al Hecho es una plataforma dedicada al monitoreo del cumplimiento de las propuestas electorales realizadas por los Intendentes más populares de nuestro país. Con una metodología específica (http://bit.ly/1HcxoLR), se genera un esquema de puntuaciones para un conjunto de propuestas seleccionadas relacionadas básicamente a algunos de los cometidos más destacados de los gobiernos departamentales.

Esta plataforma surge a partir de su homónimo chileno desarrollado por la Fundación Ciudadano Inteligente. Con el apoyo y mentoría de esta fundación, y en contexto de Elecciones Departamentales, el equipo de UYCheck se embarcó en la ardua tarea de darle forma y contenido a Del Dicho al Hecho Uruguay.

La búsqueda de la transparencia en las gestiones gubernamentales, el acceso a la información pública y el empoderamiento de la ciudadanía son los grandes objetivos de esta nueva herramienta.

Dado el amplio y complejo universo de candidatos y programas de gobierno que fueron presentados en estas elecciones departamentales, el estudio de Del Dicho al Hecho se centra en los intendentes más votados de cada partido político, así como en 4 áreas de propuestas: obras, higiene y medio ambiente, calles y tránsito, y desarrollo departamental. Cada 6 meses se presentará un avance sobre el estado de situación del cumplimiento  estas propuestas.

El sitio está disponible para los siguientes departamentos:

Este tipo de proyectos es genial y cuantos más proyectos de este estilo, mejor. Por un lado le devuelven poder a la ciudadanía de controlar a los gobernantes. Por otro lado, es un proyecto de colaboración entre grupos de países latinoamericanos y basado en Software Libre. El código está disponible en GitHub bajo licencia GPLv3.

Va a ser muy interesante poder ir viendo el avance (o falta de) respecto a las promesas de campaña. Y una vez terminado el período de gobierno, contrastar los resultados y sacar cuentas. Más allá de lo que pensemos de la política partidaria o el sistema electoral, este tipo de iniciativas generan cambios en la dirección correcta.

Felicitaciones a la gente de UYCheck por el proyecto y ojalá tenga mucho éxito y vengan más del estilo.

Ya que estamos con el tema de Tecnología Cívica, les recomiendo la lectura de la siguiente nota
Tecnología Cívica y Datos Abiertos: ¿Una relación evidente?

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

Bitácora de Javier Gutiérrez Chamorro (Guti)

Vivaldi Browser

May 09, 2015 10:16 AM

Vivaldi Browser, es un nuevo navegador web gratuito, que se encuentra disponible para Windows, Mac y Linux, desararollado por Vivaldi Technologies, sobre la cual se encuentra en anterior fundador de Opera: Jon Stephenson von Tetzchner. Su objetivo es claro, crear un navegador web idóneo para usuarios avanzados, y para entusiastas del anterior Opera. Como decía, desde su paso a Blink, Opera 15 no tiene nada que ver con sus predecesores de la versión 12 y anteriores, siendo ahora un Chromium con una apariencia ligeramente distinta, pero habiendo perdido por el camino multitud de funciones, que aún no se han reimplementado. Os mencionaba Vivaldi con el anterior una de enlaces, pero creo que merece una cobertura más detallada. De cara a ganar tiempo en el desarrollo, parten de un enfoque revolucionario, toda la interfaz del programa, está desarrollada usando HTML y Javascript, que corre sobre el motor de Blink/Chromium/Chrome. Lo malo [...]

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

Blog Bitix

Programación de juegos y 3D en Java con jMonkeyEngine

May 09, 2015 08:18 AM

jMonkeyEngine
Java

Erróneamente se sigue pensado que Java es un lenguaje lento en ejecución, en las primeras versiones era cierto pero hoy la realidad es que con las mejoras introducidas en cada versión de Java y la máquina virtual el rendimiento actual es comparable a C y C++. En la programación de juegos y 3D gran parte del proceso de representación gráfica se ha descargado de la CPU a las cada vez más potentes tarjetas gráficas, la potencia de estas GPU son las que determinan la capacidad de proceso gráfico y la calidad gráfica de los juegos.

Java no suele ser considerado como opción para programar videojuegos triple AAA pero ahí está Minecraft uno de los juegos más populares y un ejemplo de que un juego de buena calidad y rendimiento también se puede hacer en Java. Hay algunos otros ejemplos notables como de variados estilos RPG, Puzzle, MOBA, Rogue, RTS, Card MMOG, FPS, Arcade, Platform ,…:

Este es un vídeo del juego PirateHell que tiene una pinta muy buena:

Algunas capturas de imagen de estos juegos, en los enlaces anteriores se pueden encontrar vídeos de algunos de ellos.

Todos estos juegos están programados utilizando el lenguaje de programación Java y la librería jMonkeyEngine que facilita las tareas de programación de videojuegos proporcionando programación gráfica en 3D usando OpenGL, manejo de eventos de entrada como teclado o ratón, manejo de sonido, pantallas de menús o red. Usando jMonkeyEngine se pueden hacer cosas muy interesantes como se ve en los ejemplos. En el siguiente enlace se pueden encontrar el código fuente de varios ejemplos que podemos probar.

A continuación mostraré el código y unas capturas de pantalla de algunas las posibilidades de jMonkeyEngine. Primeramente veamos como crear un ejemplo básico con un cubo aplicándole una textura con el que veremos como crear una escena. El segundo ejemplo aplica texturas de diferentes formas que varían la visualización de un elemento geométrico.

<noscript><pre>https://gist.githubusercontent.com/picodotdev//raw/HolaMundoJMonkeyEngine.java</pre></noscript>
<noscript><pre>https://gist.githubusercontent.com/picodotdev//raw/Materiales.java</pre></noscript>

Se pueden crear objetos con texturas transparentes, efectos de luz, ray casting, sistemas de partículas con las que simular fuego, chispas, polvo, establecer animaciones a objetos como cuando un personaje está descansando, terrenos, paisajes, aplicar efectos simulando la física del mundo real, sonido ambiental y posicional y más cosas. En las siguientes imágenes se pueden ver algunos ejemplos de las anteriores posibilidades (la tasa de fps normal es de 60, al tomar las capturas baja).

Un videojuego se compone de múltiples recursos como imágenes, modelos 3D, música, sprites, texturas, fuentes de texto, sonidos, iconos… en la página Open Game Art podemos encontrar todo este tipo de material sin necesidad de tener que crearlo desde la nada.

jMonkeyEngine ofrece un entorno de desarrollo (IDE) basado NetBeans. Descargando el paquete de jMonkeyEngine y copiando las librerías .jar los programas se puede ejecutar perfectamente independientemente del IDE y desarrollar con eclipse y usar la herramienta de construcción gradle.

Para instalar jMonkeyEngine debemos descargar el SDK adecuado para la plataforma que usemos ya sea Windows, Linux o Macintosh. En el caso de Linux es un archivo .sh que deberemos ejecutar (dando permisos de ejecución si es necesario), seguimos las instrucciones y seleccionamos el directorio de instalación del SDK. En jmonkeyplatform/libs de la carpeta de instalación encontramos los archivos .jar que deberemos usar en el IDE o en los programas de los ejemplos.

El libro jMonkeyEngine 3.0 Beginners Guide me ha resultado muy interesante como punto de introducción a la programación gráfica 3D con Java, pero también si realmente nos interesa la programación de videojuegos es muy recomendable leer el material ofrecido en el Curso de Experto en Desarrollo de Videojuegos, un libro de una extensión de más de 1100 páginas de muy buena calidad, en español y descargables gratuitamente. En la wiki de jMonkeyEngine se pueden encontrar numerosos tutoriales para principiantes, también numerosos artículos de nivel más avanzado y el javadoc de la API.

Otras librerías como Slick2D permiten hacer videojuegos en 2D como serían los juegos de plataformas, más o menos lo que permite jMonkeyEngine en el 3D aplicado a 2D también usando como lenguaje Java. Sin duda los videojuegos han sido el motivo en parte de que muchos hoy seamos programadores e informáticos aunque en nuestro trabajo nos dediquemos a otro tipo de aplicaciones y entornos.

Que, ¿aún crees que en Java no se pueden hacer juegos que no tienen que envidiar a muchos otros?

Referencia:
jMonkeyEngine
Curso Experto Desarrollo Videojuegos
Libro jMonkeyEngine 3.0 Beginners Guide
Slick2D
libGDX

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

xailer.info

Xailer 4.0.1

May 08, 2015 12:37 PM

Estimados usuarios de Xailer,

Tenemos el placer de anunciaros una nueva versión de Xailer que incluye un montón de novedades y mejoras, a destacar las siguientes:

  • IDE:
    • TTreeView: Error al guardar los treeviewitems en los .xfm
    • User controls: Mejorados mensajes de error
    • SQLite editor: Posibilidad de salvar los registros a visualizar
    • Incluida libreria iphlpapi en configuración de MinGW

     

  • DataControls
    • TSQLite: Cambiado en CreateTable() el tipo “M” de “MEMO” a “MEMOTEXT”
    • TWebDataSource: Error en busqueda de clave primaria por no usar acentos delimitando el nombre de tabla
    • TDbfdataset: Soporte de lAutoSeek en datasets DBF
    • TDataSource: Nuevo evento OnExecute( oSender, cSql )

     

  • Controles
    • TLabelEx: Error en cálculo de posición de enlaces
    • TOcx: Pasar los parametros VT_DISPATCH como objetos TOleAuto en los eventos
    • TOcx: Error con fechas en blanco
    • TLabelEx: Error en recepción de foco
    • TRichedit: Nuevas propiedades lRE70, lRE80 y nUlineColor
    • TCombobox: Al cambiar el foco durante un OnExit, no se restauraba el foco correctamente
    • TDateEdit: Soporte de mouse wheel en edicion que permite scroll de dias, meses o años
    • TPicture: Perdida de memoria cuando se cargaba una imagen con gdi+

     

  • Clases
    • TApplication: Mejora con lSingleInstance para que active la instancia existente

     

  • Fast-Report
    • TFastReport: Error en llamada a funcion LOADIMAGEFROMHBVAR
    • TFastReport: Correcion menor para tipos BLOB que fallaban a partir de Harbour 4

Os recordamos que para poder usar esta nueva versión hay que tener una suscripción activa de Xailer y que exige realizar de nuevo el registro de todas sus instalaciones. Todos los usuarios con suscripción activa deben haber recibido un E-mail con la nueva información de registro, pero en cualquier caso puede volver hacer el registro directamente desde la opción de menú Ayuda-Registrar el producto.

En caso de no tener una suscripción activa sólo podrá utilizar Xailer 4 en modo DEMO y por lo tanto deberá instalarla en un distinto directorio.

Un saludo

[El equipo de Xailer]

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

xailer.info

Cancún Junio 2015

May 08, 2015 11:12 AM

Estimados usuarios de Xailer,

Más o menos cada dos años , tengo el placer de poder reunirme en la ciudad de Cancún con una importante comunidad de usuarios de Xailer, que mayoritariamente provienen del propio Mexico, pero también acuden normalmente colegas de Brasil, República Dominicana y Venezuela, entre otros.  Espero que está vez podamos contar con más colegas de distintos países. A los españoles es difícil de mover ya que hay que cruzar el charco, pero es que además tiene más fácil acceder al equipo de Xailer ya que de forma periódica se organizan reuniones como lo que acaba de producirse en Madrid hace muy poco tiempo.

En cada reunión intento presentar algo especial de Xailer que entiendo puede interesar a los programadores de Xailer que ya tienen cierta experiencia. Esta vez quiero centrarme básicamente en la migración a sistemas SQL, desarrollo de aplicaciones en la nube e integración con herramientas CRM. No obstante, aprovecharemos la ocasión para ver todas las mejoras que incluye Xailer 4. Intentaremos evitar profundizar demasiado en las características del lenguaje SQL ya que entendemos que es algo que posiblemente muchos usuarios ya conocerán, pero si mostraremos la potente herramienta que incluye Xailer 4 para diseñar visualmente las consultas SQL.

Voy a intentar exponer a continuación las directrices del temario que seguiremos en el curso:

  • Novedades de Xailer 4
  • Introducción a Sqlite, MariaDB y MySQL
  • Instalación de servidores locales XAMP (Apache, MySQL, PHP)
  • Uso de servidores externos proporcionados por ISPs. Ventajas e inconvenientes
  • Migración a SQL desde DBF: diferencias entre ambos sistemas, haciendo hincapié en bloqueos, transacciones, índices, grandes tablas, campos BLOB, tipos de datos y uso de claves primarias
  • Conversión de tablas DBF a SQL: Consideraciones, herramientas de Xailer 4
  • Cuando usar SQLite y cuando usar MariaDB/MySql
  • Datasets en memoria: Ventajas e inconvenientes
  • TWebdatasource: ventajas e inconvenientes. Cuando usarlo
  • Uso de modelo vista-controlador
  • Base de datos en la nube: ventajas e inconvenientes
  • Bases de datos locales: sincronización y  propagación hacia servidores en la nube
  • Introducción a CRM Prestashop
  • Protocolo REST: introducción y uso básico
  • Datasource para Prestashop
  • Acceso directo al protocolo REST de Prestashop
  • Recepción de eventos de Prestashop con programación multi-hilo

A todos los asistentes se les entregará una licencia del nuevo datasource para Prestashop que se pondrá en venta inmediatamente después del evento a un precio de 150 euros.

Y eso es todo. Espero que el curso sea de vuestro interés. Si tenéis alguna sugerencia me encantará leerla. Os ruego utilicéis los comentarios para ello.

¡Hasta pronto!

 

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

Bitácora de Javier Gutiérrez Chamorro (Guti)

Opera no muestra imágenes de Tinypic

May 05, 2015 04:16 PM

Muchos ya os habréis dado cuenta que los magníficos navegadores web Opera, basados en el antiguo motor Presto, no visualizan bien las imágenes de TinyPic desde hace unas semanas, cosa que antes no daba ningún problema. El problema se aplica a Opera 12.x y anteriores, así como a Opera Mini, y está causado por un problema en la última actualización de TinyPic, que intencionadamente o no, esconde las imágenes a navegadores basados en Presto, de modo que al final, estas no se visualizan. La solución que he creado, se basa en user.js que ha creado Drozdman de Informatics Stuff, pero que por varios motivos no me gustaba por los siguientes motivos: 1) Dependía de jQuery, que lo hace más lento y pesado. 2) No comprobaba posibles condiciones de error. 3) Era demasiado lento al usar innecesariamente expresiones regulares de búsqueda y reemplazo. De ese modo he creado mi propia adaptación, [...]

» 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