Hacer una consulta MongoDB comprobando que un atributo array no esté vacío

En el ejemplo de obtener resultados aleatorios en una consulta de MongoDB y mongoose utilizaba un where un tanto especial. Este where es para comprobar que un atributo de tipo array que está contenido en el modelo tiene datos.

Primero definamos un ejemplo de modelo simple con el que vamos a trabajar. Lo detallo en formato JSON para no anclarnos a un entorno:

{
  name: "Nombre",
  code: "Código",
  screenshots: [],
  description: "Descripción"
}

Ahora con el modelo definido veamos como utilizarlo. Para ello debemos fijarnos en la sentencia where que vamos a utilizar.

{ screenshots: {$exists: true, $not: {$size: 0}} }

En este where, sobre screenshots realizamos 2 comprobaciones. La primera comprobación es utilizar "$exists: true" donde indicamos que la propiedad necesariamente debe existir. Recordemos en las bases de datos de documentos como MongoDB no necesariamente deben coincidir todos los modelos en una colección (tabla) de la base de datos.

Lo segundo que comprobamos es "$not" negamos que el tamaño del array sea 0 o lo que es lo mismo "$size: 0", de esta forma, le pedimos a MongoDB que nos de solo modelos que tengan la propiedad screenshots y que el tamaño de screenshots sea mayor de 0.

Ahora volvamos a ver el ejemplo que usamos con mongoose.

var where = { screenshots: {$exists: true, $not: {$size: 0}} };

mongooseGameModel.count().where(where).exec(function(err, gameCount) {
  var rand = Math.floor(Math.random() * gameCount);

  mongooseGameModel.findOne().where(where).skip(rand).populate('developer').exec(function(err, game) {
    res.locals.randomGame = game;
    next();
  });
});

En este ejemplo utilizando mongoose contra MongoDB obtenemos un juego aleatorio de un listado que cumpla la condición de que screenshots no esté vacío.

Obtener registros aleatorios con MongoDB

En una base de datos NoSQL como es MongoDB nos asaltan dudas constantemente. En este caso, ¿Cómo obtener un único registro aleatorio? A continuación os detallo como obtener este dato.

Para obtener un registro aleatorio debemos de realizar una consulta de un único elemento pero saltando los x primeros registros. De esta forma obtendremos el resultado. Nada mas fácil que verlo con un ejemplo. Para ello pondré 2 ejemplos uno directamente haciendo la consulta sobre MongoDB y otro utilizando ODM de Mongoose.

En MongoDB se haría de la siguiente forma.

db.games.find().limit(-1).skip( _rand() * db.games.count() )

Si tenemos una tabla games con un listado de juegos y queremos seleccionar un juego aleatorio, lo podríamos hacer así. Seleccionamos todos los juegos, establecemos el limit a -1 y saltamos un aleatorio.

Otro método sería utilizando mongoose, este ya solo como programación.

mongooseModel.count().exec(function(err, resultCount) {
  var rand = Math.floor(Math.random() *resultCount);
  mongooseModel.findOne().skip(rand).exec(function(err, result) {
    console.log(result);
  });
});

Como podemos ver, es un lo mismo que hacerlo directamente sobre MongoDB pero añadiendo algo de complejidad en el proceso por las llamadas asíncronas. En primer lugar deberemos obtener el número de resultados, una vez los tengamos, podemos calcular el aleatorio y obtener con findOne el resultado que queremos.

Ya para terminar un buen ejemplo de como utilizar este código, es utilizando where para filtrar los resultados, que deberemos aplicar tanto a la hora de obtener el contador como cuando buscamos el resultado, ya que si no lo aplicamos en conjunto, puede fallarnos todo el código.

var where = { screenshots: {$exists: true, $not: {$size: 0}} };

mongooseGameModel.count().where(where).exec(function(err, gameCount) {
  var rand = Math.floor(Math.random() * gameCount);

  mongooseGameModel.findOne().where(where).skip(rand).populate('developer').exec(function(err, game) {
    res.locals.randomGame = game;
    next();
  });
});

