Weblogs Código

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

Leonardo Torres Quevedo

May 27, 2016 09:48 AM

Resulta sorprendente que Leonardo Torres Quevedo resulte un completo desconocido para muchos. Debo admitir, que hasta hace unos meses, también lo era para mi, pese a ejercer una actividad intelectual muy próxima a la tecnología actual. Por contra, si que conoceréis a Alan Turing, a Charles Babbage, a Nikola Tesla o a Ada Lovelace. No [...]

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

Poesía Binaria

Vicio con el teclado, comandos, manías y coletillas que nos salen sin pensar

May 27, 2016 08:30 AM

photo-1445605081472-9788fb3bc02f

Como apasionado de la consola, soy una de esas personas que tarda menos en escribir un comando y pulsar enter que en cargar una interfaz gráfica, click, click, control, clic, arrastrar, soltar, click… y el tiempo es muy valioso.
Eso sí, cuando empiezas a pegarle al teclado y escribir comandos en la terminal, parece que todo va más lento, una simple coma, o un espacio es capaz de fastidiarlo todo, pero cuando llevas mucho tiempo, lo tienes todo tan automatizado que te sale el alma.

Anécdota (o batallita)

En la Universidad, tenía una asignatura de laboratorio, y tras cada sesión, teníamos que copiar una serie de archivos a una carpeta de red, por ese motivo, el profesor avisaba 5 minutos antes de terminar. El sistema era Microsoft Windows, y todo el mundo optaba por abrir las carpetas gráficamente y arrastrar; eran varias carpetas y no todos los archivos de todas las carpetas, por lo que muchos entraban, seleccionaban, copiaban, salían, entraban en otra carpeta…
Yo, ejecutaba varios comandos desde consola, que terminé metiendo en un script, y así me iba antes.

Dejando a un lado estas historias, cada usuario, va creando una base mental de comandos que, a menudo, van acompañados de argumentos. El objetivo es no pensar demasiado y dejar que tus dedos tecleen.

Por ello, no pretendo hacer un tutorial de uso de comandos (porque no cabría todo aquí), pero sí una visión personal de lo que más suelo teclear y cómo lo hago y, es curioso ver que los argumentos siempre van en el mismo orden. Del mismo modo, me gustaría que dejarais algún comentario con algún comando curioso que os salga del alma, o de otras alternativas que soléis utilizar.

¿Por qué no uso alias

Porque no estoy siempre en mi ordenador, a menudo suelo entrar en varios servidores, y no quiero acostumbrarme a utilizar los comandos con los alias de mi equipo, que soy muy despistado y me confundo cuando esté en otra máquina (me ha pasado). También porque hay muchas otras veces que no quiero o puedo utilizar estos argumentos, no son generales, sólo comunes y no quiero tener problemas cuando vaya a usarlos para otra cosa.

ls

Yo creo que ls, junto con cd es de lo más usado del mundo, ya que es una de las tareas más básicas. Pero casi siempre que lo ejecuto lo hago con:

ls -latr

Porque me gusta listar todos los archivos, ordenarlos por tiempo dejando en última posición al más nuevo.
También suelo hacer

$ ls -latrh

Cuando quiero que los tamaños de archivos estén en formato humano o,

$ ls -laSr

Cuando quiero ordenarlos por tamaño de archivo.

ps

En el último post ya hablé de ps, y casi siempre lo que suelo hacer es:

$ ps ax

Para que muestre todos los procesos, luego ya los filtraré con grep…

rsync

Otro viejo conocido, aunque casi casi siempre que lo uso, lo hago con los siguientes argumentos:

$ rsync -avhP [origen] [destino]

De esta forma copio archivos de forma recursiva, incluyo enlaces, mantengo permisos, marcas de tiempo y algunas cosas más, muestro lo que se está copiando, los tamaños son en formato humano.

rm

Esto es muy peligroso, y alguna vez, este vicio me ha jugado una mala pasada, y es que casi siempre que pongo este comando suelo poner:

$ rm -rf [archivos, directorios…]

Intenté acostumbrarme a poner una i en medio, algo así como:

$ rm -rif [archivos, directorios…]

al menos, por precaución, aunque me acabé hartando y no lo hice.

du

Esta herramienta nos muestra el uso en disco de una carpeta, por ejemplo. Casi siempre lo suelo utilizar para saber el tamaño de un directorio y de todo lo que hay dentro, es decir, sólo quiero un número y no quiero desgloses. Además, me gusta el tamaño en formato humano, que no estoy aquí para hacer cuentas…

$ du -sh [carpeta]

df

Del mismo modo que otros comandos, y sobre todo con éste, a nadie nos apetece hacer cuentas para ver los tamaños de un modo inteligible:

$ df -h

pwgen

Un simple programa para generar contraseñas, temporales o no, para muchos sistemas. Si lo ejecutas tal cual te da buenas contraseñas, pero suelo utilizarlo de la siguiente forma:

$ pwgen -sy 12

Así me genera una colección de contraseñas de 12 caracteres, difíciles de memorizar y además incluyendo símbolos. Perfecto para contraseñas de MySQL, OTP, y cosas así, aunque alguna que otra sí que tengo aprendida de memoria.

tar

Este comando depende, mis variables más comunes en este caso son: ¿comprimir? ¿descomprimir? ¿gz?¿bz2?

Por ello, para cada combinación tengo un comando (y todos muy parecidos):

Comprimir, bzip2

$ tar cvjf [archivo de destino] [directorios, archivos… a comprimir]

Descomprimir, bzip2

$ tar xvjf [archivo de destino] [directorios, archivos… a comprimir]

Comprimir, gzip

$ tar cvzf [archivo de destino] [directorios, archivos… a comprimir]

Descomprimir, gzip

$ tar xvzf [archivo de destino] [directorios, archivos… a comprimir]

Como veis, todo queda muy sistemático, la v y la f no se mueven, la primera letra puede ser c o x y la penúltima j o z.

Opcionalmente, suelo poner a veces una p delante de la f para conservar los permisos de los archivos, sólo a veces.

grep

Su uso es sencillo cuando queremos filtrar la salida de un comando anterior (por ejemplo lsof):

lsof | grep /dev/sdc2

Pero cuando queremos buscar un patrón dentro de un archivo también nos vale este comando, aunque muchas veces, aunque grep nos dice que ha encontrado el patrón, seguimos sin la más remota idea de dónde está, para ello suelo hacer:

$ grep -nC3 ‘patron’ [archivo]

De esta forma, grep me devolverá 3 filas anteriores, 3 filas posteriores y el número de línea. Opcionalmente, si quiero que grep no sea sensible a mayúsculas minúsculas, pongo una i detrás de la n… -niC:

$ grep -niC3 ‘patron’ [archivo]

egrep

Soy muy dado a perder las cosas y luego no saber dónde están, por eso, suelo usar este comando. Con él busco un contenido dentro de una serie de archivos y directorios, casi siempre suelo hacerlo así:

$ egrep -Rn ‘texto_que_busco’ *

Así, busco en todos los archivos y carpetas de forma recursiva partiendo del directorio actual, además, cuando lo encuentro, muestro también el número de línea donde se ha encontrado lo que busco.
¿Sólo busco archivos con una extensión determinada? (antes del include van dos signos -)

$ egrep -Rn ‘texto_que_busco’ –include=’*.cpp’ –include=’*.hpp’ *

También podemos poner una i delante de la n, y parece que dice Rin… con el mismo propósito de antes, no hacer la búsqueda sensible a mayúsculas y minúsculas.

netstat

Un programa que nos sirve para mostrar conexiones de red. Casi siempre, lo que quiero hacer es mostrar las conexiones TCP (t), mostrarlas todas, incluso las que están sólo escuchando (a), no resolver los hosts (n), con esto el comando se ejecuta mucho más rápido, dando sólo las direcciones IP, y mostrar los procesos que originan dicha conexión (p), para este último argumento, ejecutar el comando como root tiene más gracia.

$ netstat -tanp

arp

Como el anterior, si resolvemos los nombres de los hosts, tardaremos mucho, y muchas veces no los necesitamos, para ello:

$ arp -n

firefox

¡Hombre! Firefox también se ejecuta desde consola, si quieres, para ello suelo hacer:

$ firefox -ProfileManager –no-remote

Así puedo cargar varios perfiles diferentes de Firefox al mismo tiempo en el sistema.

Tu turno

¿Tienes algún comando curioso que casi siempre ejecutes con los mismos argumentos? ¿Alguna manía con la consola? ¿Reglas mnemotécnicas nemotécnica para acordarte de los parámetros de algún programa? ¡Deja tu comentario!

Foto principal: Web Donut

The post Vicio con el teclado, comandos, manías y coletillas que nos salen sin pensar appeared first on Poesía Binaria.

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

Navegapolis

Las ventajas del extremismo

May 26, 2016 07:29 PM

He descubierto este vídeo de John Cleese, y no he podido evitar subtitularlo y compartirlo. :)

 

 

Pero ahora hablando en serio, hemos oído mucho acerca del extremismo últimamente, sobre cómo hay un ambiente más áspero y desagradable en todo el mundo, más abusos y actitudes macarras, menor amabilidad, tolerancia y respeto hacia los adversarios...

Vale, bien, pero lo que nunca oímos decir sobre el extremismo ¡son sus ventajas!

Bueno. La mayor ventaja del extremismo es que te hace sentir BIEN porque te proporciona enemigos. Permíteme que me explice. Lo mejor sobre los enemigos es que puedes fingir que toda la maldad del mundo entero reside en tus enemigos, y que toda la bondad del mundo entero reside en TI. Suena bien, ¿no?

Así que si por alguna razón tienes mucha ira y resentimiento en ti, y por tanto disfrutas maltratando a otra gente, ¡puedes fingir que sólo lo haces porque estos enemigos tuyos son personas terribles!

Y que si no fuera por ellos, de hecho serías amable, cortés y racional todo el tiempo. Si quieres SENTIRTE BIEN, conviértete en un radical.
Ok, ahora tienes que elegir. Si te unes a la extrema izquierda, te darán su lista de enemigos autorizados: casi cualquie ripo de autoridad (especialmente la policía), americanos, jueces, empresas multinacionales, escuelas privadas, peleteros, directores de periódicos, cazadores de zorros, generales, traidores de clase y, por supuesto, moderados.
Oh, y si prefieres ser un radical de la extrema derecha no hay problema, no hay problema, sigues teniendo una encantadora lista de enemigos, sólo que son otros diferentes: grupos minoritarios escandalosos, Rusia, "frikis", manifestantes, gorrones, clérigos entrometidos, pacifistas, la BBC, huelguistas, trabajadores sociales, comunistas y, por supuesto, moderados.

Ahora que tienes una de estas súper listas de enemigos, puedes ser todo lo desagradable que quieras y pese a todo sentir que tu comportamiento está moralmente justificado. Puedes ir por ahí maltratando a la gente, diciéndoles que podrías zampártelos para desayunar, y al mismo tiempo creerte un campeón de la Verdad. Un luchador en pos del bien mayor. Y no el triste esquizoide paranoico que en realidad eres.

 

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

El blog de Adrián Arroyo

Tutorial de Hugo en español, generador de sitios estáticos

May 26, 2016 10:22 AM

Los generadores de sitios estáticos son aplicaciones que dados unos ficheros generan un sitio web completo, listo para ser desplegado en Apache o Nginx. El generador es llamado bajo demanda del administrador por lo que, al contrario que en un CMS completo, este programa solo genera las páginas una sola vez, reduciendo considerablemente la carga de trabajo y el precio y aumentando en velocidad y rendimiento.

Página web de Hugo

Los generadores más populares son:

Nombre Lenguajde Plantillas Licencia Sitio web
Jekyll Ruby Liquid MIT http://jekyll.rb.com
Hexo JavaScript EJS y Swig MIT http://hexo.io
Hugo Go Go Template, Acer y Amber Apache http://gohugo.io
Pelican Python Jinja2 GPL http://blog.getpelican.com/

Además es también bastante conocido Octopress pero Octopress no es más que Jekyll con una colección de utilidades extra, el núcleo del programa sigue siendo Jekyll.

¿Por qué voy a elegir Hugo? Yo empecé con Jekyll y me gustó. Sin embargo Liquid no me acabó de convencer nunca y miré otras alternativas. Hexo me pareció excelente si lo que quieres hacer es un blog, funciona muy bien y es más rápido que Jekyll pero Jekyll tenía la ventaja de que se podía usar no solo en blogs, sino en cualquier web en general. Entonces oí hablar de Hugo. Hugo es el más rápido y el más flexible. No está enfocado solo en blogs, soporta todo lo que le eches. Sin embargo me parece que Hugo no es el más sencillo de configurar, así que aquí va el tutorial.

Instalando Hugo

Hugo está hecho en Go, quiere decir que está compilado y por tanto hay una versión diferente para cada sistema operativo. Descarga la versión de tu sistema operativo desde aquí. Si usas GNU/Linux es posible que tu distro haya empaquetado ya Hugo. Búscalo.

Una vez lo tengamos instalado comprobamos que todo esté en orden:

hugo version

Por defecto Hugo no trae ningún tema. Si quieres instalarte uno y no crear uno de cero puedes clonarlos desde Git. Si quieres probar los temas antes de instalarlos no dejes de mirar Hugo Themes

git clone --recursive https://github.com/spf13/hugoThemes ~/themes

Si queremos tener coloreado de sintaxis podemos usar Pygments. Si tienes PIP instalado es fácil.

sudo pip install Pygments

Además si quieres activar el autocompletado de Bash solo tienes que hacer

sudo hugo gen autocomplete
. /etc/bash_completion

Y con esto ya tenemos Hugo instalado correctamente. Ejecuta:

hugo new site MiSitioSupercalifragilisticoespialidoso

Hugo Themes

Organización en Hugo

En Hugo tenemos que tener muy en cuenta la organización de los ficheros. En primer lugar van los themes. Como puedes comprobar la carpeta themes generada esta vacía. Para ir probando los distintos temas puedes hacer un sencillo enlace simbólico entre la carpeta con los temas descargada y esta.

rmdir themes
ln -s ../themes .

Veamos el resto de carpetas:

  • archetypes. Arquetipos. Son plantillas para cuando añadimos un nuevo elemento. Por ejemplo, podemos tener un arquetipo de post sobre un vídeo de YouTube. Es posible crear un arquetipo que contenga configuración ya específica (categorías, reproductor insertado, etc) y que cuando escribamos ya lo tengamos medio hecho. A la hora de generar el sitio los arquetipos de origen no son tenidos en cuenta.
  • config.toml (o config.json o config.yaml). Este archivo contiene la configuración del sitio.
  • content. Aquí va el contenido central de la web. Dentro de content debes crear tantas carpetas como secciones tengas (aunque se puede sobreescribir vía configuración, es práctica recomendada). Cada sección tiene asignado un layout distinto. Dentro de la carpeta de cada sección la organización es libre, los archivos suelen ser de Markdown, pero HTML puro también vale.
  • layouts. ¿Cómo se organiza el contenido? Los layouts son la respuesta. Por cada sección hay que crear mínimo dos layouts, uno para mostrar un contenido solamente y otro para múltiples contenidos del mismo tipo (listas).
  • data. Aquí puedes almacenar archivos en JSON, YAML o TOML a los que puedes acceder desde Hugo. Estos archivos pueden contener cualquier tipo de información, piensa en ellos como en una especie de base de datos.
  • static. El contenido estático, imágenes, JavaScript, CSS, que no deba ser procesado por Hugo debes ponerlo aquí.

Configuración

Dentro del fichero config.toml hay que editar unos cuantos valores.

baseurl = "mi-sitio.com" # La dirección base del sitio
languageCode = "es-es" # El idioma de la web
title = "" # El título de la web
theme = "bleak" # El tema que se va a aplicar al contenido
googleAnalytics = "" # Código de seguimiento de Google Analytics
disqusShortname = ""

[Params] # A estos parámetros se puede acceder de forma directa con .Site.Params.NOMBRE
Author = "Adrián Arroyo"

También es configurable Blackfriday el motor de Markdown de Hugo, aunque las opciones por defecto son más que suficientes.

Creando contenido

Crea un archivo dentro de content. Puede estar dentro de una sección si así lo prefieres. En Hugo al igual que en Jekyll cada contenido tiene un front matter, es decir, los metadatos se añaden al principio en un formato que no se va a renderizar. Hugo soporta TOML, YAML y JSON. Si usamos TOML, los delimitadores del front matter serán +++, si usamos YAML --- y si usamos JSON tenemos que poner un objeto con las llaves, {}

+++
title = "El título de la entrada"
description = "Una pequeña descripción"
tags = ["hola","otra","etiqueta"]
date = "2016-05-23"
categories = ["Sobre el blog"]
draft = true
+++

Aquí va el contenido en Markdown o HTML que va a ser renderizado.

Podemos crear variables nuevas a las que podremos acceder desde .Params. Otras opciones predefinidas son type (que sobreescriben el valor de la sección), aliases (que permite hacer redirecciones), weight (la prioridad cuando el contenido sea ordenado) y slug (permite ajustar la URL del contenido).

Modificando el tema

Puedes modificar el tema usando la carpeta layouts. En el fondo un tema es una colección de layouts y recursos estáticos que son combinados con el tuyo. Si ya usas un tema y solo quieres realizar pequeñas modificaciones puedes editar el tema directamente. Si quieres añadir nuevas secciones o crear un tema de 0 entra a la carpeta layouts.

Hay varias subcarpetas dentro de layouts importantes:

  • _default. Es la que se usa cuando no hay otro disponible. Normalmente los temas sobreescriben esta carpeta. Si sobreescribes esta carpeta perderás el tema.
  • index.html. La página de entrada a la web
  • partials. En este carpeta se pueden guardar trozos HTML reutilizables para ser usados por los layouts.
  • shortcodes. Son pequeños trozos de HTML reutilizables con parámetros de entrada para ser usados por el contenido.

Dentro de cada layout (como en _default) tiene que haber mínimo dos archivos. Un archivo single.html que se usará cuando solo se tenga que representar una unidad de ese contenido y un archivo list.html que se usará cuando sea necesario mostrar un conjunto de esos contenidos.

Estos archivos han de programarse usando el motor de plantillas de Go y la API de Hugo. Un archivo single.html básico que muestra el título y el contenido tal cual sería así.


{{ partial "header.html" . }}
{{ partial "subheader.html" . }}
<section id="main">
  <h1 id="title">{{ .Title }}</h1>
  <div>
        <article id="content">
           {{ .Content }}
        </article>
  </div>
</section>
{{ partial "footer.html" . }}

Dentro de las páginas list.html es práctica habitual definir una vista li.html como un elemento individual. Esos elementos individuales se unen para formar la lista en list.html.

Algunos extras

Los shortcodes son pequeños trozos de HTML que aceptan parámetros. Podemos usarlos en el contenido. Piensa en ellos como Mixins de CSS o funciones de JavaScript. Por ejemplo, para marcar un resaltado de sintaxis:


<section id="mira-este-super-codigo">
	<p class="html-is-broken">Rompiendo el HTML</p>
</section>

O un enlace dentro de nuestra web: ```

```

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

Variable not found

Por el aniversario de VariableNotFound, ¡O'Reilly te regala un libro!

May 25, 2016 05:14 PM

¡Seguimos dándolo todo con motivo del décimo aniversario de Variable Not Found! Acabamos de finalizar el último sorteo y ya vamos a por lo siguiente, que os adelanto que os va a encantar :)

Seguro que no necesitáis que os presente a O'Reilly, pues se trata de una de las compañías de referencia en la difusión de contenidos para desarrolladores en forma de libros, eventos y cursos en vídeo desde hace más de veinte años.

Pues bien, O'Reilly ofrece a los lectores de Variable not found descuentos del 40% en libros en papel, y de 50% en libros electrónicos y vídeo cursos utilizando el código PCBW al realizar la compra. Interesante propuesta, ¿eh?

Pero no acaba ahí la cosa... :)

O'Reilly quiere celebrar con todos nosotros el aniversario del blog regalando a todos los lectores un libro en formato electrónico, a elegir entre los siguientes diez títulos de programación, o un vídeo-tutorial sobre Web API.

Mastering Cross-Platform Development with Xamarin Mastering Cross-Platform Development with Xamarin
By Can Bilgin
Más info
C# 6 and .NET Core 1.0: Modern Cross-Platform Development C# 6 and .NET Core 1.0: Modern Cross-Platform Development
By Mark J. Price
Más info
jQuery Essentials jQuery Essentials
By Troy Miles
Más info
C# 6.0 in a Nutshell C# 6.0 in a Nutshell, Sixth Edition
By Joseph Albahari & Ben Albahari
Más info

CSS: The Missing Manual CSS: The Missing Manual, Fourth Edition
By David Sawyer McFarland
Más info
Learning NHibernate 4 Learning NHibernate 4
By Suhas Chatekar
Más info
Learning .NET High-performance Programming Learning .NET High-performance Programming
By Antonio Esposito
Más info
Code-First Development with Entity Framework Code-First Development with Entity Framework
By Sergey Barskiy
Más info
AngularJS: Up and Running AngularJS: Up and Running
By Shyam Seshadri, Brad Green
Más info
Concurrency in C# Cookbook Concurrency in C# Cookbook
By Stephen Cleary
Más info
RESTful Services with ASP.NET Web API Vídeo (2h): RESTful Services with ASP.NET Web API By Fanie Reynders
Más info

Tanto libros como vídeos son en inglés, pero supongo que esto no será impedimento para sacarles partido, ¿verdad? ;)

¿Y cómo podéis conseguir vuestro regalo?

Los que estéis interesados (¡todos, supongo! ;D) tenéis hasta el próximo 30 de junio de 2016 para obtener vuestro regalo. Sólo tenéis que lo siguiente:
  • Ayudarme a difundirlo para darle el mayor alcance posible, pues estaréis contribuyendo a que más personas puedan beneficiarse de la oferta del patrocinador. Por tanto, os agradecería mucho;

    • Que publiquéis en vuestra cuenta de Twitter, Facebook u otras redes sociales un enlace hacia este post. Por ejemplo, estaría bien algo como lo siguiente, aunque podéis demostrar vuestra creatividad y poner otras cosas siempre que vayan en la dirección de los objetivos propuestos :)
      Por ser lector de @variablnotfound, @oreillymedia te ofrece ofertas especiales y un libro gratis: http://bit.ly/1Rhu7d4
    • Que publiquéis en vuestros blogs o páginas una breve reseña de esta iniciativa, con su enlace correspondiente a este post.
       
    • O, como mínimo, para los más perezosos, que retuiteéis en Twitter o compartáis en vuestras redes sociales los mensajes de otras personas que ya lo hayan publicado.
       
  • Si os apetece estar informados de las novedades del blog, seguir la nueva cuenta del blog en Twitter, @variablnotfound. A largo plazo pretendo que sea un canal exclusivo para el blog, separándolo de mi cuenta personal @jmaguilar.
      
  • Finalmente, reclamar vuestro libro o vídeo utilizando este enlace: http://oreil.ly/1W9VAFL. El proceso es muy simple: tendréis que registraros como usuario, elegir el contenido que os interese (uno por persona), y en pocas horas tendréis acceso al mismo.
Y por último, me gustaría agradecer a O'Reilly el interés mostrado por participar en esta celebración, y su impresionante contribución para hacerla aún más grande.

¡Que aproveche! Y seguid atentos al blog, porque la semana que viene seguiremos repartiendo regalos que seguro os dejarán alucinados :)

Publicado en Variable not found

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

Variable not found

5 cambios destacables en ASP.NET Core RC2

May 25, 2016 04:23 PM

ASP.NET Core RC2Como sabéis, hace unos días se lanzaron las respectivas versiones Release Candidate 2 de .NET Core y los frameworks ASP.NET Core y EF Core.

Los detalles ya los comentamos en un post anterior, ahora vamos a centrarnos en ver algunos cambios importantes que llaman la atención cuando empezamos a jugar con esta nueva entrega de ASP.NET Core.

1. Los proyectos ASP.NET Core son ahora plantillas independientes en VS

Recordaréis que en la RC1 (noviembre de 2015) ASP.NET Core aún no se llamaba así y era considerado como la quinta versión de ASP.NET. Por ello, la creación de este tipo de proyectos en Visual Studio se hacía eligiendo la plantilla habitual "ASP.NET Web Application", como cualquier otro de los productos alineados con la filosofía "one ASP.NET" que lanzaron desde Microsoft hace algunos años.

Pero claro, la cosa cambió cuando se decidió modificar el enfoque del producto y considerarlo algo totalmente nuevo, un reboot en toda regla que pasaría a denominarse ASP.NET Core. Ahora, en Visual Studio nos encontraremos en la categoría web con la plantilla habitual, denominada ASP.NET Web Application (.NET Framework) y con una nueva plantilla llamada ASP.NET Core Web Application, de la que tenemos dos sabores distintos, uno para .NET Core y otro para cuando vayamos a usar .NET framework completo.

Plantillas de proyecto ASP.NET Core en Visual Studio
De la misma forma, aparece una nueva categoría de plantillas llamada ".NET Core" en la que podemos crear proyectos de consola y bibliotecas de clases para este framework.
El archivo Program.cs en proyectos ASP.NET Core

2. ¿Un Program.cs, como en las aplicaciones de consola?

Pues sí, los proyectos ASP.NET Core incluyen ahora un archivo Program.cs porque de hecho son aplicaciones de consola a todos los efectos. Esto es uno de los grandes cambios que se ha introducido en la RC2 para unificar la forma en que arrancan los distintos tipos de aplicación; ya no hay magia de ningún tipo, las aplicaciones ASP.NET Core arrancan exactamente igual que una aplicación de consola estándar, y durante ese arranque configuran todo lo que necesitan para echar a andar.

En el interior de los proyectos encontraremos ahora la tradicional clase Program con su conocido método estático Main(), el punto de entrada de la aplicación, que es donde se define el host en el que se ejecutará la aplicación web, decide el servidor que usará y establece algunos detalles de su configuración antes de lanzarlo.
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
Seguro que algunos pensáis que de alguna forma esto ya lo teníamos en la RC1, pero no, no es lo mismo. En las versiones anteriores, DNX era el encargado de crear el entorno de ejecución de ASP.NET Core y desde ahí se buscaba y ejecutaba el punto de inicio de nuestra aplicación, y ahora es al revés: el método static Main() de la aplicación de consola es el que carga las bibliotecas necesarias de ASP.NET Core, prepara el entorno y ejecuta nuestra aplicación web.

Este ha sido uno de los cambios más importantes y que más han influido en el retraso del lanzamiento de la RC2.

3. El espacio de nombres AspNet es ahora AspNetCore

Era obvio pensar que un renombrado del producto tendría sus consecuencias en los espacios de nombre de muchos de sus componentes que son, al fin y al cabo, las piezas con las que construiremos nuestras aplicaciones.

Por tanto, si ya estabais programando con la RC1, el primer paso a dar para migrar la solución será actualizar todos los namespaces en usings y referencias directas a tipos:

Usings de una clase utilizando los nuevos espacios de nombre
Como consecuencia de lo anterior, también han sido renombrados los paquetes Nuget, por lo que también será necesario actualizarlos en project.json:

Referencias a paquetes Nuget en project.json utilizando los nuevos namespaces
Y, por último, observad que hay paquetes como los relativos a EntityFramework que también han cambiado su nombre a EntityFrameworkCore.

El Web.config aparece en el raíz de los proyectos4. ¿Otra vez el web.config en el raíz del proyecto?