Montar un servidor para node.js usando nodeserver

Llevo tiempo trabajando con node.js y la verdad es que es el entorno donde mas cómodo me siento. El problema que tiene node.js es que cuando buscas como montar un servidor, no tienes ejemplos reales, solo como escuchar el puerto 80.

Para mis webs uso un servidor de desarrollo propio llamado nodeserver que podemos encontrar tanto en github como en npm. Este servidor tiene varias ventajas fundamentales:

  • Al ser un desarrollo propio, me permite fácilmente ir añadiendo nuevas funcionalidades según las necesito.
  • Tiene soporte para proxy reverso, por ejemplo tener las webs en un servidor interno sin acceso público y traer las conexiones.
  • Soporte de gestión de procesos para node.js, por lo que los .js de node.js que vamos a arrancar como servidores, podemos arrancarlos automáticamente desde el servidor, así como pararlos o reiniciarlos.
  • Tiene soporte para páginas estáticas en html, con un listado de mime types en desarrollo. Esto nos permite por ejemplo, crear un sistema cookieless para un CDN sin un backend, solo configurando el servidor.
  • Soporte para páginas en PHP. Aunque aún no soporta elementos como mod_rewrite, en un futuro lo tendrá, por lo que en el típico VPS para gestionar pequeños proyectos, podemos prescindir de un NGINX o Apache y utilizar nodeserver para gestionar nuestras webs.

Vamos a ver como se instala y configura este servidor. Para esto, primero debemos tener instalado en nuestro sistema node.js, cualquier versión o io.js. Este servidor funciona desde la versión 0.10 de node.js, aunque lo mas recomendable es utilizar las últimas versiones, 4.0 o superiores.

Con nodejs ya instaldo, debemos instalar por npm nodeserver

$ sudo npm install nodeserver -g

De momento nodeserver solo cuenta con script de instalación para centos pero se irá ampliando a otros sistemas, esto no quiere decir que no se pueda utilizar, no se instalará como demonio del sistema.

$ sudo nodeserver install centos

Una vez instalado el script, que no es obligatorio, deberemos configurar el servidor. Para ello crearemos un json de configuración en /etc/nodeserver/nodeserver.config.

{
 "nodeserver": {
  "admin": {
   "active": [true|false],
   "port": admin-port-number,
   "user": "user-for-admin",
   "password": "hash-password"
  }
 },
 "sites": [{
  "name": "website name",
  "type": "node|cgi",
  "bindings": [
   "example.com:80",
   "www.example.com:80",
   "otherbindings:8080",
  ],
  "port": "internal port number for the project, do not repeat it. Only for node"
  "script": "absolute script for server.js for node or doc_root for php (cgi)",
  "security": {
   "certs": {
    "key": "/absolutepath/keycert.key",
    "cert": "/absolutepath/cert.cert",
    "ca": ["/absolutepath/ca.cert"]
   },
   "bindings": [
    "securehostforhttps.com:443",
    "www.securehostforhttps.com:443"
   ]
  },
 }, {
  "name": "php website",
  "type": "cgi",
  "bindings": [
   "myphpsite.com:80"
  ],
  "script": "/var/www/phpsite"
 }, {
  "name": "standar nodejs site",
  "type": "node",
  "bindings": [
   "standarnodejs.com:80"
  ],
  "port": "10001",
  "script": "/var/www/nodejs1/server.js"
 }, {
  "name": "secure nodejs site",
  "type": "node",
  "bindings": [
   "securenodejs.com:80"
  ],
  "port": "10002",
  "security": {
   "certs": {
    "key": "/absolutepath/keycert.key",
    "cert": "/absolutepath/cert.cert",
    "ca": ["/absolutepath/ca.cert"]
   },
   "bindings": [
    "securenodejs.com:443"
   ]
  },
  "script": "/var/www/nodejs2/server.js"
 }]
}

El json de configuración se divide en 2 keys: una de administración y otra de sitios web. La parte de administración indicamos si queremos activarlo o no, el puerto de escucha via web, usuario y contraseña. La contraseña viene en formato hash y podemos generar una utilizando el comando:

$ nodeserver password micontraseña

El resultado deberemos utilizarlo en la configuración de password.

Por otro lado tenemos los sites. Los sites tienen como configuración un nombre, un tipo cgi para estáticosphp o node para webs en node.js. Un array de bindings indicará dominio y puerto que vamos a utilizar de escucha. En los bindings podemos incluir patrones regulares, por ejemplo, para cuando tenemos subdominios que queremos gestionar desde un mismo backend. Un ejemplo sería ".+\.midominio.com:80" para capturar todos los subdominios de midominio.com en el puerto 80. El atributo port solo se utilizar en node.js y es un puerto interno de escucha para servidores node.js. El atributo script utiliza para node.js la ruta del script de arranque del proyecto o el document_root para webs en php o estáticas.

Una vez todo configurado, ya podemos arrancar y probar nuestro servidor.

$ sudo nodeserver start

Os animo a probarlo y a comentar vuestras experiencias, mejoras, etc. Esto es un ejemplo, de como prepararlo en un entorno real, pero se puede configurar nodeserver como servidor de desarrollo, tener una escucha con el parametro start-loop en lugar de start.

¿Qué es un protocolo de ObjetiveC y para que se usan los protocolos en ObjetiveC?

Cuando programamos en ObjetiveC para iphone o ipad, utilizando funciones mas avanzadas de la interfaz gráfica nos encontramos con delegados, llamados también delegates. En estos casos, por ejemplo cuando tenemos un UIScrollView que captura el evento - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView que utilizamos para controlar cuando ese UIScrollView se ha parado. Para controlar esto lo hacemos mediante el uso de los delegados. Pero mejor verlo con un ejemplo que se vea mas claro.

@implementation IndalcasaViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.indalScroll.delegate = self;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
int page = scrollView.contentOffset.x / scrollView.frame.size.width;

NSLog(@"Hemos cambiado a la pagina %i", page);
}

@end

Tras este ejemplo vemos como funciona un delegado en una clase normal de ObjetiveC. Pero aún no entendemos lo que significa ser un delegado. Un delegado no es mas que un nombre de convención, que podemos llamar como queramos y que utilizaremos como disparador, donde el objeto que está almacenado implementa una serie de funcionalidades definidas en un protocolo.

Se que ahora ha quedado claro del todo :P, pero mejor verlo en un ejemplo.

@interface IndalcasaViewController : UIViewController
@end

Como vemos en el ejemplo anterior, a la hora de extender la clase UIViewController decimos que implementa el protocolo UIScrollViewDelegate. Para los mas veteranos desarrolladores, un protocolo no es mas que una interfaz. Para los mas novatos, una interfaz es como una clase donde se definen llamadas pero no se implementa código.

Para verlo todo mas sencillo, vamos a poner un último ejemplo. Lo que vamos a hacer es definir otro UIViewController al que instanciaremos en el viewDidLoad y que implementará un metodo vacío llamado "cambioPagina" que recibirá la página por parámetro.

IndalcasaViewController.h
@interface IndalcasaViewController : UIViewController

@property UIViewController delegate;
@property (weak, nonatomic) IBOutlet UIScrollView *indalScroll;

@end

IndalcasaViewController.m
@implementation IndalcasaViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.indalScroll.delegate = self;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
int page = scrollView.contentOffset.x / scrollView.frame.size.width;

NSLog(@"Hemos cambiado a la pagina %i", page);

[self.delegate cambioPagina:page];
}

@end

DelegadoViewController.h
@interface DelegadoViewController : UIViewController
@end

@protocol IndalcasaDelegate

-(void)cambioPagina:(int)pagina;

@end

DelegadoViewController.m
@implementation DelegadoViewController

- (void)cambioPagina:(int)pagina {
NSLog(@"Hemos cambiado a la pagina %i con un delegado", pagina);
}

@end