¿Pero no habíamos quedado en que ya no hacía falta? ;D Bueno, en realidad siempre ha hecho falta si queríamos ejecutar nuestra aplicación web ASP.NET Core sobre IIS, lo que ocurre es que hasta la RC1 este archivo iba directamente sobre la carpeta wwwroot, que es donde se suponía que teníamos que establecer el raíz del sitio web en IIS.

Sin embargo, a partir de RC2, IIS debe apuntar de nuevo al raíz de la aplicación, por lo que se requiere que el web.config se encuentre de nuevo en ese punto. Por supuesto, si vamos a ejecutar directamente la aplicación sobre Kestrel o estamos trabajando sobre Linux o Mac, no necesitaremos el archivo.

Podéis leer algo más en el anuncio oficial de este cambio o seguir la discusión sobre este cambio y conocer los motivos que han llevado a ello.

En cualquier caso, también el contenido del web.config ha sufrido modificaciones desde la última release del producto. Ya no utilizaremos más HttpPlatformHandler, sino un módulo específico para ASP.NET Core llamado AspNetCoreModule (puedes leer más información sobre este cambio aquí).

5. .NET Core CLI

Si sois de los que disfrutan trasteando desde la línea de comandos, debéis saber que ASP.NET Core RC2 ya sólo funciona con el .NET Core CLI, la nueva interfaz de línea de comandos de .NET Core. Como consecuencia, las órdenes que utilizábamos hasta ahora para tareas como lanzar o compilar aplicaciones o gestionar paquetes Nuget (dnx, dnvm, dnu) han pasado a la historia.

Ahora la orden básica que utilizaremos es "dotnet", un mecanismo extensible que provee herramientas para crear proyectos, restaurar sus dependencias, construirlos, publicarlos, ejecutarlos, ejecutar tests, y generar paquetes Nuget:

Salida por consola del nuevo comando dotnet
Por ejemplo, la siguiente secuencia utiliza el comando "dotnet new" para crear una aplicación .NET Core vacía en una carpeta (el clásico "hello world"), "dotnet restore" restaurar los paquetes Nuget que necesita para funcionar, y por último "dotnet run" para ejecutarla:

Creación de una aplicación .NET Core usando .NET Core CLI y el comando 'dotnet'
Obviamente esto son sólo algunas de las novedades de alto nivel introducidas en ASP.NET Core RC2. Iremos publicando más detalles conforme vayamos profundizando en esta release y viendo qué ha traído de la mano.

Publicado en Variable not found.

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

Poesía Binaria

Cómo conocer CPU y memoria ocupada por un grupo de procesos con el mismo nombre

May 25, 2016 10:43 AM

photo-1463123081488-789f998ac9c4

En multitud de ocasiones, mientras estamos trabajando con nuestro ordenador, o incluso con un servidor remoto, se presenta la necesidad de saber la memoria ocupada o la CPU consumida por un determinado proceso.
Para ello tenemos herramientas como top o ps (entre otras) que nos permiten conocer dicha información. Podemos encontrar multitud de tutoriales para ambos comandos, sólo daré una pincelada aquí.

ps

Casi siempre que uso ps suelo hacerlo de la siguiente manera:

$ ps ax

para así mostrar todos los procesos que están corriendo actualmente, y si queremos obtener información sobre memoria y CPU podremos ejecutar:

$ ps axl

o

$ ps axo pid,pcpu,pmem,size,cmd

Si queremos obtener más datos como ID de proceso (pid), % de CPU (pcpu), % de memoria (pmem), tamaño en memoria (size), comando que genera el proceso (cmd).

top

Desde aquí podemos ver en tiempo real los procesos que están ejecutándose en la máquina (se va actualizando en el tiempo) y podemos ordenarlos por varios criterios pulsando (<) y (>) además de filtrarlos, matarlos, etc. Para salir, debemos pulsar q.
Screenshot 24-05-2016-170548

Otros administradores

Por supuesto, también tenemos administradores gráficos de tareas, por ejemplo, aquí tenemos un pantallazo del administrador de tareas de KDE:
Screenshot 25-05-2016-120557
Con muchas opciones.

Agrupando procesos

Pero en la vida del sysadmin, en ocasiones tenemos la necesidad de saber lo que ocupan todos los procesos con el mismo nombre. Porque, muchas veces, un mismo programa lanza varios procesos homónimos que corren de forma concurrente. Podemos verlo, por ejemplo, cuando ejecutamos Chrome o Chromium, Spotify, procesos de Apache, PHP, o incluso cuando tenemos muchas sesiones de terminal abiertas y queremos saber cuánta memoria ocupan todas juntas.

Para eso, podemos utilizar el siguiente script:

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
#!/bin/bash

GROUP_ARG=$1
HUMAN=0
case $GROUP_ARG in
     "rss")
    GROUPABLE="rss"
    HUMAN=1
    ;;
     "size")
    GROUPABLE="size"
    HUMAN=1
    ;;
     "pmem")
    GROUPABLE="pmem"
    HUMAN=0
    ;;
     "pcpu")
    GROUPABLE="pcpu"
    HUMAN=0
    ;;
     *)
    echo "Bad argument!"
    exit
esac

ps -axo pid,$GROUPABLE,cmd | awk '
function human(x) {
         s="KiB MiB GiB TiB EiB PiB"
         while (x>=1024 && length(s)>1)
               {
               x/=1024;
               s=substr(s,5)
           }
         s=substr(s,0,3)
         return sprintf( "%.2f%s", x, s)
}
BEGIN {
    i=0
}
{
    if (!procesos[$3])
    {
        procesos[$3]=i
        pids[i]=$1 ""
        group[i]=$2
        i++

    }
    else
    {
        n = procesos[$3]
        pids[n]=pids[n] ", " $1 ""
        group[n]+=$2
    }
}
END {
    for (p in procesos)
    {
        i = procesos[p];
                if ('
$HUMAN')
                printf "%s %s (%s)\n", p, human(group[i]), pids[i]
        else
                printf "%s %s (%s)\n", p, group[i], pids[i]
    }
}
'
;

Cuando lo ejecutemos, debemos pasar un argumento: rss (tamaño de la parte residente en memoria del proceso), size (tamaño virtual del programa), pmem (% de memoria), pcpu (% de CPU) dependiendo del criterio que vamos a agrupar.

Si observamos, el script hace una llamada a ps -axo pid,(parametro),cmd por lo que recibiremos sólo 3 elementos de cada proceso, su identificador, el elemento que queremos agrupar y la línea de comandos invocada para correr el proceso. Todo eso se lo pasamos a awk que procesará línea por línea dicha información.

Dentro de awk, tenemos la función human, que transformará tamaños de KiB a unidades superiores (para que los tamaños sean más fáciles de leer, por ejemplo 1048576KiB = 1GiB). Awk, manejará 3 arrays, procesos, pids y group. Procesos[] asignará a cada cmd un índice consecutivo. pids[] asignará a cada índice una lista de IDs de procesos separados por comas, al final será una cadena de texto y group[] asignará a cada índice un número que será la suma de todos los argumentos que agrupemos (ya sabemos, memoria, cpu…). Lo que awk hará en cada iteración será buscar si ya ha visto un proceso con ese nombre, en caso afirmativo añadirá la información de la línea actual a los arrays del proceso, de otro modo, añadirá un elemento a cada array con información del proceso que acabamos de ver.

Para finalizar, una vez se haya recopilado la información, se recorrerá el array de procesos para imprimir en pantalla la información formateada y, en el caso de que la información a agrupar sea un tamaño (memoria), lo pondremos en formato humano (función human de arriba) para facilitar la legibilidad.

Ejemplos de uso

Yo he llamado al programa groupps. Para ejecutarlo puedo hacer:

$ ./groups size

y me mostrará el espacio ocupado por todos los procesos. Aunque podemos usar grep para filtrar esta información, por ejemplo, para ver cuánto ocupan todos los procesos de php-cgi-5.5 que tengo actualmente corriendo:

$ ./groups size | grep php-cgi-5.5
/opt/phpfarm/inst/bin/php-cgi-5.5.19 101.23MiB (4790, 4791, 4792, 4793, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 28576, 28640, 28641, 28642)

En este caso veo que la suma del tamaño de todos los procesos de php es de 101.23MiB. Tenemos que tener

O puedo ver la CPU total consumida por los procesos de Spotify:

$ ./groupps pmem | grep spotify
/usr/share/spotify/spotify 12.3 (31847, 31849, 31863, 31879)

En este caso un 12.3%

Sobre este script

Este script lo incluiré en gscripts muy pronto, junto con una colección de scripts para hacer nuestra vida con la terminal más fácil.

Foto: Hoach Le Dihn

The post Cómo conocer CPU y memoria ocupada por un grupo de procesos con el mismo nombre appeared first on Poesía Binaria.

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

Variable not found

VariableNotFound cumple diez años, ¡y lo vamos a celebrar!

May 25, 2016 07:06 AM

¡10 años de VariableNotFound!Pues sí, amigos, ¡diez añazos! Mucho más de lo que habría podido imaginar en aquellos tiempos en los que Windows XP era el rey del escritorio, nadie había oído hablar de Twitter o Facebook y no existían los smartphones tal y como hoy los conocemos. Tiempos en los que decidí subirme al tren y empezar a escribir sobre cosas que iba aprendiendo y que pensaba que podría ser de utilidad a más gente.

Diez años después, con más de ochocientas cincuenta entradas, cerca de 2.000 comentarios publicados, y acercándonos a los dos millones de páginas vistas, si hay algo que tengo claro es que esto no habría sido posible sin vosotros, queridos lectores y amigos de la Variable. Muchas gracias a todos por estar ahí durante todos estos años, por vuestras visitas, vuestras aportaciones y sugerencias, y por permitirme seguir aprendiendo de vosotros cada día.

Y como desde pequeñito me enseñaron que en este mundo hay que ser agradecido, lo mejor que puedo hacer es celebrar este grato acontecimiento con todos vosotros :)

Así que, contando con el increíble apoyo de compañías de primera línea que han decidido sumarse a esta fiesta de celebración, durante las próximas semanas vamos a realizar sorteos de productos y servicios que seguro os entusiasmarán :)

CampusMVP  JetBrains  Telerik  Grapecity 
O'Reilly Media  Microsoft
  DevExpress

Estad atentos al blog, que ¡en breve comenzamos a repartir regalos!

En curso:

Por el aniversario de VariableNotFound, ¡O'Reilly te regala un libro!

Sorteos ya finalizados:

El blog: las cifras del año pasado

Y dicho todo lo anterior, ya sabéis que me gusta siempre hacer un breve repaso de la evolución del blog durante el año pasado, así que, para los curiosos, ahí va.

Siguiendo en la tónica de los últimos años, continuamos lo que ya el año pasado denominé como una fase de leve crecimiento sostenido. Según las analíticas de Google, nos visitaron 150.000 usuarios (+6%), 272.000 páginas vistas (+0,64%), con un promedio de tiempo de estancia de 03m48s (+5%). En la página de Facebook superamos los 800 amigos (+7%), y en Twitter superamos los 1415 seguidores (+13%).

El oráculo de Google dice que la mayoría sois hombres (83%), aunque curiosamente este dato ha descendido un 7% en el último año, principalmente de entre 25 y 34 años (50%), profesionales de internet, tecnófilos, aficionados al cine y TV, entusiastas de los móviles y de los deportes (fútbol, principalmente).

BrowsersChrome sigue siendo el navegador más usado para acceder a los contenidos, con más del 73% de los usuarios. Respecto al año pasado, siguen cayendo Firefox (16%) y IE (6%). El nuevo Edge no supera el 1%. El 92% de vosotros usáis Windows, siendo Mac el segundo más utilizado con el 3%. Curiosamente, el 50% lo hacéis desde Windows 7, el 23% desde Windows 8.1, y algo más del 16% estáis ya utilizando Windows 10.

Tras varios años de incremento de visitas procedentes del otro lado del Atlántico, el origen de las visitas está prácticamente igualado ya entre España (22%) y Mexico (21%). Algo detrás, pero también in crescendo, tenemos Colombia (11%), Perú (8%), Argentina (7%) y Chile (6%).

Como es habitual, el 83% de las visitas proceden de los buscadores, Google en más del 99% de las ocasiones. El acceso directo, introduciendo la URL o desde favoritos, se utiliza el 10% de las ocasiones, y apenas un 4% de enlaces desde otros sitios web.

Y respecto a la pregunta que me han hecho tantas veces: "¿Y realmente te vale la pena? ¿Qué sacas tú de esto?" La respuesta sigue siendo una afirmación categórica, por supuesto que vale la pena. La satisfacción que supone escribir sobre lo que me gusta y pensar que esto puede ser útil a alguien es inigualable, y los grandes amigos que voy haciendo a lo largo de este camino no tienen precio. Sólo esto ya compensa al 100% el esfuerzo que supone mantener un blog tanto tiempo.

Pero dejando los intangibles aparte, también aporta otro tipo de beneficios más terrenales, aunque no por el lado de la publicidad, que es el que parecería obvio: Adsense sigue básicamente en su tónica; los ingresos me permiten invitar a mi familia a almorzar un par de veces al año, pero decididamente esto no va a ayudarme a liquidar la hipoteca ;D Ni rastro tampoco de los posts patrocinados de antaño, ni de anunciantes fijos que sí disfruté hace algunos años ya.

Los beneficios son indirectos y llegan en forma de visibilidad y oportunidades profesionales que de otra forma no habrían sido posibles. Por tanto, os puedo decir de primera mano que realmente un blog no sólo os podría ayudar a encontrar empleo; si prestáis servicios profesionales de cualquier tipo, vuestra bitácora puede seros incluso de más utilidad que contratar una valla publicitaria en vuestra autopista favorita ;D