Como vemos en el ejemplo, lo que hacemos es que cuando capturamos el evento scrollViewDidEndDecelerating, que nos indica que se ha parado el scroll, llamamos a un delegado, previamente seteado que implementa el protocolo (intefaz) IndalcasaDelegate. Como sabemos que el delegado, al implementar el protocolo IndalcasaDelegate tiene un método cambioPagina que recibe un entero con la página, podemos llamar al método desde el delegado.

Comentar también que en muchos casos, nos encontraremos delegados de tipo id y no de un tipo concreto. Los tipos id vendrían a ser tipos de objetos genéricos, algo parecido al object de cualquier lenguaje.

Yo soy programador. Gobierno de España

yo-soy-programador

El Gobierno de España, ha querido hacer un video para promover que la gente estudie un módulo de FP o Formación Profesional. He estado viendo varios de los videos que han hecho a raíz de llegar a twitter el de "programador".

He de decir que mi indignación como profesional es enorme tras ver este video. Creo que cualquier persona que se pare a ver el código se dará cuenta que es una tomadura de pelo y de hecho se ha pedido en change.org la eliminación del video por parte del Gobierno de España.

Cada cual que juzgue el video y la impresión que da. Pero desde luego, no creo que ningún joven quiera estudiar un módulo de FP por este tipo de videos.

Por que usar un framework para frontend web como bootstrap

CSS3Desde hace unos años han ido apareciendo de forma generalizada y bien desarrollada lo que todo el mundo solía hacer en sus desarrollos web y son pequeños frameworks para el frontend. Quien haya maquetado de forma continuada, con el tiempo habrá ido reutilizando técnicas entre proyectos. Por ejemplo, una de ellas es el uso de estilos de reseteo como el ya clásico reset.css o la creación y reutilización de componentes básicos como botones, migas de pan, etc.

Hace unos 3 o 4 años empezó a surgir una tendencia de creación de sistemas de grid, organizando nuestra web en columnas. El uso del grid nos facilita el trabajo, siempre y cuando no vayamos buscando el pixelperfect, ya que nos permite adaptar el ancho de las columnas, dar estilos generales y modificar la apariencia de nuestra web con pocas lineas de css sobre el grid ya creado.

Hace un par de años que empezaron a nacer los frameworks completos para frontend. Estos frameworks no son solo una base de estilos, sino también componentes de uso general que usamos a diario. A veces y según el desconocimiento de la gente, piensa como frameworks frontend cosas que no lo son. Para aclararlo creo que lo mas sencillo es quedarnos en jQuery. jQuery tiene varias ramas, la librería, que no es mas que una librería de manipulación de DOM, jQueryUI que es un framework de componentes frontend y jQuery Mobile que viene a ser no un framework frontend sino ya un fullstack de frontend. La diferencia entre ellos es evidente, ya que jQueryUI no nos da una base de estilos, ni un sistema del que poder extender nuestra página, sino unos componentes como botones, tabs, sliders, etc. con los que podemos crear componentes mucho mas ricos que los nativos de HTML. Por otro lado tenemos el fullstack de jQuery Mobile que no solo nos da un theme con estilos básicos sobre los que desarrollar, sino todo el sistema de navegación, control de menús, formatos, datos, etc.

¿Qué es un framework frontend para web? No es mas que un conjunto de librerías y estilos básicos que nos permiten construir interfaces frontend de forma rápida y personalizable. Comparandolo con jQueryUI, sería como añadir unos estilos de scaffolding para la construcción de la estructura de la página y un grid de maquetación. Si por otro lado lo comparamos con jQuery Mobile, sería lo mismo pero eliminando la parte en la que jQuery Mobile nos construye todo el sistema de navegación entre páginas (es un ejemplo), bajandolo por así decir de fullstack a framework.

bootstrap-logo

Los sistemas de scaffolding nos ayudan a crear prototipos de webs de forma rápida. Podemos generar de forma rápida, paginas, menús, secciones, formularios, todo con estilos genéricos. Una vez desarrollado nuestro scaffolding básico, podemos dedicar esfuerzos a personalizar el estilo de la página. Hay que tener en cuenta que donde se diferencia de la forma clásica que teniamos de trabajar si éramos ordenados es que no nos tenemos que preocupar de la evolución de nuestro framework de base de estilos y que ademas podemos reaprovechar los plugins que desarrolle la comunidad.

Ahora un breve listado con los 4 frameworks mas útiles, aunque hay muchos mas:

Espero que os pueda servir como punto de entrada para investigar y aplicar posteriormente en vuestros proyectos.

Animaciones en CSS3: transiciones en CSS3

Hace ya tiempo que no escribo y eso no puede ser. Así que hoy os quiero hablar de animaciones, en concreto me voy a centrar en transiciones con CSS3 o como se diría en ingles CSS3 transitions.

Lo primero es sentar unas bases de lo que es una transición. Básicamente cuando hablamos de transitions en CSS3, lo que hacemos referencia es una pequeña animación de css que se ejecutará como mezcla de 2 o mas clases. En concreto una transición de CSS3, lo que indica es que propiedades cambiarán con una animación. Pero es mas fácil con un ejemplo:

.clase-indalcasa {
  -webkit-transition: all 1s ease-in-out 0.2s;
  -moz-transition: all 1s ease-in-out 0.2s;
  -ms-transition: all 1s ease-in-out 0.2s;
  -o-transition: all 1s ease-in-out 0.2s;
  transition: all 1s ease-in-out 0.2s;
}

Si nos damos cuenta del código anterior, que se repite una y otra vez para dar salida a todos los metas de navegador experimental, veremos que la sintaxis básica es:

transition: [propiedades] [duración] [functión de tiempo] [tiempo de espera, retardo]

Como podemos ver, ahora entendemos mejor que hace referencia en la clase, tomando con concepto que todos los elementos son opcionales. A continuación una explicación más detallada:

  • propiedades (properties): son las propiedades que van a ser afectadas por la transición. Es un listado separado por comas ",". Por ejemplo, si queremos aplicar a todas las propiedades de un elemento usariamos "all", mientras que si queremos afectar por ejemplo a la altura y anchura usariamos "width, height" y así ir añadiendo propiedades a las que afectar. Al final dejare una tabla con una relación de los propiedades a afectar.
  • duración (duration): la duración se indica o bien en segundos o en milisegundos. Para ello después del número de cantidad, indicamos 0.5s o 500ms para indicar medio segundo. Si tenemos varias propiedades separadas por comas, podemos indicar los tiempos de manera similar para cada una de las propiedades.
  • función de tiempo (timing function): está es quizas la configuración mas interesante, ya que nos permite indicar que función de tiempo vamos a utilizar en la transición. Por defecto hay definidas varias definidas o utilizar un cubic-bezier para definir nosotros una personalizada.
    • ease: mantiene una aceleración y frenada al principio y al final de la animación.
    • ease-in: tiene una aceleración y el final es constante hasta que termina.
    • ease-out: no tiene aceleración, sino que alcanza su tope desde el principio pero va frenando poco a poco.
    • ease-in-out: similar a ease pero con la aceleración y frenada mas prolongadas.
    • linear: es como su nombre indica, linear y constante en el tiempo
    • cubic-bezier: nos permite definir una función de curva de bezier personalizada. Esto da para todo un tema aparte y para empezar a entender que es: Curva de Bezier en Wikipedia
  • tiempo de espera, retardo (delay): al igual que la duración, se indica en segundos o milisegundos.

Ahora algunos ejemplos:

pasame
por encima

El código de este ejemplo sería:

.indalcasa-transition-hover {
  width: 100px;
  height: 100px;
  background: rgba(255, 0, 0, 0.3);
  -webkit-transition: all 2s ease-in-out;
  margin: 20px auto;
  line-height: 50px;
  text-align: center;			
}

.indalcasa-transition-hover:hover {
  width: 500px;
  height: 500px;
  background: rgba(0, 255, 0, 0.3);
  font-size: 50px;
  line-height: 250px;
  border-radius: 250px
}
<div class="indalcasa-transition-hover">pasame<br/>por encima</div>