Eso sí, también os puedo decir que en ningún caso, al menos de los que conozco, se trata de un retorno inmediato: se requieren años para llegar a este punto, y de hecho lo más habitual es que se caiga por el camino antes de conseguirlo. Pero sinceramente, no es nada que con un poco de paciencia y tesón no pueda conseguirse, así que os animo a lanzaros de forma decidida, que seguro que vuestro yo del futuro os lo agradecerá ;)

Y finalmente, aprovecho estas últimas líneas para agradeceros de nuevo vuestro incondicional apoyo durante todo este tiempo, y espero que sigáis por aquí muchos años más, ayudándome a buscar la Variable.

Publicado en Variable not found.

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

Variable not found

Enlaces interesantes 242

May 23, 2016 07:05 AM

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

Eventos

.Net

ASP.NET

ASP.NET Core

Azure / Cloud

Conceptos/Patrones/Buenas prácticas

Data

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Cross-platform

Otros

Y para finalizar, un vídeo que, por fin, nos ofrece la explicación científica de por qué hay tan pocas chicas que se dedican a la programación ;D





Publicado en Variable not found

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

Koalite

Resolviendo el acertijo de Einstein

May 23, 2016 05:06 AM

De pequeño me encantaban los pasatiempos de lógica. Creo que la “culpa” es de mi abuelo, que fue quien me introdujo en el mundo de los pasatiempos. Él era un gran aficionado a los autodefinidos, pero mis favoritos siempre fueron los típicos juegos de lógica:

pasatiempo-de-logicaLa de tardes que pasé de pequeño entretenido con pasatiempos como éste de Diario 16.


Por eso cuando Luis Souto enlazó en twitter el Acertijo de Einstein me pareció una buena oportunidad para pasar un rato entretenido, pero sobre todo, para jugar un poco con programación basada en restricciones.

Hace unas semanas escribí sobre la Programación Basada en Restricciones (Constraint Programming), que es un paradigma que nos permite resolver un problema de forma declarativa, definiendo las variables que lo componen y las restricciones entre las mismas, y dejando que sea el sistema el que halle soluciones que cumplan esas restricciones.

Una de las partes complicadas de todo esto es encontrar la forma de modelar el problema, así que vamos a aprovechar el Acertijo de Einstein para practicar un poco y ver un ejemplo algo más complejo que el de las 8 reinas que vimos en el post anterior.

El Acertijo de Einstein

El puzzle que vamos a resolver se conoce como Puzzle de la Cebra o Acertijo de Einstein y la versión que usaremos es la siguiente:

  1. Hay 5 casas colocadas una al lado de la otra.
  2. La casa del inglés es roja.
  3. El español tiene un perro.
  4. El japonés es detective.
  5. El francés bebe té.
  6. La casa blanca está inmediatamente a la derecha de la casa verde.
  7. En la casa del medio se bebe leche.
  8. La casa del noruego es la primera de la izquierda.
  9. La casa vecina al noruego es azul.
  10. La casa amarilla es del médico.
  11. El vecino del médico tiene un caballo.
  12. El vecino del inglés es arquitecto.
  13. El vecino del arquitecto tiene un zorro.
  14. El abogado bebe zumo de tomate.
  15. El ingeniero tiene un gato.
  16. En la casa verde se bebe café.

El objetivo, como os podéis imaginar, es averiguar de qué color es cada casa, de qué nacionalidad es su propietario, qué bebe y qué animal es su mascota.

Modelando el problema

Para modelar el problema voy a utilizar loco, una librería para utilizar programación basada en restricciones con clojure, pero en realidad las ideas serían aplicables a cualquier otro lenguaje o librería.

Lo primero es definir las variables sobre las que vamos a trabajar.

Para cada casa tendremos que definir el color, el país del dueño, la bebida y el animal. Pero además, viendo el enunciado, queda claro que la posición de las casas importa porque tenemos pistas de la forma el vecino del…. Por tanto, numeraremos las casas de la 0 a la 4, considerando que la 0 es la casa de la izquierda y la 4 la de la derecha.

Para crear las restricciones necesitamos trabajar con valores numéricos (al menos en loco, no sé en otras librerías), por lo que habrá que traducir los datos del puzzle (rojo, té, noruego, etc.) a valores numéricos para crear las restricciones. Eso nos lleva a que una vez hecha la traducción cada variable podrá tomar valores entre 0 y 4.

Si no queremos volvernos locos, podemos definir una estructura que nos permita traducir entre nombres y valores numéricos:

(def domain
  {:color [:red :blue :green :yellow :white]
   :country [:england :spain :france :norway :japan]
   :beverage [:tea :milk :tomato :coffee :beer]
   :animal [:dog :horse :fox :cat :zebra]
   :job [:detective :doctor :architect :lawyer :engineer]})

;; Convierte algo como [:job :lawyer] en su valor numérico (3)
(defn to-val [prop name]
  (.indexOf (domain prop) name))

;; Convierte un valor numérico en su nombre [:job 1] => :doctor
(defn to-name [[prop value]]
  (get-in domain [prop value]))

Con todas esas piezas ya podemos definir las variables en loco:

(def vars (for [prop (keys domain)
                idx (range 5)]
            ($in [prop idx] (range 5)))

;; ([:color 0] [:color 1] ... [:color 4]
;;  [:country 0] ...       [:country 4]
;;  ...
;;  [:job 0]                [:job 4])

Como todas las casas deben tener valores distintos para cada propiedad (color, país, etc.), resulta útil definir una función que nos ayude a expresarlo:

(defn all-distinct [prop]
  ($distinct (map (partial vector prop) (range 5))))

;; Para indicar que todos los colores son distintos:
;; (all-distinct :color)

Hasta aquí hemos visto una forma relativamente sencilla de modelar variables, datos y restricciones básicas (que sean todos distintos), pero nos queda la parte divertida: modelar las restricciones más complicadas.

Si analizamos las pistas del enunciado del problema, vemos que en realidad podemos clasificarlas en 4 tipos.

El primer tipo son las pistas que fijan una variable a un valor concreto, por ejemplo la casa del noruego es la primera de la izquierda o en la casa del medio se bebe leche. Traducido al DSL de loco, habría que escribir algo así:

;; [:country 0] es el país de la casa de la izquierda y 3 es el valor de noruega
($= [:country 0] 3)

Eso es completamente ilegible. Preferiría poder escribir algo así:

;; La casa del noruego es la primera de la izquierda
(fact [:country 0 :normay])

;; En la casa del medio se bebe leche
(fact [:beverage 2 :milk])

Para ello, vamos a crear una función que nos permita definir ese tipo de restricciones de una forma más agradable:

(defn fact [[prop idx name]]
   ($= [prop idx] (to-val prop name)))

El siguiente tipo de pista liga dos propiedades de una misma casa, como la casa roja es del inglés. Hay varias formas de expresar esto con loco, pero la que más me gusta es verlo como que alguna de las casas cumple que es roja y el país del dueño es inglaterra. Es decir:

∃ i : countryi = england ∧ colori = red

Escrito de forma legible, me gustaría poder expresarlo así:

;; La casa del inglés es roja
(fact [:country :england] [:color :red])

;; La casa amarilla es del médico
(fact [:color :yellow] [:job :doctor])

Para lo que podemos emplear un $or entre todas las casas:

(defn fact [[prop1 name1] [prop2 name2]]
   (apply $or (map #($and ($= [prop1 %] (to-val prop1 name1))
                       ($= [prop2 %] (to-val prop2 name2)))
                   (range 5))))

Otro tipo de pista liga dos propiedades pero no de la misma casa, sino de una casa con alguno de sus vecinos, por ejemplo el vecino del inglés es arquitecto. Esto podemos verlo como la mezcla de dos restricciones, o bien se cumple entre una casa y su vecino de la derecha, o bien se cumple entre una casa y su vecino de la izquierda:

∃ i : countryi = england ∧ jobi+1 = architect ∨ countryi = england ∧ jobi-1 = architect

Siguiendo el estilo del mini DSL que nos estamos creado, esto podríamos definirlo así:

;; El vecino del inglés es arquitecto
(side-fact [:country :england] [:job :architect])
   
;; El vecino del arquitecto tiene un zorro
(side-fact [:job :architect] [:animal :fox])

Y la función para hacerlo funcionar sería la siguiente:

(defn side-fact 
  [[prop1 name1] [prop2 name2]]
  (apply $or
         (concat
          (map #($and (fact [prop1 % name1]) (fact [prop2 (inc %) name2])) (range 4))
          (map #($and (fact [prop1 % name1]) (fact [prop2 (dec %) name2])) (range 1 5)))))

Falta un último tipo de pista, la relación entre una propiedad de una casa y la de su vecino de la derecha que aparece en La casa blanca está inmediatamente a la derecha de la casa verde. Es un caso particular del tipo anterior y se resuelve de forma muy parecida por lo que os ahorro la explicación y el código.

Usando las funciones que hemos ido creando, definir y resolver el problema es muy sencillo y hasta legible:

(def model

  (conj

   ;; Variables [:country i] [:animal i] [:color i] [:beverage i] [:job i] con i = [0..4]
   (for [prop (keys domain)
         idx (range 5)]
     ($in [prop idx] (range 5)))

   ;; Todas las variables de cada propiedad deben ser diferentes
   (all-distinct :color)
   (all-distinct :animal)
   (all-distinct :beverage)
   (all-distinct :country)
   (all-distinct :job)

   ;; La casa del inglés es roja
   (fact [:country :england] [:color :red])
   
   ;; El español tiene un perro
   (fact [:country :spain] [:animal :dog])
   
   ;; El japonés es detective
   (fact [:job :detective] [:country :japan])
   
   ;; El francés bebe té
   (fact [:country :france] [:beverage :tea])
   
   ;; La casa blanca está inmediatamente a la derecha de la casa verde
   (right-fact [:color :green] [:color :white])
   
   ;; En la casa del medio se bebe leche
   (fact [:beverage 2 :milk])
   
   ;; La casa del noruego es la primera a la izquierda
   (fact [:country 0 :norway])
   
   ;; La casa vecina al noruego es azul
   (side-fact [:country :norway] [:color :blue])
   
   ;; La casa amarilla es del médico
   (fact [:color :yellow] [:job :doctor])
   
   ;; El vecino del médico tiene un caballo
   (side-fact [:job :doctor] [:animal :horse])
   
   ;; El vecino del inglés es arquitecto
   (side-fact [:country :england] [:job :architect])
   
   ;; El vecino del arquitecto tiene un zorro
   (side-fact [:job :architect] [:animal :fox])
   
   ;; El abogado bebe zumo de tomate
   (fact [:job :lawyer] [:beverage :tomato])
   
   ;; El ingeniero tiene un gato
   (fact [:job :engineer] [:animal :cat])
   
   ;; En la casa verde se bebe café
   (fact [:color :green] [:beverage :coffee])))

(def sol (solution (model))

El código completo incluye algun detalle para formatear la solución, pero básicamente es lo que hemos visto en este post.

Resumen

Además de como divertimento, me ha gustado resolver el problema para intentar entender mejor cómo modelar problemas con programación basada en restricciones.

Aunque no sea algo que vaya a usar a diario, me parece una forma de resolver problemas muy interesante donde la complejidad reside en ser capaz de especificar el problema a base de restricciones y ver que, pensando un poco, es posible modelar cosas a priori bastante alejadas de los típicos ejemplos de álgebra lineal que he encontrado por ahí me ha parecido curioso.

No hay posts relacionados.

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

Variable not found

Sorteo: Libro "Programación con SignalR"

May 22, 2016 10:55 AM

Sorteo cerrado, ya tenemos los ganadores :) Muchas gracias a todos por participar!
Como os comenté hace unos días, vamos a celebrar el décimo aniversario de este blog con regalos para vosotros, que al fin y al cabo sois los que habéis hecho posible que hayamos llegado tan lejos en esta aventura.

También os adelanté que mi idea era organizar sorteos de productos y servicios proporcionados por los patrocinadores que se han sumado a este acontecimiento. Se trata de empresas que todos conocéis sobradamente y que han decidido donar productos y servicios de gran calidad (y habitualmente de un coste considerable) para vosotros.

Pero para inaugurar esta serie, quería empezar con una aportación personal que, por su significado, es para mi muy especial: sortearemos 3 ejemplares en papel de mi libro "Programación con ASP.NET SignalR".

Mi libro de SignalR 2.0Para los que no estéis al tanto, se trata de mi primera aventura en el mundo literario, es una completa guía de aprendizaje de SignalR, el framework de programación de aplicaciones en tiempo real. El libro ha sido distribuido de forma global, está disponible en español, inglés, chino y japonés, y ha alcanzado una valoración de 4.8 puntos sobre 5 en Amazon.

Los ganadores recibirán su ejemplar en la dirección que indiquen una vez concluya el sorteo. Además, para que el valor del regalo pase de algunas decenas de euros a ser realmente incalculable, os lo enviaré con una dedicatoria personal (naah, esto es básicamente porque dedicar ejemplares me hace sentir importante ;D)

Por limitaciones de disponibilidad dos ejemplares serán en español, editado y distribuido por los amigos de Krasis Press, y uno de ellos en inglés, la edición original de Microsoft Press. Si tenéis algún problema en recibir la copia en inglés podéis indicarlo al participar en el sorteo.

¿Y cómo participo en el sorteo?

Los que estéis interesados en participar sólo tenéis que conseguir "papeletas"; cada uno de vosotros podéis conseguir hasta cuatro, dependiendo del grado de afinidad que mostréis con Variable not found ;D Obviamente, cuantas más papeletas consigáis, más probabilidades tendréis de ganar el premio.

Atentos a las especificaciones:
  • Para conseguir la papeleta que os da derecho a participar en el sorteo, sólo tenéis que escribir un comentario en este post del blog. Podéis aprovechar para contarme cuánto tiempo lleváis siguiéndolo, qué cosas os gustan más (o menos) de él, a qué os dedicáis, o el tiempo que hace en vuestra ciudad ;D El caso es comentar algo. Y sobre todo incluid alguna vía para que pueda contactaros si sois los afortunados (preferiblemente email, pero también podría ser twitter o la dirección de vuestro perfil de facebook).
Ojo: si incluís vuestro email en el comentario, usad alguna forma creativa de ocultarlo a los rastreadores para que no os frían a spam. Por ejemplo, "pedroperez en ge mail punto com", o "dale la vuelta a com gmail arroba joselito".
Para que os quede más claro, el siguiente sería un ejemplo de comentario de un participante que se ha asegurado de que sigue a Variable Not Found en todos sus perfiles y que jugaría con todas las papeletas posibles:
Hola, sigo tu blog desde el mes pasado y me parece muy bueno.
Soy mazinger en ge-mail y al final le añades un .com si me toca.
+TW1+TW2+FB
No olvidéis incluir en el comentario los textos "+TW1", "+TW2" o "+FB" para indicar los perfiles a los que seguís, pues pretendo automatizar el proceso del sorteo, y las papeletas serán asignadas por una aplicación en función de la existencia de esos textos en el comentario ;)

Y aseguraos de que realmente seguís, y que yo puedo comprobarlo, los perfiles sociales que habéis indicado, porque de no ser así seréis descalificados!

¿Cuándo se realiza el sorteo?

El sorteo se realizará el próximo domingo 22 de mayo. Todos los comentarios que entren a partir del sábado a las 23:59 serán eliminados, como castigo por dejarlo para última hora ;D

Como no creo que vaya a poder venir ningún notario, tendréis que confiar en el que el proceso será completamente limpio. Una aplicación leerá los comentarios del post y asignará papeletas en función de los perfiles seguidos (+TW1, +FB…). La misma aplicación elegirá al azar los tres ganadores, y verificaré manualmente que sus papeletas sean correctas antes de darlos por definitivos, repitiendo el proceso si fuera necesario.

Los ganadores seréis notificados personalmente a través de la vía que hayáis indicado al participar. Si por cualquier motivo no fuera capaz de contactar con vosotros en un tiempo razonable, el premio será sorteado de nuevo entre los participantes. También lo iremos difundiendo a través del blog y los distintos perfiles sociales.

Ale, ya estáis tardando en participar :D ¡Mucha suerte!

Publicado en Variable not found

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

Blog Bitix

3 opciones ofimáticas alternativas a Microsoft Office

May 22, 2016 10:30 AM

Office es la suite ofimática de Microsoft con un margen de diferencia en la cuota de uso muy amplio sobre la siguiente opción en los sistemas con Windows. Es muy completa que incluye más funciones incluso que la mayoría de usuarios conoce o necesita pero también es una opción más cara que otras alternativas que incluso llegan a ser gratuitas sin tener nada que envidiarle para la mayoría de usuarios y casos de uso.

Microsoft
LibreOffice

En el primer artículo de este 2016 comentaba que Windows y Office aún siguen siendo fáciles de usar sin licencia. Licencia que cuesta nada más ni nada menos que unos 125€ para el hogar y estudiantes y unos 250€ para empresas, por equipo. Y si el equipo se renueva o estropea requiriendo cambiar algunos componentes debe adquirirse una nueva licencia. Dado el coste nada despreciable de la licencia no es de extrañar que tanto Windows como Office sean unos de los productos más usados sin licencia o pirateados.

Dada lo fácil que es usar Windows y Office sin licencia junto con el impuesto Windows hacen que tengan una cuota de mercado en números prácticamente de monopolio ni hay muestras de que vaya a cambiar a corto plazo. A veces pienso que a Microsoft no le importa que uses Windows u Office sin licencia para uso personal. Sin embargo, hay alternativas tanto para Windows como para Office que tienen poco que envidiarle, mucho más baratas o incluso gratuitas y de software libre incluso con un soporte mejor que el que ofrece Microsoft para su propio software.

Las alternativas a Windows son los caros productos de Apple muy orientados a gamas altas sobre todo por el precio o alguna de las muchas distribuciones GNU/Linux que son prácticamente en su totalidad gratuitas y de software libre, aunque el software libre no tiene por que ser gratuito en la mayoría de los casos lo es.

En este artículo me centraré más en las alternativas a Office que también son varias. Obviando el tema del software libre, Office es una buena y completa suite ofimática con más opciones de la que muchos usuarios necesitarán.

Microsoft Office

Microsoft Office incluye Word como procesador de textos, Powerpoint para presentaciones, Excel para hojas de cálculo, Access para bases de datos, Outlook como cliente de correo electrónico, OneNote para tomar notas o Publisher para publicaciones. Solo está disponible para Windows y Mac para el escritorio y las versiones web para estos y otros sistemas. Office 365 tiene un coste alrededor de 8,80€ por usuario y mes según el plan que incluye más o menos aplicaciones.

LibreOffice

La alternativa libre y gratuita equivalente de Office es LibreOffice. Incluye un editor de textos con Writer, hojas de cálculo con Calc, presentaciones con Impress, Draw para crear gráficos y Base para bases de datos sencillas. Sin embargo, la interfaz es el similar al de Office en las ediciones anteriores a la incorporación de ribbon con una estética sin la sensación de estar cuidada. Los menús son largos y encontrar un opción entre las muchas disponibles no es sencillo, al abrir una opción de menú uno se puede sentir intimidado por la longitud del mismo y es algo más difícil encontrar rápidamente la opción buscada entre todas las mostradas. Habrá usuarios que prefieran la interfaz de menús y barras de herramientas, yo soy de los que les gusta más ribbon. Está disponible para Windows, Linux y Mac.

WPS Office

Si nos gusta más la interfaz ribbon sin menús con multitud de opciones y que esté más cuidada en cuanto a diseño que LibreOffice similar a la usada en Microsoft Office, WPS Office es una opción muy a tener en cuenta, también puede activarse en modo clásico con menús y barras de herramientas soportando editar varios documentos en tabuladores. Ofrece únicamente los programas básicos de una suite ofimática: editor de textos, hojas de cálculo y presentaciones. Para un uso personal es gratuita con algunas limitaciones al imprimir y exportar documentos a formato PDF pero más que suficiente aún sin todas las opciones solo disponibles en la opción de pago.

Para el ámbito empresarial o con todas sus opciones su licencia tiene un coste mucho más razonable que el de Microft Office, 45€ para una licencia de un año y 80€ para la licencia de por vida por usuario.

Está disponible para Windows (XP, Vista, 7, 8, 10) incluso en versiones para los que ni Microsoft Office ya ofrece soporte, Linux, Android e iOS. Su instalador ocupa únicamente unos 80 MiB contra los más de 3 GiB de Office.

Google Docs

Otra alternativa a Office es Google Docs, no tiene todas las opciones que tiene Office pero para la mayoría de usuarios es suficiente. Basta con tener una cuenta de Google para usarla que incluye un editor de textos, de hojas de cálculo, de presentaciones y la posibilidad de realizar formularios. Se ejecuta en el navegador y aunque es posible en trabajo sin conexión a internet en momentos puntuales es requerirdo. Los documentos se almacenan en la nube con lo que no los perderemos en caso de estropearse nuestro equipo, podremos acceder a los documentos desde cualquiera de nuestros dispositivos como un teléfono inteligente, editar el mismo documento dos o más personas de forma simultanea o compartir los documentos con otras personas. Al estar basado en la nube no necesitamos realizar actualizaciones de software salvo el navegador.

Para las empresas se ofrece al precio de 4€ por usuario al mes que incluye el cliente de correo Gmail, calendarios, videollamadas y 30 GB de almacenamiento. Serán 8€ con más opciones de almacenamiento y retención de mensajes.

Alguna otra opción que merece ser comentada es Calligra la suite del entorno de escritorio KDE, Abiword, Lyx o Gnumeric.

La próxima vez que me pidan reinstalar Windows u Office en vez de instalar la suite ofimática de Microsoft sin licencia creo que instalaré la opción para uso personal de WPS Office, recomendaré usar Google Docs o LibreOffice que espero mejore y actualice a los tiempos modernos su interfaz cuando tenga que instalarlo.

Referencia:
A Microsoft no le importa que uses Windows u Office sin licencia
Windows 10 y Office 2016 tan fáciles de usar sin licencia como siempre
El impuesto Windows
LibreOffice
WPS Office
Google Docs

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

Variable not found

Ganadores del sorteo de libros de SignalR

May 22, 2016 09:43 AM

Bien, pues mi generador de números seudoaleatorios ha hablado y ya tenemos los tres ganadores del sorteo de libros de SignalR:

image Programación con ASP.NET SignalR 2.0
Krasis Press
David Carrascosa
@carrascosad
Madrid
image Programación con ASP.NET SignalR 2.0
Krasis Press
Ellery Sammy Valest Torres
@ellerysammy
Barranquilla – Cartagena
image SignalR programming in Microsoft ASP.NET
Microsoft Press
Dachi Gogotchuri
@dachibox
Madrid
En breve me pondré en contacto con los afortunados para concretar los detalles del envío :)

¡Muchas gracias a todos por participar!  Y no os despistéis mucho, porque esto sólo acaba de comenzar y en breve vamos a lanzar nuevas oportunidades para que os llevéis regalos aún más sorprendentes.

Publicado en Variable not found

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

Poesía Binaria

BITes: ImageTragick, Windows95, metadatos, top, peligros DRM, software libre y más

May 22, 2016 07:57 AM

photo-1458400411386-5ae465c4e57e

Hace unas cuantas semanas que no publico un resumen de enlaces, así que éste debe ser especial, vamos, un poco más largo, y mira que me dejo cosas, de lo mucho que ha pasado en el mundo tecnológico estos días, aunque hay algunos temas que me han interesado más y no tienen por qué ser novedades.

  • Command Injection en ImageMagick: He hablado estos días de este gran programa de manipulación de imágenes desde terminal. Y precisamente, ha sufrido uno de esos grandes golpes llamado ImageTragick. Nos puede afectar tanto en nuestro ordenador, como en nuestro servidor si tenemos aplicaciones que utilicen ImageMagick o MagickCore. Permite ejecutar cualquier cosa en el servidor de destino, lo cual lo convierte en un fallo muy grave. Muchas distribuciones siguen sin parche, aunque en muchos sitios se puede aplicar una restricción en las políticas de ImageMagick para evitar que se puedan abrir ciertos tipos de archivo y evitar así el problema.
  • Ejecuta Windows95 en un Apple Watch: Una de esas cosas inútiles de la vida, que parece mentira que alguien haya utilizado algún día de su vida en hacer algo que no vale para nada. Porque sólo vale para decir: he conseguido ejecutar Windows95 en mi Apple Watch, pero no puedes hacer nada remotamente útil con él
  • Metadatos en GNU/Linux: Una excelente introducción al mundo de los metadatos en nuestro Sistema Operativo favorito, con varias herramientas muy útiles.
  • ¿Que es VIRT, RES y SHR en la salida del TOP?. Es algo que me han preguntado en varias ocasiones. Pues bien, aquí está explicado de una forma sencilla.
  • Diferencias entre software libre, software privativo y código abierto. Aunque hace poco traté un tema parecido, aquí tenemos otro punto de vista más. En ocasiones muchos pecamos de meter software libre y open source en la misma saca. Si Richard Stallman pudiera salir por mi pantalla me daría una colleja…
  • Los peligros imprevistos del DRM. No tiene desperdicion, y pensar que en pleno 2016 estemos así… pero, como siempre, los intereses económicos son más valiosos que la propia evolución.
  • Cleaning up your Linux Sturtup Process. Hacer una limpieza de los servicios de arranque del sistema. También nos vale como una introducción a systemd.

Reto 2016

¡No sé por qué lo recuerdo! Ya que he pasado mucho tiempo sin publicar con tanta asiduidad como a primero de año, pero bueno, vamos a ver… eran 150 posts este año, y casi casi llegando a los 6 meses he publicado sólo 39, por lo que en poco más de medio año tengo que hacer más de 100 posts. Aunque nada es imposible :) Bueno, tengo muchas ideas, y terrenos inexplorados.

Foto principal: Geoffrey Arduini

The post BITes: ImageTragick, Windows95, metadatos, top, peligros DRM, software libre y más appeared first on Poesía Binaria.

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

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

DR-DOS

May 21, 2016 09:57 AM

Tal vez os cueste de creer, pero hubo una época en que mi espíritu tecnológico, se encontraba al margen de Microsoft, así que cuando descubrí DR-DOS 3.41 (1989), en una época en la que MS-DOS 3.30 ya llevaba un tiempo establecido, directamente me entusiasmé. Por aquel tiempo se me pasó por alto que DR-DOS pudiera [...]

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

Picando Código

Purism – la empresa que respeta tu libertad y privacidad presenta nueva tablet/laptop

May 20, 2016 09:20 PM

Purism es una empresa cuyos valores más importantes son la libertad y la privacidad del usuario. Hasta el momento la empresa contaba con dos modelos en el mercado, pero acaban de presentar su nueva Librem 11. La Librem 11 es una tablet desmontable/laptop 2-en-1 de 11.6 pulgadas. Presentaron también un modelo de 10 pulgadas, aunque se enfocan principalmente en la de 11.

Purism Librem 11

La tablet/laptop se puede obtener mediante una campaña de crowdfunding en Indiegogo. La tablet los acerca un poco más al objetivo final de producir un smartphone Librem.

Por defecto viene instalado con GNOME Shell y PureOS. PureOS solía basarse en Trisquel, la distribución GNU/Linux 100% libre, pero comenzó a basarse en Debian testing. El jefe de tecnología en Purism se acercó a Debian para conversar sobre imágenes OEM de Debian para sus máquinas. De esta forma, por cada computadora Purism que se venda Debian pre-instalado, Debian recibirá una donación.

Las especificaciones técnicas:

  • Funciona con cualquier distribución GNU/Linux fácilmente
  • 8GB, hasta 16GB RAM
  • Partes desacoplables y accesibles de actualizar
  • Teclado desmontable incluido
  • 6 a 8 horas de batería
  • Prototipo funcional, listo para producción masiva
  • Interruptor por hardware para matar:
    • Redes inalámbricas/Bluetooth
    • Cámara/Micrófono
    • GPS
    • Celular

Cada día aparecen más amenazas a nuestras libertades y privacidad desde las corporaciones y gobiernos. Purism entiende que los usuarios necesitan una alternativa a todas esas plataformas privativas. Por lo tanto sus productos apuntan a devolverle el control al usuario, dándole la libertad de usar el sistema operativo

Matriz de Control y Amenaza

Como mencionaba en el post anterior sobre Purism, espero que esta empresa siga creciendo y ojalá contagie a otras con sus prácticas y filosofía.

Más información sobre los modelos, formas de adquirirlos y especificaciones:

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

El blog de Adrián Arroyo

Programando para Haiku - BApplication, BWindow y BButton - Parte I

May 18, 2016 09:10 PM

Hoy voy a comenzar una serie de tutoriales donde explicaré la programación de una apliación en Haiku. Para ello vamos a usar C++ y la BeAPI. Siempre que tengais cualquier duda podéis visitar la documentación oficial: tanto la antigua de BeOS en el BeBook y la nueva de Haiku en Haiku API. Aun así hay APIs nuevas que todavía no aparecen documentadas. En ese caso hay que recurrir al código fuente.

Librerías en Haiku

Haiku (y BeOS) comparte con UNIX muchas características de bajo nivel. El tema de las librerías es uno de ellos. También han de empezar por lib y terminar por .so si son compartidas y .a si son estáticas. Para compilar también se usa GCC. Sin embargo hay una pequeña diferencia con el resto de sistemas UNIX. En UNIX normalmente disponemos de una librería del C, libc y una librería de funciones matemáticas, libm. En Haiku no existe libm, en cambio existen muchas más, libroot y libbe, para interactuar con el sistema de manera básica, libtracker, con funciones relacionadas con el explorador de archivos, libnetwork y libnetapi, con funciones de red, y muchas otras.

Además la API se divide en Kits, cada Kit se encarga de una tareas diferentes dentro del sistema operativo. AppKit, Game Kit, Interface Kit, Media Kit, Storage Kit, etc… Si queremos usar la funcionalidad de un kit tendremos que revisar que hemos añadido la librería correcta al compilador y que hemos añadido #include dentro del código que lo usemos.

Un hola mundo

Vamos a empezar por lo simple, una aplicación que muestre una ventana y ya.

Creamos un archivo de C++, será el punto de inicio de nuestra aplicación. Como sabéis, el punto de inicio de un programa de C o C++ es la función main.

int main(int argc, char** argv)
{
	AplicacionPrueba app;
    return app.Run();
}

Hemos creado un objeto llamado app del tipo AplicacionPrueba y después hemos ejecutado la aplicación. AplicacionPrueba tiene que ser del tipo BApplication. Es la clase básica de todas las aplicaciones Haiku/BeOS. BApplication provee de mensajería entre los distintos procesos del programa (hay que tener en cuenta que BeOS se diseñó pensando en el multiproceso). Vamos a ver como definimos AplicacionPrueba

#include <AppKit.h>

class AplicacionPrueba : public BApplication {
	public:
    	VentanaPrueba* ventana;
    	AplicacionPrueba() : BApplication("application/x-applicion-prueba"){
        	ventana = new VentanaPrueba();
            ventana->Show();
        }
};

Las Application necesitan un MIME type, al igual que se usa para indicar los tipos de archivo. No es necesario que sea real. Además hemos creado un objeto VentanaPrueba y la mostramos. VentanaPrueba es del tipo BWindow y es la ventana básica de Haiku, lo que vemos. Veamos la definición:

class VentanaPrueba : public BWindow{
	public:
    	VentanaPrueba() : BWindow(BRect(100,100,900,700),"Mi ventana", B_TITLED_WINDOW,0){
         // iniciar ventana
        }
        bool QuitRequested(){
        	be_app_messenger.SendMessage(B_QUIT_REQUESTED);
            return BWindow::QuitRequested();
        }
        void MessageReceived(BMessage* msg){
        	switch(msg->what){
            	default:
                	BWindow::MessageReceived(msg);
            }
        }
};

BWindow necesita un tamaño, que es indicado con BRect, un título, un estilo (por defecto es B_TITLED_WINDOW, pero podemos tener ventanas sin bordes o modal) y opciones varias. En las opciones varias podemos especificar que al cerrar la ventana se cierre la aplicación (B_QUIT_ON_WINDOW_CLOSE), que el usuario no pueda cambiar su tamaño (B_NOT_RESIZABLE), que no se pueda minimizar (B_NOT_MINIMIZABLE) y otras opciones por el estilo.

Además dentro de la clase hemos definido dos funciones virtuales, es decir, que tienen implementación por defecto de la clase padre, BWindow, pero nosotros podemos modificar su comportamiento.

QuitRequested es llamada cuando algo pide el cierre de la ventana. El objeto global be_app_messenger es del tipo BApplication, pero está definido en todos los puntos de nuestra aplicación sin que nosotros hagamos nada. Gracias a este objeto podemos enviar mensajes entre procesos. En este caso enviamos el mensaje a la aplicación de B_QUIT_REQUESTED. Y luego llamamos a la función sin modificar.

MessageReceived es muy importante. Se encarga de procesar todos los mensajes que recibe la ventana. Para distinguir los mensajes (que son del tipo BMessage) tenemos que inspeccionar la propiedad what. Se trata de un valor de tipo uint32. Hay algunos ya definidos por el sistema como B_QUIT_REQUESTED pero nosotros podemos definir más. Veremos más tarde como. De momento simplemente devolvemos el procesado de mensajes a BWindow padre.

Con esto ya podemos compilar.

gcc -o AplicacionPrueba app.cpp -lbe -lroot

Añadiendo BView, BButton y BGroupLayout

Ahora vamos a añadir cosas a nuestra ventana sosa. Ponemos una vista dentro de la ventana. Las vistas en Haiku son muy potentes pero eso lo trataré en otro momento. A esa vista le añadiremos un botón.

VentanaPrueba() : BWindow(BRect(100,100,900,700),"Mi ventana", B_TITLED_WINDOW,0){
         // iniciar ventana
         BGroupLayout* sizer = new BGroupLayout(B_HORIZONTAL);
         BView* panel = new BView(Bounds(), NULL, B_FOLLOW_ALL_SIDES,
                           B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE |
                               B_FRAME_EVENTS | B_DRAW_ON_CHILDREN);
         panel->SetViewColor(220, 220, 220);
         panel->SetLayout(sizer);
         
         BButton* boton = new BButton("Hola Mundo",NULL);
         
         sizer->AddView(boton);
         AddChild(panel);
        }
        

Aquí hemos hecho varias cosas. Por una parte he creado un layout horizontal. Es decir, dispongo el espacio de la ventana de manera horizontal, según se vayan añadiendo elementos lo harán a la derecha. Esto no estaba en BeOS y es particular de Haiku, pero recomiendo usar este sistema pues permite realizar un responsive design. Creamos una vista o panel. Bounds() indica que cubra todo el espacio disponible. El resto son propiedades de la vista más o menos estándar. Con SetViewColor le podemos poner un color de fondo, y con SetLayout le aplicamos el layout previamente creado.

Creamos un botón, que es del tipo BButton. BButton tiene muchos constructores si revisais la documentación pero este es muy cómodo si usamos el sistema de layouts. Simplemente indicamos el texto que va a mostrar y el mensaje que envía. En este caso NULL pues no vamos a poner ninguno.

sizer->AddView() lo usamos para añadir el botón al layaout y AddChild para añadir la vista a la ventana. Puedes compilar.

Añadiendo eventos. Mensajería con BMessage. Diálogo con BAlert.

Vamos ahora a crear un evento para el botón. Cuando pulsemos el botón mostrará un mensaje al usuario.

Los eventos se realizan por el sistema de mensajería basado en BMessage y BHandler. Para crear un BMessage necesitamos un ID, que es del tipo uint32. Eso es lo mínimo y con eso ya serviría para este caso.

const uint32 MOSTRAR_DIALOGO = 1;

...

BMessage* msg = new BMessage(MOSTRAR_DIALOGO);
BButton* boton = new BButton("Hola mundo",msg);

...

Pero los mensajes pueden llevar información adicional de cualquier tipo. Por ejemplo si queremos añadir además una cadena de texto al mensaje usaremos AddString.

msg->AddString("NombrePropiedad","ValorPropiedad");

Podremos recuperar el valor en cualquier momento con FindString.

Ahora si vamos a MessageReceived podemos añadir código que gestione este tipo de mensaje.

        void MessageReceived(BMessage* msg){
        	switch(msg->what){
            	case MOSTRAR_DIALOGO:
                BAlert* alert = new BAlert("Hola", "Sabes pulsar el boton, eh?", "Sip");
                alert->Go();
                break;
            	default:
                	BWindow::MessageReceived(msg);
            }
        }

Con un simple case gestionamos el mensaje. Para mostrar un diálogo simple se puede usar BAlert. Es muy simple, indicamos el título, el contenido del mensaje y el texto del botón que aparecerá. Y con Go lo mostramos.

Esta ha sido la primera parte del tutorial. Os ha gustado. Hay algo que no haya quedado claro. Comentádmelo.

#include <AppKit.h>
#include <InterfaceKit.h>
#include <Layout.h>
#include <GroupLayout.h>

const uint32 MOSTRAR_DIALOGO = 1;

class AplicacionPrueba : public BApplication {
	public:
    	VentanaPrueba* ventana;
    	AplicacionPrueba() : BApplication("application/x-applicion-prueba"){
        	ventana = new VentanaPrueba();
            ventana->Show();
        }
};

class VentanaPrueba : public BWindow{
	public:
VentanaPrueba() : BWindow(BRect(100,100,900,700),"Mi ventana", B_TITLED_WINDOW,0){
         // iniciar ventana
         BGroupLayout* sizer = new BGroupLayout(B_HORIZONTAL);
         BView* panel = new BView(Bounds(), NULL, B_FOLLOW_ALL_SIDES,
                           B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE |
                               B_FRAME_EVENTS | B_DRAW_ON_CHILDREN);
         panel->SetViewColor(220, 220, 220);
         panel->SetLayout(sizer);
         
         BMessage* msg = new BMessage(MOSTRAR_DIALOGO);
         BButton* boton = new BButton("Hola Mundo",msg);
         
         sizer->AddView(boton);
         AddChild(panel);
        }
        bool QuitRequested(){
        	be_app_messenger.SendMessage(B_QUIT_REQUESTED);
            return BWindow::QuitRequested();
        }
        void MessageReceived(BMessage* msg){
        	switch(msg->what){
            	case MOSTRAR_DIALOGO:
                BAlert* alert = new BAlert("Hola", "Sabes pulsar el boton, eh?", "Sip");
                alert->Go();
                break;
            	default:
                	BWindow::MessageReceived(msg);
            }
        }
};

int main(int argc, char** argv)
{
	AplicacionPrueba app;
    return app.Run();
}

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

Jesús Perales

Detector de incendios en base a video con javascript

May 18, 2016 08:33 PM

Detector de incendios en base a video con javascript

Los incendios en espacios pequeños como apartamentos, casas o edificios son advertidos mediante detectores de humo y detectores de calor y son efectivos, pero estos tienen muchos problemas al tratarse de espacios abiertos.

Una aproximación diferente es pasar el problema al terreno de la visión computacional, en el que se tratara de detectar el fuego y el humo a través de vídeo en tiempo real.

Crear un detector incendios en base a vídeo tiene la ventaja de cubrir un área más grande con una simple cámara y no hereda ninguna deficiencia de los detectores tradicionales.

Para hacer esto me decidí por Javascript ya que es el lenguaje de programación interpretado que conozco mejor y con el que me siento más cómodo para experimentar, por ser relativamente rápido trabajar con el.

El repositorio de código de este proyecto se encuentra en Github, en la siguiente liga.

En primera instancia se comenzó por una simple imagen con fuego

Detector de incendios en base a video con javascript

Para poder trabajar con la imagen teníamos que cargarla en nuestro HTML y después utilizar el elemento canvas que nos permitirá la manipulación de imágenes pixel por pixel.

Para definir si se ha encontrado fuego se utilizo un método muy sencillo que se basa en un diccionario de colores para decidir que es fuego y que no.

Las coordenadas del pixel se envía a un escuchador donde se busca definir cuatro puntos maximos y minimos en los ejes "X" y "Y" para dibujar un rectángulo al finalizar.

Se obtuvieron los siguientes resultados

Detector de incendios en base a video con javascript

Detector de incendios en base a video con javascript

Después de detectar el fuego en las imagen se paso a detectarlo en video, podemos decir que el video solo son muchas imágenes continuas.

El proceso es muy similar en video y en imágenes, se seguirá trabajando con el objeto canvas, pero en lugar de recibir una imagen y pasarla al procesamiento, se pasan muchas.

Hay que tener una función que ejecute el procedimiento N veces cada determinado tiempo, debido a que la detección del fuego en la imagen es lento se hizo cada segundo y se obtuvieron buenos resultados con la flama de un encendedor.

Detector de incendios en base a video con javascript

Detector de incendios en base a video con javascript

Técnicamente para pasar una imagen a canvas se utilizaba la etiqueta <img> pero ahora se utiliza la etiqueta <video> y una función de Javascript que obtiene el vídeo de la webcam mediante el objeto getUserMedia y después se refresca el elemento canvas en una frecuencia determinada.

Para aumentar la velocidad del procesamiento de las imagen se implementaron los Web Workers, el resultado de integrar esta tecnologia es un rendimiento muy superior en el procesamiento.

Caemos en la idea que al finalizar el procesamiento del video, solo son necesarios los 4 puntos para dibujar nuestro rectángulo.

Actualmente el proyecto solo es demostrativo, pero es posible llevarlo a mucho más agregando mejoras de algoritmos para tener un detector de fuego en video fiable y que no falle cada vez que pasamos algo rojo frente a el (xD) .

Entre las mejoras que podemos agregar serían:

  • Algoritmo de detección de movimiento.
  • Algoritmo de búsqueda profunda.
  • Incorporar el modelo de color HSV.
  • Detección de humo.

Estas ideas las obtuve al buscar en Github algunos proyectos relacionados, la mayoria estaban escritos en C++ o Python, quiza tengan un mejor rendimiento.

Una ventaja de mi proyecto es que puedes correrlo con tan solo descargarte el código, tener una webcam y abrir el archivo index.html en tu navegador.

Detector de incendios en base a video con javascript

¡Mira mamá sin compilar!

Nuevamente el repositorio del proyecto se encuentra aquí, quiza mas adelante haga una pagina web para este proyecto.

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

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

¿Por qué deberías quitar tu caché de WordPress?

May 17, 2016 08:33 AM

Una de las primeras cosas que se recomiendan tras instalar un WordPress es activarle un plugin de caché. Yo mismo lo hice y lo recomendé en mi configuración de WP. El caso es que tras configurar y optimizar CloudFlare, haciendo pruebas, me di cuenta que en realidad un plugin de cache, ya sea W3 Total [...]

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

Jesús Perales

Javascript ES6, Fetch API

May 16, 2016 05:36 PM

Javascript ES6, Fetch API

ECMAScript 6 (ECMAScript 2015 o ES6) nos trae muchas funcionalidades nuevas que nos facilitan la vida con el lenguaje al tener que desarrollar aplicaciones grandes.

Una de estas nuevas funcionalidades es la nueva Fetch API y vendría a reemplazar el objeto XHR( ¿alguien lo usaba realmente? ), esta pensada para trabajar con la búsqueda de recursos AJAX.

Lo anterior quiere decir que podremos hacer peticiones de recursos de una forma muy sencilla sin tener que depender de librerías de terceros como jQuery para hacer una petición GET, POST, etc.

Mucho ruido y poco código, veamos como llenaríamos las opciones de un select consultando una API REST con jQuery y como haríamos lo mismo con ES6.

jQuery:

ES6:

Realizar peticiones AJAX únicamente utilizando Javascript ahora es viable y no tenemos que utilizar una gran cantidad de código.

Para aprender mas de la Fetch API podemos consultar la documentación de MDN.

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

Koalite

Semantic logging: entre el logging y la analítica

May 16, 2016 05:06 AM

Una de las primeras cosas que aprendí cuando empecé a dedicarme profesionalmente a programar era que iba a necesitar una forma de diagnosticar errores, porque como tuviera que basarme en lo que me decían los usuarios (o en lo que yo intuía), lo llevaba claro.

Ello me llevó a poner siempre mucho cuidado en generar un buen log como primera herramienta de diagnóstico, y es algo que está entre las cosas que considero imprescindibles si desarrollas una aplicación.

Reconozco que siento predilección por los sistemas de logging simples, especialmente los ficheros de texto. La facilidad de acceder a ellos, de gestionarlos, de consultarlos y de compartirlos me resulta muy atractiva, pero sé que no escalan bien cuando tienes un volumen de información muy grande, por lo que no siempre pueden ser la única opción.

Además, no toda la información interesante de una aplicación es del mismo tipo. Por una parte, está bien saber qué está pasando (o qué ha pasado) para diagnosticar errores, pero también es útil poder auditar las operaciones individuales, obtener estadísticas de uso, de rendimiento, etc.

Entre todo este tipo de información, aparece lo que se conoce como semantic logging, a medio camino entre el log convencional puramente textual y una herramienta con más capacidades analíticas.

Un log estructurado

El logging semántico consiste en dotar de una mayor estructura a los eventos registrados en nuestro log. Ni más, ni menos. No es algo especialmente novedoso y hay muchos sistemas que ya hacían cosas similares, pero ya sabéis lo mucho que nos gusta ponerles nombres molones a las cosas para que parezcan más importantes.

En realidad, cualquier evento de un log ya tiene una cierta estructura. Como mínimo, suelen tener una fecha y hora de generación, un nivel de severidad y un mensaje, aunque es frecuente, especialmente si se utilizan sistemas como log4net o NLog, que podamos acceder a más información como el nombre de log o la hebra en la que se generó el evento.

El problema es que la parte realmente importante del evento, lo que ha pasado, no es más que una cadena de texto, por lo que poder tratarla de forma automatizada para explotar la información que contiene no es una tarea fácil. Al utilizar logging semántico intentamos resolver este problema haciendo que los eventos contengan, de forma estructurada, la información relevante para cada evento.

Por ejemplo, si tenemos un evento que representa el usuario ‘Paco’ ha aplicado el cupón de descuento ‘OFER25′, en un log semántico el evento llevaría asociada información parecida a ésta:

{
  severity: "INFO",
  timestamp: "2016-05-15T10:01:41",
  message: "El usuario 'Paco' aplicó el descuento 'OFER25'",
  action: "APPLY_DISCOUNT_CODE",
  user: "Paco",
  offerCode: "OFER25"
}

En lugar de limitarnos a almacenar un mensaje, añadimos información suficiente sobre el evento para tratarlo posteriormente. Así, podríamos obtener todos los descuentos aplicados por un usuario, o comparar las horas en que se aplican descuentos, etc.

Va un paso más allá del log tradicional cuyo objetivo principal es el diagnóstico, y aporta características propias de herramientas analíticas.

Aunque el evento del ejemplo esté representado en JSON, el concepto de log semántico es independiente de la representación elegida para los eventos y de la forma en que los almacenemos. Igual que pasa con sistemas de log tradicionales, que permiten almacenar el log en un fichero de texto, en un syslog o en una base de datos, cuando usamos un sistema de log semántico podemos optar por el sistema de almacenamiento que mejor se ajuste al uso que vayamos a darle después a la información.

Lo malo, claro, es que generar un log de estas características requiere más trabajo que ir escupiendo líneas de texto a un fichero.

Para empezar, si queremos que la información almacenada sea útil, deberíamos dedicar algo de tiempo a pensar qué queremos hacer con ella y qué datos debería incluir cada evento de log. Necesitamos algo de planificación a priori.

Además, generar cada evento de log implica un esfuerzo mayor y, dependiendo del lenguaje de programación que estemos utilizando, puede ser más o menos incómodo. En lenguajes con tipado estático y mal soporte para estructuras de datos dinámicas (como Java), podemos necesitar mucho código para generar los eventos. Podemos crear clases concretas para representar cada evento (al estilo de lo que haríamos con eventos de dominio), pero el coste de desarrollo es aún mayor, y habría que ver si realmente compensa.

Simplificando el proceso con Serilog

Serilog es una librería para .NET que permite generar eventos con información estructurada de una forma muy simple y cómoda. La idea es sencilla: aprovechar el mensaje que escribiríamos en cualquier log de texto para extraer la información relevante en base al formato. Algo así:

log.Information(
   "El usuario {user} ha aplicado el cupón de descuento {offerCode}", 
   user.Name, 
   offer.Code);

Serilog utiliza una pequeña DSL similar a las cadenas interpoladas de C# 6 para obtener la información estructurada que se guardará junto al mensaje. En este caso, incluirá en el evento una propiedad user ligada al primer parámetro, user.Name, y otra propiedad offerCode asociada al segundo parámetro, offer.Code.

El enlace entre parámetros y propiedades no se basa en el nombre, sino en la posición de los argumentos, y existen varias maneras de elegir cómo se formateará la información. Dependiendo del tipo de valor podemos utilizar su método ToString(), serializarlo, etc.

Una vez generados los eventos serán enviados a los loggers que hayamos creado que, por supuesto, pueden ser jerarquizados, pueden añadir nuevas propiedades a los eventos que reciben, pueden filtrarlas… en fin, todo lo que esperarías de un sistema de logging.

Al igual que ocurre con los sistemas de logs más “tradicionales”, la forma de persistir la información es completamente ortogonal al sistema de logging, por lo que podemos asociar distintos destinos (sinks, en terminología de Serilog) a cada logger en función de nuestras necesidades.

No voy a entrar en detalles sobre cómo se utiliza Serilog porque su documentación es muy completa, y si estás familiarizado con cualquier libería de logging, todos los conceptos te resultarán muy familiares.

Lo que me ha parecido muy interesante de esta librería es lo fácil que resulta añadir información estructurada a los eventos del log sin tener que hacer un esfuerzo adicional muy grande.

Puede que no sea la opción más potente, pero es un buen paso intermedio hasta que estés seguro de que realmente puedes explotar esa información adicional y sacarle un rendimiento que compense el esfuerzo de generarla y almacenarla.

Conclusiones

Me ha pasado varias veces y es extremadamente frustrante. Falla un aplicación, hablas con el desarrollador y te dice que no tiene ni idea de lo que puede ser. Te ofreces a enviarle el log y te mira asombrado, él no usa de eso. Le preguntas que cómo puede diagnosticar el problema y pone cara de “a mi qué me cuentas, sólo tengo el mensaje de error y no es muy aclarativo”.

Como experiencia de cliente es nefasta, pero es que para el desarrollador tampoco es una situación agradable. Cuando hay un problema, lo mejor es tener herramientas para solucionarlo, y poder contar con un histórico de lo que ha pasado en la aplicación es fundamental (por no decir indispensable).

Si además utilizas un sistema de logging estructurado, puedes aprovecharlo para comprender mejor el uso real de tu aplicación, lo que te ayudará a decidir en qué partes debes hacer más o menos esfuerzo a la hora de desarrollar nuevas funcionalidades, corregir problemas, o incluso enfocar las acciones comerciales y de marketing.

Dar el salto de guardar el stacktrace de las excepciones a tener un sistema de análisis no siempre es fácil, y menos si quieres realmente sacarle partido a ese sistema de análisis (almacenar datos es mucho más sencillo que convertir esos datos en información accionable), pero en ocasiones merece la pena.

Librerías como Serilog son una manera de mejorar la información que obtenemos de nuestras aplicaciones sin que nos cueste demasiado. Si prefieres dormir tranquilo cuando haya problemas y además disfrutas con el porno de estadísticas, tal vez merezca la pena que te plantees su uso.

Posts relacionados:

  1. Mejorando el paso de parámetros entre controladores en AngularJS
  2. Paso de parámetros entre controladores en AngularJS

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

Blog Bitix

Qué es el concepto de Heap Pollution en Java

May 14, 2016 11:15 AM

Al trabajar con referencias de tipos genéricos, raw y arrays debemos conocer el concepto de Heap Pollution si no queremos que en algún punto del programa Java se produzca una excepción no esperada del tipo ClassCastException. No teniéndolo en cuenta nos encontraremos con un error de los más difíciles de depurar ya que la excepción solo nos dirá donde se produjo no donde se encuentra el código erróneo que lo provocó.

Java

La introducción de los tipos genéricos al lenguaje Java en la versión 5 hizo posible que pudiesemos parametrizar los tipos y que el compilador hiciese validaciones sobre ellos, también se permitieron eliminar muchos cast que hasta entonces eran necesarios al usar el framework de colecciones. Los tipos genéricos permiten evitar errores en tiempo de compilación, al mismo tiempo la eliminación de los cast hace el código más legible y más fácilmente refactorizable. Sin embargo, para mantener la compatibilidad con versiones anteriores se optó por hacer algunos sacrificios en la implementación de genéricos en pos de otros beneficios. Una situación potencialmente problemática es el denominado Heap Pollution.

El concepto de Heap Pollution consiste de forma breve (quizá inexacta) en que un tipo genérico contiene un objeto con un tipo que no le corresponde según su tipo genérico, con un ejemplo, que una lista del tipo List<String> contenga un Number entre sus elementos. Que un tipo genérico pueda contener un objeto que no sea de su tipo genérico es detectado en tiempo de compilación con los unchecked warning pero bajo algunas circunstancias se produce en tiempo de ejecución una excepción de tipo ClassCastException, si ignoramos las advertencias y nuestro código no es cuidadoso. Esto es posible porque en Java el tipado de los genéricos sólo está disponible en tiempo de compilación lo que significa que no son reified, el tipado genérico no está disponible en tiempo de ejecución como consecuencia del proceso conocido como erasure, al trabajar con referencias de tipo raw y genéricas hay que tener cuidado en las asignaciones y las advertencias del compilador.

Veamos en código las circunstancias bajo las cuales se pueden producir Heap Pollution. Un tipo List<String> puede asignarse a un List y luego añadir a esa List un Integer momento en el que el compilador nos avisa con un unchecked warning indicando que no puede validar que la lista raw siendo List un tipo genérico se le está añadiendo una referencia del tipo que debería tener, el compilador nos informa de que esa responsabilidad la tenemos nosotros. También podemos asignar un List a un List<Number>, en este caso el compilador tampoco puede validar que la List sea realmente un List<Number> y lo indica también con un unchecked warning. Ignorando estas adevertencias se produce un ClassCastException al acceder al elemento Integer que contiene la List<String> como se comprueba en los teses.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/51c3db8facfc286f2e87d908caf018d8/raw/MainTest-generics.java">MainTest-generics.java</pre></a></noscript>

Por otra parte en Java los arrays en tiempo de ejecución necesitan conocer el tipo reified que contendrá. Esto unido a que los varargs realmente se transforman en un array, el posible Heap Pollution se da también en los métodos que soportan varargs.

El compilador convierte los varargs de tipos genéricos de la siguiente forma:

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/51c3db8facfc286f2e87d908caf018d8/raw/Erasure-varargs.txt">Erasure-varargs.txt</pre></a></noscript>

En un método cuyo último argumento es un vararg y de tipo genérico puede producirse Heap Pollution como indica el compilaror, si estamos seguros de que no se puede dar este caso en el código del método podemos eliminar la advertencia del compilador añadiendo la anotación @SafeVarargs en el método. Añadir la anotación solo implica que el compilador eliminará la advertencia pero aún con ella puede seguir produciéndose la excepción ClassCastException si el método no ha sido cuidadoso.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/51c3db8facfc286f2e87d908caf018d8/raw/MainTest-varargs.java">MainTest-varargs.java</pre></a></noscript>

Tener en cuenta el Heap Pollution es importante ya que la excepción ClassCastException se produce más tarde y en un punto diferente de donde realmente está el error, mucho más tarde si el tipo genérico es serializado e incluso en otra JVM diferente. Estos errores son de los peores de depurar por la poca información que proporcionan ya que la traza de la excepción solo dice quien la lanzó no donde se introdujo el fallo.

La implementación de los generics en Java viene con la garantía conocida como cast-iron que consiste en que mientras el compilador no produzca una unchecked warning en tiempo de compilación se garantiza que en tiempo de ejecución no se producirá una ClassCastException por los cast introducidos en el proceso de erasure.

Si nos encontramos con una de estas excepciones con los genéricos en una colección una buena alternativa es hacer uso de los métodos Collections.checkedCollection, Collections.checkedSet, Collections.checkedMap y alguno más similar que evitará que en una colección se produzca Heap Pollution, la excepción ClassCastException se lanzará en el momento de añadir a la colección la referencia que provocaría el Heap Pollution.

Relacionados con casos de combinar genéricos y arrays y ClassCastException en el libro Java Generics and Collections se definen dos principios a seguir para evitar excepciones: The Principle of Truth in Advertising y The Principle of Indecent Exposure.

Salvo que hagamos operaciones complicadas entre genéricos de diferentes tipos no será muy habitual que nos encontremos ClassCastException por Heap Pollution, pero es un concepto interesante conocer, en cualquier caso el compilador nos informará con los unchecked warnings.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew test.

Referencia:
Tutorial sobre los tipos genéricos de Java
Novedades y nuevas características de Java 8
Introducción y nuevas características de Java EE 7
Heap Pollution

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

Blog Bitix

La clase ThreadLocal de Java y usos prácticos

May 14, 2016 11:00 AM

En Java existe una clase con la que podemos asociar un dato al hilo o thread que ejecuta el código. Podemos usar esta clase para evitar incluir en cada método el parámetro de ese dato si es usado en multitud de métodos simplificando en gran medida el código. En las aplicaciones web este dato puede ser el usuario que se ha autenticado, el dominio por el que se ha accedido a la aplicación, el dispositivo móvil, el idioma del usuario o cualquier otra información que queramos esté disponible de forma global en el hilo de ejecución.

Java

En algunos casos nos encontramos con que un determinado dato lo pasamos como parámetro en sucesivas llamadas a métodos, obligándonos a declararlo en cada uno de ellos. En una aplicación web el dato podría ser el usuario autenticado, el dominio por el que se ha accedido a la aplicación, el dispositivo móvil, el idioma del usuario, su preferencia de divisa o cualquier otra información no relativa al usuario pero que igualmente la aplicación necesita en muchos sitios y usa esta información contextual para variar su funcionalidad. En una aplicación web podemos obtener el dominio por el que es accedido la aplicación con la clase Request, asociando el dato como un atributo de la petición lo tendremos disponible de forma global en la capa de presentación. Sin embargo, este objeto request solo estará disponible en la capa de presentación de la aplicación con la intención de que la capa de lógica de negocio sea independiente de la tecnología o framework web. Para hacer que algún dato global también esté disponible en la capa de lógica de negocio podemos usar la clase ThreadLocal.

La clase ThreadLocal básicamente asocia un dato con el Thread que ejecuta el código, teniendo una variable global en la aplicación con la referencia a la clase ThreadLocal podemos acceder al dato desde cualquier punto de la aplicación. Si necesitásemos varios datos tendríamos varias instancias globales de ThreadLocal.

Las variables globales es algo a evitar pero para algunos datos podemos hacer una excepción ya que entendemos que las ventajas son mayores que las desventajas, uno de los mayores peligros de las variables globales es la concurrencia si varios hilos modifican el dato global, como el dato asociado a ThreadLocal es local al hilo no hay peligro, simplemente deberemos asegurarnos de que una vez el hilo de ejecución termine limpiar el dato para que la siguiente petición en una aplicación web que procese ese hilo no use una dato anterior de otra petición.

La clase ThreadLocal es bastante simple tiene un método para establecer el dato con set, para obtenerlo con get, para eliminarlo con remove y desde Java 8 para establecer el valor inicial con una interfaz funcional Supplier con el método withInitial.

Veamos un ejemplo en el que crearemos un filtro que detecte el dominio por el que se accede a la aplicación y lo deje disponible en una variable ThreadLocal de modo que la aplicación lo tenga disponible desde cualquier capa de la aplicación. Primero crearemos una clase con variables estáticas globales que contendrá la referencia a la instancia ThreadLocal.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c8af01d1fb19ee3b266c01e0256ff3bc/raw/Globals.java">Globals.java</pre></a></noscript>

A continuación el filtro que obtiene el dominio de la request y lo deja en el ThreadLocal de forma global. Al usar una clase ThreadLocal es importante limpiar el dato correctamente, en este caso usando un bloque try con su finally para que aunque se produzca una excepción el dato acabe desasociado del thread al finalizar la petición, de lo contrario tendremos una fuga de memoria.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c8af01d1fb19ee3b266c01e0256ff3bc/raw/AppFilter.java">AppFilter.java</pre></a></noscript>

Finalmente, podemos acceder al dato desde cualquier punto de la aplicación, en este caso desde la capa de presentación en la página Index de una aplicación usando Apache Tapestry y desde la capa de lógica de negocio o servicios que es independiente de la capa de presentación.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c8af01d1fb19ee3b266c01e0256ff3bc/raw/Index.java">Index.java</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c8af01d1fb19ee3b266c01e0256ff3bc/raw/DefaultJooqProductoDAO.java">DefaultJooqProductoDAO.java</pre></a></noscript>

Con el filtro y las anteriores clases en la consola se imprimirán los mensajes con el dominio por el que ha sido accedida la aplicación, en este caso localhost.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c8af01d1fb19ee3b266c01e0256ff3bc/raw/System.out">System.out</pre></a></noscript>

En definitiva, en ciertos casos el uso selectivo de ThreadLocal simplifica el código evitando incluir un parámetro en multitud de métodos y si el dato ha de recuperarse de la base de datos evita realizar la misma consulta varias veces haciendo el programa más eficiente.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew run.

Referencia:
Alternatives to Global Variables

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

Jesús Perales

Repositorios privados ilimitados en Github

May 12, 2016 02:41 PM

Repositorios privados ilimitados en Github

Ayer por la mañana (El 11/05/2016) recibí un correo de parte de Github en el que se me informa que ahora tengo repositorios privados ilimitados para mi cuenta personal.

Así sera mientras siga siendo estudiante ya que como lo había mencionado antes tengo el Github Student Developer Pack.

También decir que el precio por tener en tu cuenta personal repositorios ilimitados privados es de $7 dolares por mes.

Repositorios privados ilimitados en Github

Anuncio oficial en el blog --> aquí

Liga a Github Student Developer Pack --> aquí

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

Picando Código

¡Salva a Firefox!

May 12, 2016 01:00 PM

Save Firefox

Había una vez, dos navegadores web principales que usaba virtualmente todo el mundo: Netscape e Internet Explorer, atrapados en una batalla a muerte por el futuro de la Web. Hicieron grandes esfuerzos para tentar a los editores web a optimizar sus sitios para que funcionaran mejor dentro de sus ventanas, y esperaron que los usuarios fueran los siguientes.

Después, un cambio en el terreno del juego: el navegador abierto, sin fines de lucro Mozilla emergió de Netscape, con la misión de poner a los usuarios, no a los editores, a cargo. Mozilla bloqueaba los anuncios pop-up por defecto, la peste de los primeros días de la web. Fue un paso que ninguno de los navegadores importantes podía permitirse tomar, porque los editores estaban convencidos que quedarían en quiebra sin ellos, y cualquier empresa cuyo navegador bloqueara los pop-ups por defecto alienaría a los editores, quienes se alinearían con la competencia.

Poco más de una década más tarde, y el mundo de los navegadores es irreconocible: Mozilla se transformó en Firefox; Internet Explorer se transformó en Edge, Apple lanzó Safari, y Google lanzó Chrome. ¡Cada uno de ellos bloquea los pop-ups por defecto! Literalmente ninguno de los navegadores dominantes de hace una década están en uso hoy.

Lo que no quiere decir que no haya competencia. La hay, y es tan feroz como siempre, y como siempre, es una lucha estratégica para favorecer tanto a editores como usuarios, cuyos intereses no son siempre los mismos. Los editores quieren recolectar más información sobre los usuarios; los usuarios quieren mantener su información privada. Los editores quieren controlar la experiencia visual y de navegación de los usuarios; los usuarios quieren sentarse en el asiento del conductor.

Necesitamos competencia; también necesitamos diversidad. Necesitamos la posibilidad de que aparezcan participantes jóvenes que cambien el terreno de juego en el mercado. Necesitamos que esa idea se mantenga viva, para asegurarnos que todos los navegadores no cambien su rumbo de mantener a los usuarios felices a simplemente mantener felices a unas pocas corporaciones gigantes que dominan la Web. Porque siempre hay presión para hacer eso, y si todos los navegadores terminan jugando ese mismo viejo juego, los usuarios siempre van a perder.

Necesitamos más Firefoxes.

Necesitamos más navegadores que traten a sus usuarios, en vez de a los editores, como sus clientes. Es el ciclo natural de concentración-ruptura-renovación que ha mantenido a la Web palpitando por casi 20 años (eones, en años-web).

Puede que nunca obtengamos otro, sin embargo.

El World Wide Web Consortium (W3C), una vez la fuerza por los estándares abiertos que evitó que los navegadores trancaran a los editores a sus capacidades privativas, ha cambiado su misión. Desde 2013, la organización ha proveído un foro donde las compañías de los navegadores dominantes de hoy y las compañías de entretenimiento dominantes puedan colaborar en un sistema que le permita a nuestros navegadores controlar nuestro comportamiento, en vez de a la inversa.

Este sistema, “Encrypted Media Extensions” (EME) usa código definido por estándares para canalizar video en un contenedor privativo llamado “Content Decryption Module”. Para que un navegador nuevo soporte este nuevo estándar de transmisión de video — el cual está siendo impulsado por los grandes estudios y operadores de cable — tendría que convencer a esas compañías de entretenimiento o uno de sus socios permitirles tener un CDM, o esta parte de la Web “abierta” no se mostraría en su nuevo navegador.

Esto es lo opuesto a cada estándar de la W3C hasta la fecha; en algún momento, todo lo que necesitabas para presentar contenido enviado por un servidor era seguir el estándar, no obtener permiso. Si los navegadores hubiesen necesitado permiso para representar una página en el lanzamiento de Mozilla, los editores hubieran congelado este nuevo advenedizo que bloqueaba pop-ups. Dale un beso de despedida a Firefox, en otras palabras.

La W3C no tenía que hacer esto. Ninguna ley de derechos de autor dice que hacer un video te da el derecho de decirle a la gente que lo mira legalmente cómo deben configurar su equipamiento. Pero por el diseño de EME, los dueños de los derechos podrán usar la ley para cerrar cualquier navegador nuevo que intente representar el video sin su permiso.

Eso es porque EME está diseñado para gatillar responsabilidad bajo la sección 1201 del Digital Millennium Copyright Act (DMCA), el cual dice que quitar una tranca digital que controla acceso a trabajo con derechos de autor sin permiso es una ofensa, incluso si la persona quitando la traba tiene derecho al contenido que restringe. En otras palabras, una vez que un video es enviado con EME, una nueva empresa que lo destraba para sus usuarios puede ser demandada, incluso si los usuarios no hacen nada ilegal con ese video.

Propusimos que la W3C podría proteger a navegadores nuevos haciendo que sus miembros prometan no usar a la DMCA para atacar a nuevas entradas en el mercado, una idea apoyada por un grupo diverso de miembros de la W3C, pero el ejecutivo de la W3C nos denegó diciendo que el trabajo avanzaría sin garantías para la futura competencia.

Es incluso peor que a primera vista. La DMCA no está limitada a los Estados Unidos: El US Trade Representativa ha propagado reglas tipo-DMCA a virtualmente cada país que tenga negocios con Estados Unidos. Peor aún: La DMCA también está siendo usada regularmente por compañías para amenazar y silenciar a investigadores de seguridad que revelan defectos vergonzosos en sus productos. La W3C también rehusó requerirle a sus miembros que protejan a investigadores de seguridad que descubran fallas en EME, dejando a todo usuario Web vulnerable a vulnerabilidades cuya revelación sólo puede llevarse a cabo de manera segura si la compañía afectada decide permitirlo.

La W3C necesita credibilidad con la gente a quien le importa la Web abierta y la innovación para poder ser viable. Son sensibles a este tipo de crítica. Nosotros simpatizamos. Hay muchas personas buenas trabajando ahí, personas que genuina y apasionadamente quieren que la Web permanezca abierta para todos, y que sea segura para sus usuarios. Pero la organización ha tomado una decisión terrible cuando optó proveer un hogar para EME, y una peor cuando le rechazó a sus propios miembros y negó protección para investigación de seguridad y nuevos competidores.

Necesita oír de tí ahora. Por favor, comparte este artículo, y difunde el mensaje. Ayuda a que la organización W3C sea lo que estaba destinada a ser.

Traducción de:
Save Firefox! por Cory Doctorow en el blog de la EFF.
Disponible bajo una licencia Creative Commons CC BY 3.0 US

» 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