Por último y para terminar esta breve explicación, una tabla de propiedades que se pueden o no cambiar con las transiciones.

Nombre de la propiedad Tipo de valor
background-color color: nombre, hexadecimal, rgb, rgba
background-image gradientes de css
background-position porcentaje, tamaño: pixeles, em, etc
border-bottom-color color: nombre, hexadecimal, rgb, rgba
border-bottom-width tamaño: pixeles, em, etc
border-color color: nombre, hexadecimal, rgb, rgba
border-left-color color: nombre, hexadecimal, rgb, rgba
border-left-width tamaño: pixeles, em, etc
border-right-color color: nombre, hexadecimal, rgb, rgba
border-right-width tamaño: pixeles, em, etc
border-spacing tamaño: pixeles, em, etc
border-top-color color: nombre, hexadecimal, rgb, rgba
border-top-width tamaño: pixeles, em, etc
border-width tamaño: pixeles, em, etc
bottom tamaño: pixeles, em, etc, porcentaje
color color: nombre, hexadecimal, rgb, rgba
crop rectangulo
font-size tamaño: pixeles, em, etc, porcentaje
font-weight número, nombre
grid-* varios
height tamaño: pixeles, em, etc, porcentaje
left tamaño: pixeles, em, etc, porcentaje
letter-spacing tamaño: pixeles, em, etc
line-height número, tamaño: pixeles, em, etc, porcentaje
margin-bottom tamaño: pixeles, em, etc
margin-left tamaño: pixeles, em, etc
margin-right tamaño: pixeles, em, etc
margin-top tamaño: pixeles, em, etc
max-height tamaño: pixeles, em, etc, porcentaje
max-width tamaño: pixeles, em, etc, porcentaje
min-height tamaño: pixeles, em, etc, porcentaje
min-width tamaño: pixeles, em, etc, porcentaje
opacity número de opacidad, de 0.0 a X
outline-color color: nombre, hexadecimal, rgb, rgba
outline-offset número
outline-width tamaño: pixeles, em, etc
padding-bottom tamaño: pixeles, em, etc
padding-left tamaño: pixeles, em, etc
padding-right tamaño: pixeles, em, etc
padding-top tamaño: pixeles, em, etc
right tamaño: pixeles, em, etc, porcentaje
text-indent tamaño: pixeles, em, etc, porcentaje
text-shadow valores
top tamaño: pixeles, em, etc, porcentaje
vertical-align nombres, tamaño: pixeles, em, etc, porcentaje
visibility valores de css
width tamaño: pixeles, em, etc, porcentaje
word-spacing tamaño: pixeles, em, etc, porcentaje
z-index posición de entero
zoom número

Publicada la versión 0.8.53 de w2s cloud ide

w2sOs traigo buenas nuevas y es que hace poco se ha liberado la versión 0.8.53 de nuestro proyecto w2s cloud ide. En esta versión hemos trabajado para solucionar problemas, automatizar tareas, aunque aún no es suficiente y ofrecer algunas mejoras que suponen un importante avance en el desarrollo  de la herramienta. Cabe destacar en esta versión de w2s los avances que se han realizado sobre la configuración y compilación de proyectos de .Net, así como poder dar soporte a python, con django a la cabeza. También es importante el cambio de la forma de visualizar los errores, de una linea roja completa, para indicar el error, a un ligero subrayado al lugar del error, así como la posibilidad de cambiar el template de colores no solo del código, sino del ide completo, que ahora se puede oscurecer o clarecer y sigue todo una consonancia. Os dejo la lista completa de con todos los cambios: Correcciones * Ahora el visor de imagenes siempre muestra las dimensiones de la imagen y no 0x0 cuando la imagen no estaba cacheada. Mejoras

  • Ahora se pueden crear nuevos proyectos con templates
  • Se añade un validador de css, que nos corrige y hace sugerencias acerca de nuestro código css
  • Se actualiza el editor con multiples mejoras, entre algunas, cabe destacar que ahora los errores no resaltan la linea completa, sino que muestra un subrayado rojo para los errores y amarillo para las advertencias.
  • Añadido soporte de django al ide en general
  • Al crear un nuevo template de proyecto, ya disponemos de uno para django
  • Se añaden al menu contextual una nueva sección django con las subopciones: runserver, stopserver, syncdb y collectstatics
  • Se recoloca la opción de compilar un proyecto de c# para que este dentro de csharp > compile
  • Se añade soporte de jpeg al visor de imagenes
  • En c#, las referencias a otros proyectos ahora son copiadas directamente a nuestro proyecto cuando compilamos
  • Se añade soporte multicultural (multiidioma) a los proyectos de c#, permitiendo así crear librerias localizadas.
  • Se añade un generador de archivos de recursos para .Net, que compilan un xml de resx y lo convierten en recursos embebidos para los archivos neutrales y librerias compiladas satelite para las externas.
  • Añadido autocompletado de código en c# y python. Ahora el código se autocompleta en c#, python, javascript y html5.
  • Añadidos puntos de interrupción a c# aunque aún no se puede depurar.
  • Añadidos templates para el ide, al oscurecer el editor de codigo, nuestro ide (menu, navegación, consola, etc) también cambia de color. Planificadas

  • Permitir la opción de manterner la sesión abierta permanentemente.

  • Añadir un contralador al ide para mostrar un login si nuestra sesión ha expirado.

  • Permitir borrar proyectos de forma segura.
  • Depurar proyectos de c#
  • Permitir mover carpetas y ficheros entre si
  • Permitir renombrar ficheros y directorios
  • Permitir autoocultar tanto la consola como el menú de navegación
  • Integración con GIT.
  • Publicación por FTP
  • Compartir proyectos entre usuarios
  • Añadir tareas a los proyectos Recordad que estamos abiertos a sugerencias y si las tenéis, podeis dejarnoslas en los comentarios y las estudiaremos para implementarlas.

Modas y versiones o como pasar no actualizar a sacar verisones como churros

enter-key-appleHacia tiempo que no escribia un post incendiario y creo que hoy es un buen día para ello. Últimamente estoy viendo una moda en las versiones de las aplicaciones que yo clasificaría en la de "estamos todos locos" o como diría vayavoragine "vamos a morir todos" y es que últimamente aparecen versiones como churros. Pero voy a hacer un poco de abuelo cebolleta y os voy a contar como ha evolucionado la moda con el paso de los últimos 15 o 20 años en la industria del software para que os hagais un poco a la idea de este brutal cambio.

Cuando Adan y Eva andaban por el paraiso y cogiendo la manzana prohibida acabaron por NextStep, alla por los años 80 y 90, las versiones del software era como un buen artículo de la Wikipedia expondría y es que son numeradas con {version}.{subversion}.{revision}.{commit,fecha,codigoquequeramos}.

La idea es que nuestra versión solo se actualiza cuando sufre cambios importantes y que afectan tanto que podría significar que se trata de una version completamente nueva, aquí podemos poner como ejemplos: una reescritura del código, cambio de lenguajes o librerías, o un cojunto de tantos cambios de golpe que podamos considerar que es un nuevo programa y de ahi su salto de version. Muchas veces tambien se asocia a un cambio de diseño, sobre todo en versiones web.

La subversión (con confundir con SVN), hace referencia a cambios, que aunque también grandes, no varian brutalmente el diseño de la web, por ejemplo añadir una o varias nuevas funcionalides. Imaginemos que tenemos wordpress y de repente hay una nueva funcionalidad que añade un nuevo módulo de galeria de fotos, esto sería una subversión, pero si por el contrario, la funcionalidad fuera permitir (de forma nativa y sin plugins) un sistema de multidioma para los artículos que conlleva la reescritura de medio core de wordpress, entonces, se podría considerar una versión nueva.

De revisión hasta el final, es algo opcional y solo informativo, normalmente la revision suelen ser las releases oficiales, aunque no se hayan hecho públicas, por ejemplo, cada vez que compilamos para sacar una versión en producción o en entornos de desarrollo, podríamos considerarlo como revisión y puede tener pocos o ningún cambio. Igual pasa con los siguientes parámetros, que suelen hacer referencia, si es que se usan, a número de commit en el control de código, la fecha del día, un número aleatorio o algún código que haga referencia a la fecha y número de veces que hemos compilado.

Hasta aquí la explicación, ahora vamos con la historia. Hace años se respetaba esta teoría en mayor o menor medida, cada versión nueva era un software nuevo, cientos de funcionalidades nuevas, mejoras importantes, rediseños completos, algo grande y por tanto, las versiones de los software eran pequeñas y una buena muestra es el propio Microsoft Windows que en 30 años y 14 versiones oficiales, realmente la version de Windows 8 es la 6.2.9200. A veces se daba el caso en que algún software, para competir un poco, se saltaba alguna versión para dar mas apariencia de software maduro, como por ejemplo y sin salir del ejemplo de Microsoft, nos encontramos con SQL Server, que salto de la versión 1.1 a la 4.21 haciendo un chasquido de dedos... y ¿Dónde quedaban la versión 2 y 3? Pues cuando le preguntaron esto, como si de guionistas de Lost se trataran, con otro chasquido de dedos, estabamos ante la versión 6 ¿Y la 5? y lo que sería la llegada a la normalidad en las versiones de SQL Server.

Algunos pensaran, que Microsoft, que malo es, vade retro, pero en realidad era una práctica común cuando un software se quedaba atras y es que por aquella época, Oracle con 15 años mas de desarrollo a sus espaldas, contaba con su versión 7 de base de datos, mientras que SQL Server solo la 1.1, por lo que se vieron obligados a saltar hasta una versión 6, indicando que eran inferiores a Oracle pero no estaban tan lejos. Caso así encontramos a Firefox, que el pobre, tuvo que optar por la moda del rapid release para poder competir con Chrome que saca versiones como churros.

¿Qué es eso del rapid release? Es cambiar la forma de obtener versiones, en lugar de tener varios branchs de desarrollo en versiones diferentes, las  versiones nacen y mueren rápidamente para centrar todo el esfuerzo en una funcionalidad, sacarla con una versión y pasar a la siguiente. Esto tiene cierta lógica en desarrollos en producción y que no necesite de excesivo testeo, por ejemplo, implementar en el caso de Firefox, ciertas funcionalidades experimentales de HTML5 que pueden fallar pero que de entrada funcionan mas o menos.

De todos es conocido que Google Chrome, utiliza rapid release, que se puede ver como en cuestión de 3 años han sacado 25 versiones y para no quedar descolgado, Firefox se ha subido al carro del rapid release. Ya con esto nos podemos echar en cierta medida las manos a la cabeza, ya que cada mes o dos meses tenemos una nueva versión, pero el colmo ha sido Linux. Hace como un año, leia la noticia que la versión del Kernel de Linux iba a ser actualizada hasta la versión 3, no por los cambios que conllevaba, sino por pasar de la version 2.6 en la que llevaba anclada prácticamente 6 años. Cual es mi sorpresa que ayer leia que se había publicado la versión 3.8 del Kernel de Linux y es que habían publicado 8 subversiones.

Cada día hay mas proyecto/empresas que adoptan el rapid release y aunque cada uno pone las versiones que les da la gana, digo yo, si seguimos sacando versiones como churros, apareceran doodle por versión en Chrome, tal como desactivar el modo incognito en la version 69, o haciendo referencia al hombre el la luna. Lo curioso del caso es que, hace unos años, habia otra moda, la moda del "beta" y como recordar a tantos proyectos marcados como "beta", sin ir mas lejos GMail o el "peta" de meneame.

¿Pasamos 5 años en modo beta y luego adoptamos un rapid release y sacamos 14 versiones en 2 años? Así que publico esto en mi WordPress 33, con mi OSX 21.37 y luego veo el post con mi iphone 11. Y como colofón, mencionar como Apple con la tontería, hace tiempo que su iPad3 es solamente iPad y el resto de versiones, son solo iPad, sin versión. Y es que el mundo se ha vuelto loco.