Quantcast
Channel: Planeta Código
Viewing all 2730 articles
Browse latest View live

Variable not found: Cambios en la denominación de variables de entorno de ASPNET Core

$
0
0
ASP.NET CoreVa un post rapidito, sólo para informar de un pequeño cambio que ha introducido ASP.NET Core RC2, recientemente lanzado, relativo al nombrado de variables de entorno de sistema operativo.

Desde RC2, los nombres de las variables de entorno de sistema operativo que permiten configurar ciertos aspectos, como definir si el entorno de ejecución es "Development" o "Production" usan ahora el prefijo "ASPNETCORE_":

Variable de entorno "ASPNETCORE_ENVIRONMENT" establecida a "Development" en las propiedades del proyecto

No es la primera vez que cambia, de hecho creo recordar tres o cuatro prefijos diferentes a lo largo de la vida del producto desde sus primeras betas, así que espero que esta sea la definitiva :)

Publicado en Variable not found.

Blog Bitix: Ofrecer contenido personalizado al usuario basado en su ubicación

$
0
0

Cuando navegamos por internet el navegador envía mútiple información sobre nosotros y algunas páginas web recopilan esa información y la procesan para ofrecer contenido personalizado que creen nos resultaría de interés. Contenido con mayor relevancia para el usuario mejora la experiencia de usuario y la páginas web mejorarán su ratio de conversión y facturación. La información que proporcionamos sin ser conscientes son las cookies, la dirección IP, el navegador que usamos, el sistema operativo, nuestra resolución de pantalla, la hora a la que accedemos a la página, … en base a ella y aunque la información está impersonalizada sirve para identificarnos como inequivocamente usuarios. Con la dirección IP y usando una base de datos es posible obtener al menos el país desde el que se accede a una web y muy posiblemente la ciudad.

Linux
GNU

Un usuario cuando navega por internet proporciona diversa información que las páginas web pueden utilizar para personalizar el contenido que le muestran. La información que el usuario proporciona es el navegador que utiliza, sistema operativo y dirección IP. Con las cookies las páginas web pueden almacenar información en su navegador que persista en varias sesiones. Amazon por ejemplo personaliza el contenido que ve el usuario cuando accede a la página de inicio mostrando diferentes categorías de productos en los que puede estar más interesado, por ejemplo, productos visitados en anteriores sesiones, relacionados o similares. Si el usuario ha visitado un producto con anterioridad es muy posible que esté interesado en comprar ese producto con lo que Amazon se lo muestra de nuevo en la siguiente sesión o le envía un correo electrónico al día siguiente como recordatorio. Una página de eventos, viajes, hoteles, restaurantes, museos, el tiempo, … puede mostrar información basada en la localización, por ejemplo, si alguien está en Madrid quizá esté interesando dependiendo de la búsqueda que haga en eventos, hoteles o museos en esa ciudad.

En Arch Linux al igual que en muchas otras distribuciones GNU/Linux hay unos comandos y unos paquetes que contienen una base de datos que en base a la dirección IP proporciona el país, ciudad, código postal y coordenadas geográficas de latitud y longitud, son geoip con información del país y geoip-database-extra para obtener información de la ciudad. La localización de un usuario también puede obtenerse usando una consulta que implique red de datos hacia algún servicio y si el usuario en su navegador lo permite proporcionar la información de su geoposicionamiento, la diferencia es que la petición que haga uso de red añade algo de latencia a la respuesta de la aplicación tampoco requieren pedir permisos al usuario para activar su geoposicionamiento. La información proporcionada por geoip quizá no sea tan exacta en todos los casos que los anteriores métodos pero más que suficiente en la mayoría. En caso de querer la mejor precisión se puede optar primeramente pedir al usuario que comparta su localizacion mediante el navegador, luego o en la primera petición hasta que el usuario comparta su posición por usar la base de datos de geoip, si esta no es exacta aunque seguramente proporcione al menos el país pero no proporciona la ciudad se puede optar por usar algún servicio que implique red.

Instalados los paquetes con las bases de datos de geoposicionamiento en la distribución GNU/Linux su uso desde la línea de comandos es el siguiente, indicando la dirección IP o nombre de dominio de la que queramos conocer su ubicación:

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c521d486dd5740b5c9fa6144bde3bbc4/raw/geoiplookup-85.84.77.93.sh">geoiplookup-85.84.77.93.sh</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c521d486dd5740b5c9fa6144bde3bbc4/raw/geoiplookup-8.8.8.8.sh">geoiplookup-8.8.8.8.sh</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c521d486dd5740b5c9fa6144bde3bbc4/raw/geoiplookup-marca.es.sh">geoiplookup-marca.es.sh</pre></a></noscript>
Comando para obtener información de geoposicionamiento en base a la dirección IP

En una aplicación web Java en la interfaz ServletResquest y con el método getRemoteAddr() obtenemos la dirección IP del usuario, ya solo nos queda lanzar un proceso del sistema desde Java que invoque al comando geoiplookup con la dirección IP obtenida, obtener la salida del proceso, interpretarla y hacer con ella lo que queramos hacer en la aplicación. En la aplicación web adicionalmente somos libres de usar la API de geoposicionamiento implementada en los navegadores.

Proporcionar contenido personalizado al usuario probablemente ayuda a mejorar la conversión de un sitio de comercio electrónico y la experiencia del usuario ofreciéndole productos o servicios en los que de alguna forma esté interesado ya sea como en este caso basado en su ubicación, pero como en el caso de Amazon según las visitas anteriores y en otros podría ser en base al sistema operativo o navegador como hace Google cuando accedemos a su buscador indicándonos que nos instalemos Chrome si usamos Firefox.

Referencia:
Lanzar proceso del sistema con Java
Geolocation_software
W3C Geolocation API

El blog de Adrián Arroyo: Programando para Haiku - File panel - Parte II

$
0
0

Continuamos los tutoriales de programación en Haiku. Hoy veremos como usar el File Panel. ¿Qué es el File Panel? El File Panel es el diálogo que nos aparece cuando queremos abrir o guardar un archivo o carpeta. En todos los sistemas operativos gráficos es similar.

File Panel de Windows

BFilePanel

La clase básica es BFilePanel. Esta clase se encarga de mostrar esa ventanita que nos deja elegir el archivo o carpeta para abrir o para guardar. Lo primero que tenemos que saber si queremos hacer un File Panel es si va a ser para abrir un archivo existente o para guardar un nuevo archivo. Así, distinguimos entre B_OPEN_PANEL y B_SAVE_PANEL. Si estamos dentro de un B_OPEN_PANEL además indicaremos si aceptamos archivos, carpetas, enlaces simbólicos o alguna combinación de estas cosas. Por último, ¿cómo recibimos la información del panel? Pues usando BMessage, como es habitual en Haiku/BeOS. Pero hay que indicar quién va procesar el mensaje, el conocido como BMessenger. Veamos código:

constuint32OPEN_FILE=42;BFilePanel*filepanel=newBFilePanel(B_OPEN_PANEL,newBMessenger(this),NULL,B_FILE_NODE,newBMessage(OPEN_FILE));filepanel->Show();

En este código creamos un file panel para abrir un archivo. El BMessenger encargado de procesarlo será el del mismo contexto en el que se ejecute este código. Hay que tener en cuenta que tanto BApplication como BWindow heredan de BMessenger y por tanto cualquier objeto de estas clases es apto. El siguiente parámetro es la carpeta por defecto, que con NULL la dejamos a elección de Haiku. Luego indicamos que queremos abrir archivos, no carpetas ni enlaces simbólicos. Por último especificamos el ID del BMessage que enviará el panel. Esto nos servirá para después saber que ID tenemos que leer dentro de la función MessageReceived del BMessenger. Por último mostramos el panel para que el usuario decida el archivo a abrir. Si la acción es cancelada también será disparado el mensaje, tendremos que comprobar si el usuario eligió el archivo o cerró el diálogo.

Haiku File Panel

Leer la respuesta

Dentro de la función MessageReceived del BMessenger tenemos que accionar un caso especial si el ID del BMessage es el que hemos especificado en el panel.

voidMiVentana::MessageReceived(BMessage*msg){switch(msg->what){caseREAD_FILE:{if(msg->HasRef("refs")){entry_refref;if(msg->FindRef("refs",0,&ref)==B_OK){BEntryentry(&ref,true);BPathpath;entry.GetPath(&path);std::cout<<"El archivo es "<<path.Path()<<std::endl;}}break;}}}

Tenemos que comprobar si el mensaje tiene la propiedad “refs”. La propiedad “refs” la ajusta el File Panel cuando se ha seleccionado un archivo. Si la propiedad existe entonces lo leemos. Leeremos una entry_ref. Un entry_ref es una entrada dentro del sistema de archivos. Sin embargo esta estructura es de bajo nivel y no sabe exactamente donde se ubica. BEntry representa localizaciones dentro del sistema de archivos. Se construye con un entry_ref y esta clase ya sabe donde se ubica de forma legible por un humano (o un programador perezoso). Si queremos saber la ruta del archivo antes tendremos que crear un objeto vacío BPath que llenaremos con contenido. Finalmente la ruta, como string, la podremos leer llamando a la función Path dentro del objeto BPath.

Ya hemos visto como se usan los file panel en Haiku. Los file panel de guardar archivo se programan exactamente igual cambiando esa pequeña flag al principio.

Variable not found: Y el ganador del sorteo del curso de ASPNETMVC 5 en CampusMVP es…

$
0
0
Sorteo de Curso de ASP.NET MVC 5 en CampusMVPDe nuevo, mi generador de números seudoaleatorios ha introducido su inocente mano virtual en el bombo y ha elegido al afortunado ganador del sorteo del curso de ASP.NET MVC 5 en CampusMVP.

And the winner iiiiiis… momentos de emoción... redoble de tambores…

Adrián LópezAdrián López @aldacosta
Santiago de Compostela (Spain)

¡Enhorabuena, Adrián! En breve nos pondremos en contacto contigo y te daremos instrucciones para comenzar a disfrutar del premio cuanto antes :)

Muchas gracias a todos por participar, y por supuesto, a CampusMVP por el gran apoyo prestado en los preparativos y difusión de esta iniciativa.

Y chicos, estad atentos porque esto no acaba aquí, y en un par de días comenzamos un nuevo sorteo :) Mientras tanto, daos prisa si aún no habéis descargado vuestro libro de regalo de O'Reilly, que van quedando pocas semanas para el cierre!

Publicado en Variable not found

Blog Bitix: Moment.js, librería JavaScript para fechas

$
0
0
JavaScript

Hace un tiempo escribí una serie de artículos mostrando el uso de varias de la librerías de JavaScript, el primer artículo fue sobre una introducción sobre RequireJS hasta un Ejemplo lista de tareas con Backbone y React pasando por otra serie de herramientas útiles en una aplicación que tiene una parte importante en el navegador como:

En este artículo comentaré otra librería de JavaScript que nos será de utilidad para el trabajo con datos de tipo fecha en el navegador, la librerías es Moment.js.

La librería Moment.js permite en el lado del cliente formatear fechas según un patrón, manipular fechas añadiendo o restando días, comparar fechas, hacer consultas como si es un año bisiesto o la fecha está usando una zona horaria de verano o según calendario, soporta diferentes lenguajes además de permitirnos trabajar con diferentes zonas horarias y periodos de tiempo. En la propia página de inicio del proyecto y la sección de zonas horarias están incluidos diferentes ejemplos de cada una de estas posibilidades. El la documentación están explicadas más detalladamente todas las opciones, como usarlo con Require.js y el gestor de paquetes Bower o con npm.

En este artículo no incluiré un ejemplo de código ya que en la página de inicio del proyecto está muy bien explicado, la documentación parece bastante completa.

Referencia:
Moment.js

Variable not found: Enlaces interesantes 244

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

.Net

ASP.NET

.NET Core / ASP.NET Core

Azure / Cloud

Conceptos/Patrones/Buenas prácticas

Data

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Otros

Y para acabar, un divertido vídeo, real como la vida misma, sobre esos "listillos" que tenemos en nuestro interior y que nos ayudan mientras desarrollamos aplicaciones:



Publicado en Variable not found

Poesía Binaria: Instalar múltiples versiones de PHP y extensiones con phpfarm en Ubuntu/Mint/Debian…

$
0
0

photo-1441749074938-1c6782303919
Si llevas varios años trabajando con este lenguaje de programación. Tal vez se te ha presentado un pequeño problema: tienes varios desarrollos a lo largo del tiempo y tienes código en una versión de PHP antigua que no es compatible con versiones nuevas. Y, por otro lado, mientras mantienes una versión de producción de otro proyecto (para PHP 5.5 o PHP 5.6), quieres empezar a hacer pruebas para ver cómo se comporta con PHP7, y todo ello sin morir en el intento.

En mi día a día, muchas veces me enfrento a esa situación. Hay programas que no voy a tocar nunca, ni estoy dispuesto a ello, hechos con versiones antiguas de PHP y que ahora mismo están corriendo en PHP 5.3 sin problema. Son programas de esos que el día que me ponga con ellos, los quiero reescribir enteros, y lo voy dejando, lo voy dejando… aunque en ocasiones necesitan un arreglo (¡ no, un array no ! Un arreglo, de arreglar, o bueno, reparación, parche…) y tengo que poder ejecutarlos en local.

Entonces, en necesito constantemente en mi ordenador tres versiones instaladas, PHP 5.3, PHP 5.5 y PHP 7. Una solución puede ser crear máquinas virtuales o usar vagrant para cada uno de los proyectos. Aunque por un lado puedo desactivar máquinas y olvidarme de ellas cuando no están, incluso tenerlas en un disco duro externo para que no estén ocupando, por otro lado, necesito replicar varias veces un software que ya tengo (sistema operativo, servidor web, bibliotecas de sistem, etc), y todo esto consume disco, memoria y procesador cuando está cargado. Podría utilizar tecnologías como LxC o docker para utilizar en local estos servidores.

Yo opté por utilizar phpfarm y, aunque es un proyecto antiguo, hace lo que tiene que hacer: nos proporciona un entorno en el que compilar y utilizar distintas versiones de PHP de forma razonablemente fácil. Incluso se defiende bien para compilar las últimas versiones de PHP sin problemas.

Aunque los siguientes pasos puedan parecer muy complejos, lentos y costosos si no estás acostumbrado a compilar software en tu ordenador, es más sencillo de lo que parece. Esta instalación la he hecho en Linux Mint 17.3 Rosa, aunque debería funcionar sin problemas en Ubuntu y en Debian (si no tienes sudo, hazte root y quita el sudo).

Preparando el entorno para compilar PHP

Si has compilado algo anteriormente, seguramente ya tendrás instaladas las build-essential, pero para instalarlas:

$ sudo apt-get build-essential

Ahora, vamos a instalar algunas dependencias para compilar PHP, serán algunas bibliotecas que se requieren para poder realizar la compilación con éxito. Bueno, también he incluido git, ya que descargaremos phpfarm desde su repositorio de github

$ sudo apt-get build-dep php5
$ sudo apt-get install libmcrypt-dev libc-client2007e-dev git

Como servidor web voy a utilizar Apache 2.4 en modo CGI (podemos utilizar otras opciones), para ello debemos instalar también:

$ sudo apt-get install libapache2-mod-fcgid

Y activarlo

$ sudo a2enmod fcgid

Instalando phpfarm

Ahora clonamos el repositorio desde github. Yo lo he copiado todo en /opt/ (hace mucho que vi en una guía que alguien lo instalaba ahí y me gustó la idea, en lugar de hacerlo en un directorio de usuario). Así que todo lo que queda de tutorial lo haremos desde esa carpeta.

$ sudo git clone https://github.com/cweiske/phpfarm.git /opt/phpfarm

Los siguientes pasos se repetirán para cada una de las instalaciones que vayamos a hacer de PHP. Por lo que, para esta primera instalación lo pondré con más detalle, en las siguientes instalaciones iré un poco más rápido.

Configurando y compilando PHP

A mí me gusta hacer una configuración individual por cada versión de PHP que instalo, o al menos, hasta la versión menor. Por ejemplo, uno para PHP5.3, otro para PHP5.5 y otro para PHP7.0, a lo mejor necesitamos llegar hasta la revisión en alguna instalación puntual (5.5.19), pero bueno, tenemos la opción. Esta configuración irá en un archivo llamado custom-options.sh dentro de /opt/phpfarm/src . Si queremos:

  • Una configuración global para todas las compilaciones de PHP, utilizaremos custom-options.sh
  • Una configuración para todo lo que sea PHP 5 (5.1, 5.2, 5.3, …) usaremos custom-options-5.sh
  • Una configuración para todos los PHP 5.3 (5.3.1, 5.3.2, 5.3.10, …) usaremos custom-options-5.3.sh
  • Una configuración particular para una revisión en concreto (5.3.19) usaremos custom-options-5.3.19.sh

Además, este archivo no tiene por qué tener permiso de ejecución. En este archivo incluiremos las opciones que vamos a pasarle al configure de PHP. Es decir, los diferentes elementos a los que daremos soporte en nuestra compilación. Muchos serán los módulos que se incluirán (por ejemplo exif, gd, mbstring, ttf, openssl, pear…), un poco más adelante os diré cómo averiguar las diferentes opciones que soporta una versión de PHP. En este caso crearemos custom-options-5.3.sh con el siguiente contenido (delante de cada enable y cada with hay dos guiones seguidos – -):

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
# You can override config options very easily.
# Just create a custom options file; it may be version specific:
# - custom-options.sh
# - custom-options-5.sh
# - custom-options-5.3.sh
# - custom-options-5.3.1.sh
#
# Don't touch this file here - it would prevent you to just "svn up"
# your phpfarm source code.

configoptions="\
--enable-bcmath \
--enable-calendar \
--enable-exif \
--enable-ftp \
--enable-gd-native-ttf \
--enable-mbstring \
--enable-pcntl \
--enable-soap \
--enable-sockets \
--enable-wddx \
--enable-zip \
--enable-sysvshm \
--enable-sysvsem \
--enable-sysvmsg \
--enable-cgi \
--with-openssl \
--with-zlib \
--with-pear \
--with-pecl \
--with-gettext \
--with-imap \
--with-imap-ssl \
--with-kerberos \
--with-pdo-mysql \
--with-mysqli \
--with-mysql \
--with-curl \
--with-gd \
--with-jpeg-dir=/usr/lib \
--with-mcrypt"

Una opción interesante puede ser activar “–enable-fpm” si queremos configurar nuestro servidor con este soporte (experimental en 5.3), pero nos permitirá correr servidores de PHP que luego se podrán comunicar con nuestro servidor web.

El siguiente paso es compilar la versión de PHP que queremos. Para ello, nos situamos dentro de /opt/phpfarm/src y ejecutamos:

$ sudo ./compile 5.3.29

Esto trabajará solo un rato. Él sólo se descarga la versión elegida de PHP desde varias fuentes (según esté disponible), hace el configure, make y lo pone todo en su sitio. Normalmente si hemos seguido las instrucciones, debería terminar sin problemas. Aunque si os da algún problema debemos leer bien el error de la compilación. Muchas veces si buscamos el error en Internet nos dirá cómo solucionarlo, porque puede que nos falte alguna biblioteca por instalar o que haya algo mal escrito en el archivo custom-options.sh, aunque os animo a escribir un comentario con el fallo que os da a ver si entre todos lo podemos arreglar.

Configurar Apache

Ya tenemos la versión instalada. En este punto, de cara al servidor web, ya que haremos la configuración con CGI, crearemos dentro de /opt/phpfarm el directorio cgi-bin:

$ mkdir cgi-bin

y allí crearemos un archivo llamado php-5.3 (como root). Y, con un editor de texto (nano, gedit, vi, emacs…) añadiremos el siguiente contenido:

1
2
3
4
5
6
7
#!/bin/sh
PHP_FCGI_CHILDREN=3
export PHP_FCGI_CHILDREN
PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS

exec/opt/phpfarm/inst/bin/php-cgi-5.3.29

Si os fijáis, en la última línea ponemos la ruta del archivo ejecutable de php-cgi correspondiente a la versión que queremos configurar. Ahora configuraremos el VirtualHost de Apache añadiendo las siguientes líneas (ir a esta web para ver un virtualhost completo):
En el vhost incluir:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        <Directory /home/usuario/webs/miweb53/>
                Options +Indexes +FollowSymLinks -MultiViews +ExecCGI
                AddHandler php-cgi .php
                AllowOverride All
                AddHandler fcgid-script .php .php5 .phtml
                FcgidWrapper /opt/phpfarm/cgi-bin/php-cgi-5.3 .php
                FcgidWrapper /opt/phpfarm/cgi-bin/php-cgi-5.3 .php5
                FcgidWrapper /opt/phpfarm/cgi-bin/php-cgi-5.3 .phtml
                Require all granted
        </Directory>
        <Directory "/opt/phpfarm/cgi-bin">
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                AllowOverride None
                Require all granted
        </Directory>

Tras esto, sólo queda recargar la configuración de Apache:

$ sudo service apache2 reload

Ejecutable para PHP en línea de comandos

Esto será un simple enlace en /usr/local/bin (debemos asegurarnos de tener esta ruta en nuestro PATH, para ello, en consola podemos hacer $ echo $PATH). Con esto vamos a hacer que la ejecución de php-5.3 sea global en nuestro sistema:

$ sudo ln -s /opt/phpfarm/inst/php-5.3.29/bin/php /usr/local/bin/php-5.3

De la misma manera podemos crear enlaces a los diferentes ejecutables que hay en ese directorio.

Si además queremos que al ejecutar php (a secas, a nivel de sistema) se haga con esta versión:

$ sudo ln -s /opt/phpfarm/inst/php-5.3.29/bin/php /usr/local/bin/

Instalando APC con PECL

Una extensión que suele usarse mucho es APC como caché de código y datos. Y suele ser obligatoria en muchos scripts. Para instalarla, iremos a /opt/phpfarm/inst/php-5.3.29/bin/ y ejecutaremos:

$ sudo pecl install apc

Esto nos hará varias preguntas para configurar la extensión (podemos decir que sí a todo, o darle a enter), normalmente no suele haber problemas si la versión del módulo no es muy antigua.

Luego editamos /opt/phpfarm/inst/php-5.3.29/lib/php.ini e incluimos al final:

1
extension=apc.so

Instalando otras versiones de PHP

Yo instalo también otra versión la 5.5.35, para ello creo un custom-options-5.5.sh con un contenido muy parecido al anterior (eliminamos -with-pecl porque ya viene incluido y este flag no se reconoce):

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
# You can override config options very easily.
# Just create a custom options file; it may be version specific:
# - custom-options.sh
# - custom-options-5.sh
# - custom-options-5.3.sh
# - custom-options-5.3.1.sh
#
# Don't touch this file here - it would prevent you to just "svn up"
# your phpfarm source code.

configoptions="\
--enable-bcmath \
--enable-calendar \
--enable-exif \
--enable-ftp \
--enable-gd-native-ttf \
--enable-mbstring \
--enable-pcntl \
--enable-soap \
--enable-sockets \
--enable-wddx \
--enable-zip \
--enable-sysvshm \
--enable-sysvsem \
--enable-sysvmsg \
--enable-cgi \
--with-openssl \
--with-zlib \
--with-pear \
--with-gettext \
--with-imap \
--with-imap-ssl \
--with-kerberos \
--with-pdo-mysql \
--with-mysqli \
--with-mysql \
--with-curl \
--with-gd \
--with-jpeg-dir=/usr/lib \
--with-mcrypt"

Compilamos como antes:

$ ./compile 5.5.35

Cuando termine el proceso, instalamos APCU (nueva versión con compatibilidad con APC). Debemos asegurarnos de instalar la versión 4.0.10 que es la última compatible con PHP5.5:

$ sudo ./pecl install apcu-4.0.10

De la misma manera al final del fichero /opt/phpfarm/inst/php-5.5.35/lib/php.ini incluimos:

1
extension=apcu.so

De la misma manera, podemos configurar el VirtualHost que trabajará con PHP5.5 creando un lanzador en /opt/phpfarm/cgi-bin/php-5.5 y cambiando la ruta también en Apache, además, crear los enlaces a php-5.5 en /usr/local/bin.

Instalando PHP7

Por el momento, las opciones de compilación de PHP7 pueden ser las mismas que para PHP5.5, incluso podemos hacer:

$ sudo ./compile 7.0.6

sin problema (la 7.0.6 es la última versión estable a día de hoy, y no descarto que tengamos que modificar el custom-options.sh para futuras versiones). La configuración del virtualhost y los enlaces, todo se mantiene de forma similar a como veníamos haciéndolo hasta ahora.

Versiones de PHP que no se pueden descargar

Tal vez queramos instalar una versión antigua, o muy nueva (una RC por ejemplo), que ya no (o todavía no) está en los repositorios oficiales de PHP. Lo que podemos hacer es descargarla a mano en formato tar.bz2 y darle el siguiente nombre:

php-version.tar.bz2

Ese archivo lo copiamos en /opt/phpfarm/src/bzips luego podemos hacer el ./compile [version] como hasta ahora. Todo lo demás se mantendría igual.

Experimentos y otros detalles

Experimentar con las configuraciones

Ahora llega el momento de jugar. Por ejemplo, ¿qué otras opciones podemos darle a PHP para compilar? Esas famosas opciones para el configure. En esta guía, he puesto algunas opciones genéricas que en mi caso funcionan bien, pero tal vez necesites un módulo adicional, o soporte para alguna tecnología que utilizas. Para ello, viene bien saber todo lo que hay disponible. Eso lo podemos averiguar si después del ./compile estamos atentos y paramos el proceso (Control-C) una vez descomprimido el archivo descargado (si dejamos que se compile todo, simplemente tardaremos más). Una vez parado el proceso entramos en /opt/phpfarm/src/php-5.5.35 (o la versión que queramos) y allí ejecutamos:

$ ./configure –help

Será muy largo, por lo que tal vez quieras paginarlo con less o more:

$ ./configure –help | less

Esto implicará mucha lectura por tu parte para saber qué es cada cosa. Muchas veces, requerirá algo de búsqueda por Internet y, tal vez sea necesario instalar alguna biblioteca en el sistema antes de poder compilar. De todas formas, os animo a probar y a comentar vuestras configuraciones propias.

Varias versiones para un mismo proyecto

Puede que un proyecto ejecute normalmente con PHP5.5, pero que para ciertas operaciones intensivas utilice PHP7.0, es sencillo, podemos configurar el VirtualHost para que dos directorios diferentes utilicen versiones diferentes de PHP. Será Apache el que se encargue de hacer el cambio.

Cambiar la versión de PHP en consola

Para consola, podemos crear un enlace de la siguiente manera:

$ sudo ln -s /opt/phpfarm/inst/current-bin /usr/local/bin/php

y

$ sudo ln -s /opt/phpfarm/inst/switch-phpfarm /usr/local/bin/

De esta forma, podremos ejecutar:

$ sudo switch-phpfarm

y ver las versiones disponibles, y del mismo modo:

$ sudo switch-phpfarm 5.5.35

Para hacer que el ejecutable php a nivel de sistema sea el de la versión 5.5 (y cambiar de versión cuando queramos).

Foto principal: Evelyn Paris

The post Instalar múltiples versiones de PHP y extensiones con phpfarm en Ubuntu/Mint/Debian… appeared first on Poesía Binaria.

Mig Salazar: De Wordpress a Github

$
0
0

Dos años fueron necesarios para tomar la decisión; siempre tuve en mente que mis necesidades estaban cubiertas y no había mucho por hacer, hasta hace unas semanas. Por razones misteriosas, me decidí a colgar mis blog posts en algun repo de Github y recordé que hace tiempo había dejado pendiente el crear una personal start page en Github Pages. Pues todo o nada…

Así que he dejado mi blog en Wordpress.com para darle el beneficio de la duda a Github Pages. Sinceramente, me siento contento de este cambio, creo que fué la mejor decisión que pude tener respecto a esto.

Sabemos que Wordpress y Github Pages tienen objetivos/enfoques un tanto diferentes, pero para los fines del blogging y en terminos de elegir, creo que es prudente hacer una ligera revisión. Lo que menos deseo es que esta entrada se convierta en una comparativa, para eso hoy en día existen muchos post al respecto que se pueden encontrar rápidamente en Google; sin embargo y a pesar de esto, me gustaría mencionar las razones que me han llevado a realizar este cambio.

Warning: Todas las razones siguientes son gustos y perspectivas personales. Por hoy, dejaré a un lado la objetividad.

Razones

  • Jekyll: Simple, blog-aware, static sites. Definitivamente no necesito todo el peso de Wordpress; tener que cargar 1000E+1000 scripts para un simple post, hoy en día suena ridículo. Lo único que necesito es simple texto e imagenes, Jekyll me viene perfecto.
  • Markdown: Nada nuevo, pero suficiente para no hardcodear HTML para scrapear css de los templates en Wordpress =”)
  • WYSIWYG: Nunca podré ser fan de los editores WYSIWYG. Demasiado peso que le da el plugin/widget a la página de edición; se vuelve lento y complicado intercambiar entre vista HTML y Text. Al contrario en Github, las opciones son infinitas; cualquier notepad es útil. Personalmente disfruto mucho utilizando atom.
  • CSS: Aunque mi fuerte definitivamente no es el diseño, no significa que me parezca menos importante. En Wordpress, sentía estrés al entrar al wp-admin y saber que era necesario pagar para poder personalizar los temas. Si bien entiendo que los temas premium deben tener un costo -los diseños necesitan algo de financiamiento-, no veo la razón por la cual debo contratar un plan para modificar un free template. Al contrario en Github, tienes la mayoría del control de los archivos del sitio.
  • Hosting: Aunque no es necesario utilizar Wordpress.com y bien podemos instalar Wordpress.org en algun servidor y mantener control total de los archivos, Obviamente, se debe contratar un plan de hosting… pero si pudiera costear algún plan mensual, probablemente me cambiaría a Ghost. Asi que mejor con Jekyll, en Github es gratis.
  • Mapeo de dominio: Si bien no es costoso, para poder hacer hacer el mapeo sin un reedireccionamiento y que el https esté habilitado, se tiene que adquirir un servicio extra en Wordpress ($13 usd). Al contrario en Github, basta con configurar el archivo CNAME y listo; además, suponiendo que se desee aplicar HTTPS/SSL, podemos colgarnos de algún plan y servicio gratis de Cloudflare. Oye, de verdad que todo quieres gratis
  • SEO: Definitivamente Wordpress tiene un super SEO al instante, sin configuración mínima. Este punto es donde aún estoy algo corto para hacerlo efectivo en mi blog actual. Pero, bah… nada que no se pueda pulir; hoy estoy probando algo de Google Analytics, Google Webmasters y la misma consola para el indexamiento, además de esta gema
  • Plugins: Aunque es poco lo que he llegado a requerir de plugins en Wordpress, esto no debería detener. Existen montones de gems de Ruby para Jekyll que hacen y deshacen lo que se necesite al gusto.
  • Comentarios: Aquí existen varias opciones; yo he elegido Disqus-claro, es gratis-. Inicialmente opté por mantener el blog bastante minimal dado que Disqus no permite modificar el aspecto visual de su plugin. Pero al final, preferí incluirlo y mantenerlo oculto en un simple div. Aún así, bastante desventaja; Disqus es pesadísimo y dependiendo de la ubicación de la red en que nos encontremos, no estará accesible.
  • Redes sociales: Aquí Wordpress, debido a su naturaleza, se lleva al trofeo. Con simples clics, se pueden integrar muchas cuentas en redes sociales para crear un post al mismo tiempo en que se publica el artículo. Por esta parte no he indagado mucho al respecto, pero al menos estoy conforme con la gema para Twitter Cards, aunque bien se puede realizar a mano.
  • Repositorio: Definitivamente Github/GIT tiene mucho más peso aquí. Historial de commits, forks-pull requests, etc., nada mejor que tener versionado el sitio en general. Además, el flujo de trabajo con git es bastante simple y familiar.

En fin, trataré de organizar un poco mas la lista e ir agregando situaciones que vayan surgiendo así como enlaces útiles. Por lo pronto, por si no quedo claro… definitivamente me quedo con Github Pages =)


Mig Salazar: HTML5, Canvas y Matemáticas

$
0
0

Era finales del año 2008 cuando estaba por terminar mi tercer ciclo de carrera en la FCFM; en aquel entonces cursaba la materia “Programación Orientada a Objetos” haciendo uso del lenguaje JAVA y una de nuestras asignaciones finales era la de construir una pequeña aplicación donde se implementaran los temas del curso.

Mi aplicación básicamente trataba de un pequeño applet de JAVA que evaluaba y graficaba funciones matemáticas.

Hoy en día decir algo como “construiré un applet para implementarlo en la web” suena como “Te envío un SMS”¿Qué diablos es un SMS?. Así que he intentado explorar algunas alternativas…

Warning: El código siguiente solo funciona para explicar la idea de los pasos a seguir. El código completo se puede encontrar en este gist; es demasaido feo y necesita refactorizarse, solo debe tomarse como un prueba de concepto.

Canvas HTML5

Canvas es un elemento de HTML5 que nos sirve para dibujar “lineas” vía scripting (Javascript) en un navegador web. Al acceder a este elemento podemos hacer uso de un conjunto de métodos que nos ayudan a trazar elementos como lineas, cuadros, circulos, etc.

En w3schools podemos encontrar un tutorial completo para el manejo de canvas.

- Contexto

Primeramente necesitamos construir nuestro elemento en el HTML; a este elemento le asignamos propiedades básicas (id, ancho y alto), así como un pequeño mensaje en caso de que el navegador no tenga soporte para HTML5:

Con nuestro elemento canvas en el HTML, podemos acceder al contexto:

- Transformación

Un punto importante a mencionar es el trabajo con las coordenadas del canvas; desde el punto de vista del elemento canvas, visto como un rectángulo, el sistema de coordenadas tiene el punto orgien en el vértice superior izquierdo. Sin embargo, para el plano cartesiano requerimos que se encuentre en el centro. Asi que necesitamos trasladar este punto al centro.

En adelante, todos los puntos evaluados en la función deben ser calculados a partir del origen.

- Evaluar

Una vez con el contexto en memoria, se debe evaluar cada punto en la función a graficar. Los puntos a evaluar serán todas las x transformadas al origen del canvas.

Cada iteración del ciclo for evalua la x en la función f. Suponiendo que se desee evaluar una función , para valores :

Cada será el valor del eje y con esto generamos un conjunto de puntos:

- Trazar

A partir de este punto, podemos hacer uso de los métodos para el trazado. Para los fines, básicamente necesitamos los siguientes métodos:

  • beginPath(): Begins a path, or resets the current path.
  • moveTo(): Moves the path to the specified point in the canvas, without creating a line.
  • lineTo(): Adds a new point and creates a line to that point from the last specified point in the canvas
  • stroke(): Actually draws the path you have defined

El listado completo de métodos y propiedades, lo podemos encontrar en w3schools.

Agregando al código anterior los métodos para el trazado, se inicializa el contexto y en cada iteración construimos la línea del punto actual:

- Implementación

Como se puede ver en el último fragmento de código, para calcular la real se debe invocar el método f. Este método, se puede enviar como parámetro a la función que se encarga de generar la iteración, para tenerlo como parámetro a la hora de ser implementado. Algo como lo siguiente:

De este modo, plot será la función encargada de inicializar la gráfica; se le envía la función a evaluar y el rango sobre el cual se desea trabajar en el conjunto de las .

- Test

A este ejemplo le he hecho un ligero ajuste para animar la gráfica utilizando el método requestAnimationFrame, su documentación se encuentra aquí.

Conclusión

Definitivamente con javascript son muchísimas líneas de código menos que en JAVA y es un primer buen acercamiento con el trazado de formas en la web utilizando canvas. Aún así, me parece que da mejores resultados implementar este tipo de situaciones con SVG, quizá para un futuro post =)

Arragonán: Semanas 414, 415, 416 y 417

$
0
0

Casi un mes, nada menos que 4 semanas sin retro semanal, ahí es nada. La verdad que con tanto tiempo me ha costado tratar de recopilar lo hecho y resumirlo, han pasado muchas cosas en lo profesional y personal: Saraos, entrenamientos, celebraciones, no-celebraciones, partidos, cosas del día a día, algún viaje relámpago… hasta he sacado tiempo para hacerme cuenta en un servicio web de puretas que yo me sé. Pero bueno, en el acumulado ha ido bien la cosa :).

En estas semanas tuvimos por ahí en medio un Friday Dojo de Refactoring (que seguiremos este viernes). Nos sirvió como despedida del que ha sido el local de Hispalinux durante un porrón de años. Un local en el que han habido gran cantidad y variedad de eventos organizados por diferentes comunidades locales. He tenido que buscarlo, se inauguró en local nada menos que en 2006 y, aunque a temporadas ha estado algo parado, se le ha sacado mucho partido; pero bueno, seguiremos montando cosas en otros locales y espacios que nos cedan, eso seguro.

Con los CodingStones nos siguen saliendo cosas. Hemos cerrado con una Startup una colaboración a medio camino del mentoring y la consultoría, por el momento haremos una primera visita con algunas actividades y si todo va bien la colaboración se alargará en el tiempo. Mientras que por otro lado hemos trabajado con un par de posibles clientes para ver si encajamos para echarles una mano después del verano. Son 2 proyectos de temáticas muy diferentes, uno sobre trata movilidad y geolocalización mientras el otro combina arduinos y visualización de datos, ambos son relativamente pequeños y nos resultan muy atractivos.

Y aparte de algún side-project que se llevó algunos ratos de mi tiempo, estos fueron a grosso modo las cosas en las que trabajé:

  • En Outreach Tool estuve haciendo arreglos menores con vistas a algunos eventos de presentación de la metodología y la herramienta que da soporte. Ahora mismo la herramienta sigue siendo una hoja de cálculo bastante técnica que os podéis descargar cualquiera. Yo llevo un tiempo dándole vueltas a ver cómo podemos pasarlo a una aplicación web, mientras mis compañeros lo están rodando y van captando feedback.
  • Con los CodingStones hemos estado trabajando a tope en Conecta. Durante estas iteraciones hemos conseguido fortalecer una relación de confianza con el cliente, aportando cosas tanto en lo puramente técnico como en la visión de producto. Quizás no vayamos lo rápido que nos gustaría implementando funcionalidades, pero hemos puesto un estándar bastante alto en la calidad de lo que hacemos, tanto a nivel de código como de producto y por el momento vemos que el cliente lo percibe y valora. Como equipo también vemos que vamos mejorando poco a poco, el que tengamos todos una visión muy acorde con los valores y principios del Extremme Programming en mi opinión está facilitándolo mucho. Estamos sacando puntos de mejora muy interesantes en cada retrospectiva y revisión de código, incluso nos vamos inventado algunos artefactos un tanto locos para resolver ciertos escenarios que por el momento nos resuelven la papeleta.
  • También he ido dedicando algunos ratos a Mosica. En la parte de contenidos el mes de Mayo ha sido desastroso, no he dedicado apenas esfuerzo a ello. Mientras en la de desarrollo, he ido resolviendo algún problemilla que ha ido surgiendo, pero nada de los planes de evolución que tengo previstos hacer en algún momento.

Buena semana.

Variable not found: Nuevo sorteo: ¡componentes profesionales de Grapecity!

$
0
0
GrapeCityHasta ahora, con motivo de la celebración del décimo aniversario del blog, como decía un amigo del blog vía Twitter, hemos regalado conocimiento: un curso online de MVC en CampusMVP, unos cuantos libros de SignalR e incluso un libro a elegir de entre una selección de O'Reilly (libro que, por cierto, ¡aún podéis reclamar!).

Con este sorteo que iniciamos hoy, comenzamos una serie en la que repartiremos herramientas para desarrolladores que os ayudarán a ser más productivos y mejorar la calidad de vuestras aplicaciones :)

Certificado de premioSeguro que os suena Grapecity, la compañía que hay por detrás de componentes y herramientas de gran reputación como ComponentOne, Wijmo o ActiveReports. Pues tras ponerme en contacto con ellos para hablarles del décimo aniversario del blog, se ofrecieron amablemente para apoyar la celebración cediendo tres licencias completas de sus productos.

Para que os hagáis una idea del volumen de la apuesta, deciros que se trata en todo caso de productos comerciales cuyos importes pueden llegar a superar los 1.000 dólares cada uno ¡Uau! :)


Así pues, entre los participantes del sorteo elegiremos a los tres ganadores y les haremos llegar a cada uno un certificado como el que veis en la imagen anterior. Con este certificado podréis poneros en contacto con la compañía, elegir el producto que más os interese y os facilitarán una licencia de la versión completa del mismo.

Los productazos entre los que podréis elegir son los siguientes:

ComponentOne Studio

1ComponentOne Studio

Controles .NET para aplicaciones de negocio serias
Desarrolla para cualquier dispositivo, en cualquier plataforma con ComponentOne Studio. Con un juego de componentes de interfaz que cubren todas las plataformas de Visual Studio, incluyendo WinForms, WPF, ASP.NET, MVC, Xamarin, UWP, e incluso ActiveX, estarán cubiertas tus necesidades de desarrollo presentes y futuras.
Más información…
Wijmo

2Wijmo

Una nueva generación de controles Javascript
Desarrolla potentes aplicaciones de negocio con los controles HTML5 más punteros (Wijmo 5) o con los widgets clásicos para jQuery (Wijmo 3). Tanto si estás trabajando en aplicaciones móviles modernas o necesitas soporte para IE6, el conjunto de herramientas de Wijmo Enterprise te lo permitirá.
Más información…
Xuni

3Xuni

Ve a nativo. Ve a Xuni.
La colección de controles para móvil nativos y multiplataforma te permiten emplear las mismas API en iOS, Android y Xamarin utilizando programación nativa. Con Xuni, tendrás controles de alta calidad para el desarrollo de aplicaciones empresariales que proporcionan la misma experiencia en las distintas plataformas.
Más información…
ActiveReports

4ActiveReports

Informes en .NET para todas tus necesidades
Crea virtualmente cualquier tipo de informe con diseñadores integrados en Visual Studio, componentes, y un extenso API. Incluye visores libres de royalties para HTML5, WPF, WinForms y ASP.NET, así como un add-on opcional para servidores.
Más información…
Spread

5Spread

Componente de hoja de cálculo empresarial para .NET
El componente de hoja de cálculo más popular del mundo para por los desarrolladores de Visual Studio que desean incluir en sus aplicaciones WinForms, ASP.NET, WPF y WinRT avanzadas rejillas de datos y hojas de cálculo con funcionalidades similares a Microsoft Excel.
Más información…

¿Y cómo participo en el sorteo?

La forma de participar en este sorteo es muy parecida a la que hemos utilizado anteriormente, de forma que los que ya habéis participado apenas tendréis que hacer nada ;)

Los que estéis interesados en participar sólo tenéis que conseguir "papeletas"; cada uno de vosotros podéis conseguir hasta cuatro papeletas, dependiendo del grado de simpatía que mostréis con Variable not found ;) Obviamente, cuantas más papeletas consigáis, más probabilidades tendréis de ganar el premio.
  • 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, el que queráis. Podéis aprovechar para contarme cuál de los productos de Grapecity es el que os interesaría y por qué, o qué pensáis hacer las próximas vacaciones ;D El caso es comentar algo, lo que sea. 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 el 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 "com gmail arroba joselito".
Para que os quede más claro, este sería un ejemplo de comentario de un participante que sigue a Variable Not Found en todos sus perfiles posibles, por lo que participaría con todas las papeletas:
Hola, soy Roberto, y en las próximas vacaciones pienso ponerme como un tizón bajo las soleadas playas de Ibiza. Ah, y si me toca el sorteo creo que pillaré ComponentOne porque me vendría de fábula para desarrollar aplicaciones empresariales, que es lo que hago a diario.
Soy bertillo en gemail, con el consabido puntocom para finalizar.
+TW1+TW2+FB
No olvidéis incluir en el comentario los textos "+TW1", "+TW2", "+FB" para indicar los perfiles a los que seguís, pues tengo automatizado el proceso del sorteo y las papeletas se asignarán automáticamente en función de estas pistas incluidas en el comentario ;) Y aseguraos de que lo que indicáis es cierto, porque de no ser así seréis descalificados!

¿Cuándo se realiza el sorteo?

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

Ese día, una aplicación leerá automáticamente los comentarios del post y asignará papeletas en función de los perfiles seguidos (+TW1, +FB…). La aplicación elegirá al azar tres ganadores, y verificaré manualmente que sus papeletas sean correctas.

Tras ser confirmados, me pondré personalmente en contacto con los ganadores través de la vía que hayan indicado al participar. Si por cualquier motivo no fuera capaz de contactar con alguno de ellos en un tiempo razonable, su premio sería sorteado de nuevo entre los participantes.

Pues nada más, ¡¡apuntaos ya, que los regalos bien lo merecen!!

Publicado en Variable not found

Variable not found: App_Offline, también disponible en ASPNET Core

$
0
0
ASP.NET CoreUno de los cambios que ha introducido ASP.NET Core RC2 respecto a la anterior Release Candidate es que dejaremos de utilizar HttpPlatformHandler para redirigir las peticiones desde IIS hacia Kestrel que, como sabemos, es finalmente el que ejecuta nuestra aplicación.

El problema es que este componente era un redirector genérico, no ligado a ninguna tecnología concreta, lo que impedía el uso de algunas características interesantes o necesarias para la correcta ejecución de ASP.NET Core en todos los entornos, como el soporte para directorios virtuales de IIS o el reenvío de certificados de cliente.

Por esta razón, se ha optado por crear un módulo específico para correr aplicaciones ASP.NET Core sobre IIS, llamado AspNetCoreModule, que será a partir de ahora el proxy inverso que encaminará las peticiones hacia nuestra aplicación. De esta forma, ya ha sido posible añadir características específicas para ASP.NET Core, como el soporte para el clásico archivo "App_Offline.html", que podremos utilizar con total normalidad desde la RC2.

Si no habéis oído hablar de él, se trata de una característica disponible desde los tiempos de ASP.NET 2.0, que consiste en que cuando el framework detecta un archivo con ese nombre en la carpeta raíz de la aplicación web, ésta era "apagada" y todas las peticiones se respondían con el contenido de dicho archivo siempre que este cumpliera determinadas condiciones.

Esto era bastante útil para procesos de actualización, y de hecho las herramientas de despliegue habituales ya lo utilizaban para mostrar un mensaje del tipo "Web en mantenimiento, vuelva en un ratillo" mientras hacíamos un despliegue.

Podéis encontrar más información en el anuncio oficial en Github.

Publicado en Variable not found.

Variable not found: Por el aniversario de VariableNotFound, ¡O'Reilly te regala un libro!

$
0
0
¡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 regalando a todos los lectores del blog 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 XamarinMastering Cross-Platform Development with Xamarin
By Can Bilgin
Más info
C# 6 and .NET Core 1.0: Modern Cross-Platform DevelopmentC# 6 and .NET Core 1.0: Modern Cross-Platform Development
By Mark J. Price
Más info
jQuery EssentialsjQuery Essentials
By Troy Miles
Más info
C# 6.0 in a NutshellC# 6.0 in a Nutshell, Sixth Edition
By Joseph Albahari & Ben Albahari
Más info

CSS: The Missing ManualCSS: The Missing Manual, Fourth Edition
By David Sawyer McFarland
Más info
Learning NHibernate 4Learning NHibernate 4
By Suhas Chatekar
Más info
Learning .NET High-performance ProgrammingLearning .NET High-performance Programming
By Antonio Esposito
Más info
Code-First Development with Entity FrameworkCode-First Development with Entity Framework
By Sergey Barskiy
Más info
AngularJS: Up and RunningAngularJS: Up and Running
By Shyam Seshadri, Brad Green
Más info
Concurrency in C# CookbookConcurrency in C# Cookbook
By Stephen Cleary
Más info
RESTful Services with ASP.NET Web APIVí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 el aniversario de @variablnotfound, @oreillymedia me ha regalado un e-book. ¡Ve a por el tuyo! 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 adicionalmente todas las semanas estamos repartiendo regalos impresionantes :)

Publicado en Variable not found

Blog Bitix: La siguiente disrupción tecnológica, la convergencia

$
0
0

La tecnología no para de avanzar, cada varios meses salen noticias de avances importantes. Algunos avances se convierten en realidad, otros tardan más en llegar, otros llegan pero no triunfan y de otros pasado un tiempo no se vuelve a oír hablar de ellos. Algunos cambios aunque mejoran lo existente son leves sin añadir nuevas posibilidades ni cambian los comportamientos de los usuarios o como interaccionan estos con la tecnología. Otros pocos son disruptivos y cambian de forma significativa el mercado de la tecnología junto con sus usuarios, estos cambios novedosos son capaces de hundir empresas líderes si no saben adaptarse o no los prevén al mismo tiempo que crean nuevos líderes en el mercado.

En el mundo de la tecnología cada nuevo procesador, tarjeta gráfica, SSD y otros componentes de un dispositivo se presentan prometiendo mejoras significativas en rendimiento y/o consumo de energía habitualmente entre un 20% y 90% sobre la generación anterior. Las mejoras de los componentes aunque significativas no suponen una disrupción en la tecnología, simplemente la hacen más rápida. El caso de los procesadores, tarjetas gráficas o SSD es una muestra, estos nuevos sistemas de almacenamiento aunque suponen una gran mejora sobre los discos duros mecánicos con una mucho mayor tasa de transferencia no modifican de forma disruptiva la tecnología para el usuario, si el ordenador en vez de iniciarse en un minuto y medio tarda 15 segundos aunque el SSD suponga una mejora significativa en el rendimiento de los ordenadores no es más que esperar más o menos tiempo, es una pequeña disrupción para los usuarios aunque grande para los fabricantes.

De las disrupciones que estoy hablando son las cambian significativamente la tecnología, la aparición del ordenador personal y como los aprovechó Microsoft e IBM no supo o no pudo, la aparición de las interfaces gráficas cuando solo existía la línea de comandos o estaban basadas en texto e iniciaron el dominio de Microsoft y Apple en la informática de consumo, de la aparición de los teléfonos móviles en la que en una época Nokia era el líder y como con la aparición de los teléfonos inteligentes al no adaptarse o preverlo sucumbió al menos tal y como era, de como 3dfx no pudo competir con las GPU modernas que NVIDIA popularizó con gran éxito. Algunas disrupciones importantes no son instantáneas pueden tardar algún lustro pero sin las compañías líderes no las ven venir ni se adaptan cuando quieren darse cuenta ya es demasiado tarde llegando a desaparecer o convertirse en poco relevantes. Algunas tecnologías prometedoras no tienen el éxito esperado como las pantallas de televisión 3D o curvas, un porcentaje grande de otros casos siguen el mismo camino, ¿alguien ha dicho blu-ray?, ¿smartwatch?, …

MicrosoftAppleLinux

¿Cuál será la siguiente disrupción? Hacer cábalas sobre futuro es difícil y suele ser más propio del inicio de año pero aquí haré mi apuesta y a ver si acierto. En estos momentos hay varias novedosas que pueden cambiar significativamente el mundo de la tecnología una de ellas es la realidad virtual o la realidad aumentada de las holosens de Microsoft, muy de películas futuristas pero incómodas de usar para el usuario ya que requieren gafas en el caso de la realidad virtual que acaparan la visión y las holosens de Microsoft para la realidad aumentada no veo porque no vayan a seguir el mismo camino que las Google Glass, otro proyecto futurista de realidad aumentada es Google Tango que será un nuevo ámbito de acción para muchas empresas. De todas la que creo que más temprano que tarde llegará será la convergencia entre dispositivos móviles, tabletas, ordenadores e incluso smart tv.

Con la cada vez más capacidad de los dispositivos móviles que aumenta en un gran porcentaje en cada generación ¿cuando será el momento en que sean capaces de sustituir a otros dispositivos como ordenador y tabletas? Algunos móviles ya tienen 3 y 4GiB de memoria, sus procesadores más núcleos que un ordenador de escritorio, almacenamiento de 64GiB y 128Gib más que suficiente existiendo el almacenamiento en línea y externo para los dispositivos permanentemente conectados. Los procesadores de los dispositivos móviles ARM no está muy lejos del rendimiento de los procesadores de escritorio Intel Core ¿cuánto tiempo tardará en aparecer el primer ordenador de escritorio con procesador ARM? ¿Intel tiene que preocuparse por ARM? Yo creo que sí tiene que preocuparse por la convergencia en la que un procesador ARM no tardará mucho en tener suficiente capacidad (y II) para tareas básicas de escritorio mucho más barato de fabricar y más eficiente energéticamente. Intel hoy lidera la fabricación de procesadores de escritorio, ARM el diseño de procesadores de dispositivos móviles, la disrupción será que los procesadores ARM serán capaces de adentrarse en el escritorio e incluso en los servidores. ¿Apple en algún momento fabricará un MacBook con procesador ARM de los que ya incorpora personalizados en sus dispositivos móviles?

Los ordenadores de escritorio no se pueden transportar, los portátiles no pesan tanto siendo más manejables pero son incómodos y no acarrables en todo momento como los móviles por otro lado en los teléfonos inteligentes es incómodo escribir, copiar, pegar, trabajar con múltiples aplicaciones, navegar por internet y tiene una pantalla del alta resolución pero pequeña, digamos que hay una necesidad de unir ambos mundos que proporcione lo mejor de los dos. El ordenador de escritorio y portátiles de hoy serán irrelevantes salvo para algunos usuarios que requieran potencia extrema al igual que ocurre con las tarjetas gráficas dedicadas para jugadores exigentes, la convergencia hará que tengamos un único dispositivo para lo que hasta ahora utilizábamos varios para los casos de requerir mayor potencia surgirán dársenas o docks que proporcionen mayor capacidad gráfica y más opciones de conectividad. El smartphone sustituirá al ordenador de escritorio cuando podamos conectarlo a una pantalla externa junto con un teclado y ratón, el teléfono inteligente se convertirá en el dispositivo universal. El conector USB Type-C ya podría proporcionar la conectividad necesaria con pantallas, teclado, ratón y más dispositivos.

Cuando la diferencia entre el ordenador de escritorio y el dispositivo móvil sea poco significativa la convergencia será una realidad, cada año está más cerca no hay más que ver que ya hoy hay móviles con 4GiB de memoria la misma que algunos ordenadores de escritorio y portátiles de gama mediana y baja. Solo falta saber quienes del mercado tecnológico se adaptarán, perecerán, surgirán, perderán su relevancia y cual será el primero en comercializar un producto convergente.

IntelARM

Intel lo tiene difícil, más con las recientes noticas del abandono de sus SoCs móviles, ya que los procesadores ARM son más baratos de fabricar y consumen menos energía lo que los hace más adecuados para los dispositivos móviles, salvo que el histórico Intel se adapte perderá gran parte de su relevancia en el mundo del hardware de cómputo en la misma medida que ARM la gane. Los fabricantes que adaptan los diseños ARM explorarán nuevos campos de mercado que hasta ahora no les era posible acceder. Los mejor posicionados Qualcomm, Samsung y quizá Nvidia tenga más éxito con sus procesadores ARM Tegra y en menor medida Freescale, Texas Instruments, Broadcom, y puede que veamos a AMD fabricar de forma masiva procesadores con arquitectura ARM en detrimento de x86-64, …

Por otro lado, la convergencia requerirá de software que se adapte a cada caso de uso, como dispositivo móvil y teléfono y como ordenador de escritorio y pantallas grandes como la televisión. Microsoft ya ha dado muestras de que está trabajando en la convergencia y si es la primera en hacerla realidad de forma útil para los usuarios seguirá durante alguna década más con su práctico monopolio en el escritorio y ganar una cuota mucho mayor entre los dispositivos móviles que hoy aún se le atraganta en detrimento de Google y Android y Apple e iOS. Google tiene las partes para iniciar la convergencia con Android en el ámbito móvil, por otro lado está Chromimum OS incorporados en sus Chromebooks en el ámbito de escritorio y si es capaz de juntar las piezas y no retrasarse frente a sus competidores puede mantener su amplia cuota de mercado en el ámbito móvil y ganarla en el escritorio desafiando la posición de Microsoft. De Apple aún no he oído noticias sobre la convergencia pero también tiene una buena posición con iOS por un lado y Mac OS X por el otro pero aunque se adelante a Microsoft y Google los precios de sus productos serán más elevados que lo que más tarde Google o Microsoft fabriquen y vendan con lo que hará que Microsoft no pierda su posición dominante si Google no se la cuestiona. Seguramente GNU/Linux irá detrás de la cresta de la ola, Ubuntu ya ha dado muestras de la convergencia y está desarrollando Snapy pero probablemente llegue más o mucho más tarde que los actores anteriores.

Esta batalla tecnológica de la convergencia forjará el nuevo equilibrio de fuerzas que se mantendrán durante algún lustro o década en la que esperemos los usuarios seamos en gran parte beneficiados por nuevos productos con nuevas posibilidades a precios asequibles… hasta una nueva disrupción. Está por ver quienes pierden su posición dominante, quieres la ganan y que nuevos contendientes surgen en este nuevo mercado que transformará el existente. Finalmente, todo esto no es más que una elucubración pero una muy plausible y no lejana de lo que finalmente se produzca.

Koalite: Lo peor de desarrollar software

$
0
0

Imagínate que quieres ir a comer a un restaurante.

Después de buscar un poco, te decides por una arrocería que tiene una pinta estupenda. Cuando llegas, un atento camarero te trae la carta y eliges un arroz con bogavante que, según te aconseja el solícito camarero, es magnífico.

- Tardará unos 10 minutos en prepararse, queremos asegurarnos de que todo está a su gusto – te advierte.

Te resulta extraño porque sueles cocinar bastante arroz y sabes que tarda unos 20 minutos en estar listo, pero prefieres pensar que aquí son muy eficientes, porque la alternativa de que tengan el arroz hecho y lo vayan a recalentar te pone un poco nervioso.

Cuando pasados más de 20 minutos allí no ha aparecido arroz alguno, se lo reclamas al camarero. Éste, disculpándose amablemente, te explica que ha habido algunos problemas pero que ya casi está. Empiezas a enfadarte: estaba claro que no podían preparar el arroz en 10 minutos y, una de dos, o te están engañando o no tienen ni idea de hacer arroz, pero bueno, prefieres no pensar mucho en ello y disfrutar de tu arroz cuando llegue.

Y por fin llega el arroz. Con pollo.

- Esto es pollo. ¿Y el arroz con bogavante que había pedido? – preguntas al camarero.

- Vaya, lo siento. Tiene que haber sido un error. Le preparamos un bogavante y se lo añadimos a este arroz, así no tiene que esperar otra vez y podemos aprovechar parte del trabajo que hemos hecho ya.

Respiras profundamente mientras vas asumiendo que vas a comer arroz con pollo y bogavante. No suena muy bien, pero tienes suficiente hambre como para aceptarlo.

Cuando llega el bogavante, te mira con ojos desafiantes mientras avanza hacia ti chasqueando sus pinzas.

- ¡Está vivo! ¿Me ha traído un bogavante vivo?

- Verá, señor, vamos justos de tiempo, teníamos que haber terminado con su mesa hace un rato, pero su proyecto, digo, su comida, está resultando más complicada de lo que esperábamos y…

- Quiero mi bogavante. Y, por supuesto, lo quiero cocinado.

- Sí, señor, no se preocupe que esto lo solucionamos enseguida. Pondremos a nuestros cocineros certificados en bogavantes a trabajar en ello para asegurarnos de que reconducimos su proyecto, digo, comida.

Ahora sí, el bogavante tiene un aspecto mucho más apropiado y, por fin, puedes empezar a comer tu arroz (ya frío) con pollo (bastante reseco) y bogavante… ¿dulce? ¿Han cocido el bogavante en agua con azúcar? ¿A qué clase de experto certificado en bogavantes se le ocurriría hacer eso?

- Perdone, pero este bogavante está cocinado con azúcar. ¿Es que sus expertos no comprueban lo que están haciendo? ¿Por qué siempre me traen cosas sin sentido?

- Verá, nosotros creemos en trabajar estrechamente con el cliente durante la fase de testing y control de calidad para asegurar que la comida ofrece el valor añadido esperado. Además, habíamos reservado unas determinadas horas para atenderle y esto se está alargando más de lo previsto, por lo que comprenderá que tenemos que facturarle…

La realidad del desarrollo de software

Por desgracia, así funciona la mayoría del desarrollo de software, al menos en España.

Casi siempre que nos juntamos unos cuantos desarrolladores y nos quejamos de nuestro trabajo acabamos hablando de comerciales que sólo se preocupan por vender, de clientes que no saben lo que quieren (y tampoco están dispuestos a pagar un precio justo por ello) y de usuarios empeñados en “romper” nuestros preciosos sistemas.

Pero sobre todas esas cosas, si echo la vista atrás, lo que más frustración me ha producido ha sido la relación con otras empresas de desarrollo o con los departamentos de desarrollo de otras empresas.

Pocas veces he sufrido tanto como cuando yo he sido el cliente de un desarrollo.

Y eso que, se supone, algo sé del tema y debería estar preparado. O a lo mejor es justo por eso, porque sé algo del tema y sé que hay otras formas de hacer las cosas. En cualquier caso, cuando pienso en lo que debe de sentir alguien que contrata un desarrollo de software a la típica empresa del sector, me da lástima.

La mayoría del software que te entregan tiene una calidad ínfima.

Comprendo que definir correctamente la funcionalidad de un sistema no es una tarea fácil, requiere una buena comunicación y estoy dispuesto a asumir mi culpa como cliente por no haberla expresado bien o incluso por no haber sabido lo que realmente necesitaba, pero hay cosas que claman al cielo.

Aplicaciones que nadie se ha molestado en probar. No digo ya probar a fondo y cubrir cada caso extraño que pueda producirse, sino simplemente ver que se ejecuta y hace algo mínimamente lógico. No puede ser que se entregue una aplicación que a duras penas funciona en el caso más simple, y que, por supuesto, en cuanto fuerzas un poco, explota por mil sitios diferentes.

Los fallos de regresión están a la orden del día, y conseguir estabilizar un sistema se convierte en una auténtica labor de malabaristas; por cada cosa que se arregla se rompe otra.

Interfaces de usuario diseñados a patadas. No todos contamos con un excelente equipo de diseñadores para hacer interfaces de usuario atractivos y originales, pero qué menos que molestarse en mantener los controles alineados, revisar errores tipógraficos, ser consistente en los patrones de interacción. No hace falta ser un experto diseñador, con aplicar un poco de sentido común y poner algo de interés basta.

Usabilidad inexistente. ¿Que hay que obligar al usuario a dar 40 pasos para hacer una tarea que tiene que repetir 30 veces al día? ¿Que los mensajes de error son incomprensibles? ¿Que dejamos que el usuario destruya toda su información por no validar lo que introduce en el sistemma? Da igual, es su problema. Que aprenda a hacer las cosas bien y ser eficiente.

Gestión del ciclo de vida del producto nula. Lo he dicho antes: desarrollar es sólo el principio y entregar una aplicación es sólo un primer paso. Estoy cansado de que nadie haya previsto un plan para actualizarla, que no haya forma de diagnosticar errores en producción o que, ni siquiera, sea posible saber qué versión se está ejecutando en producción.

Y ojo, que en ningún momento estoy hablando de la calidad del código o la metodología empleada. Como cliente, me da igual la calidad del código, me importa el resultado que obtengo.

Me gustaría decir que estos problemas sólo se dan en determinados tipos de empresas, pero me los he encontrado trabajando con empresas grandes y con empresas pequeñas. Con empresas que tenían un organigrama tradicional, con una separación muy clara de roles entre comerciales, analistas, programadores, etc., y con empresas mucho más planas. Con empresas waterfall y con empresas agile. Con empresas desconocidas y con empresas “Business Golden Partner of the Century” del fabricante de turno. Con empresas caras y con empresas baratas.

Mi experiencia es que, desde el punto de vista del cliente, el panorama a la hora de contratar un desarrollo de software es desolador. No creo que se trate de un problema técnico. Tampoco de un problema comercial o de negocio. Es una cuestión cultural.

Y, sin embargo, funciona

Lo sorprendente de todo esto es que, al final, el mundo funciona. Y funciona a base de software. ¿Cómo?

Ha llegado un punto en que se asume que contratar un desarrollo de software será algo que requiera un esfuerzo enorme por parte del propio cliente para obtener un resultado final dudosamente aceptable. Como decía antes, es una cuestión cultural: hemos asumido que esto es lo que hay. Los clientes no son conscientes de que hay otra forma de desarrollar software.

Así, todos esos problemas que mencionaba antes y que a mi me parecen tan graves, no los son tanto para otros clientes. Están dispuestos a asumir que tendrán que perder mucho tiempo en conseguir que el proyecto arranque. Que, es cierto, nunca funcionará como las aplicaciones “de verdad”, porque, claro, es una aplicación “que nos hicieron a nosotros, y tiene sus cosillas“.

No sé en qué punto decidimos los clientes y usuarios que no importaba que el software fallase, pero es algo que tenemos bastante interiorizado. En otros productos esperamos que el funcionamiento sea siempre perfecto y predecible. En el software aceptamos que a veces “pasan cosas”.

Esa idea de que es normal que el software falle la hemos llevado a la contratación de un proyecto. Si contratases a un pintor para que te pintara la casa, no permitirías que te dejara las paredes mal acabadas, con manchas y ronchones. Tampoco verías normal que la pared que habías pedido azul acabase de color rojo. He visto muchos clientes de desarrollos de software que, cansados de luchar para que la pared fuese azul, acaban quedándose con la pared roja. O verde. O lo que sea, con tal cerrar de una vez el proyecto y acabar con esa pesadilla.

Esta gestión de expectativas entre empresas de desarrollo y clientes es lo que permite que el sistema siga funcionando. Sí, te he entregado un producto deficiente, pero es lo que hay. Todas las empresas somos iguales y esto funciona así. A veces me recuerda al mundo de las operadoras de telefonía. Todas te tratan mal, pero saben que pueden hacerlo porque son todas iguales y, vayas donde vayas, acabarás en la misma situación.

¿Todas? No. No todas las empresas son iguales.

Hay empresas que intentan cambiar esto. Que intentan actuar con profesionalidad y responsabilidad. Por desgracia, estas empresas tienen que luchar con la inercia de un mercado en el que cuesta mucho vender calidad porque, simplemente, el cliente no cree que eso exista.

Por eso me frustra especialmente esta situación.

Porque, además de afectarme como cliente, me afecta como desarrollador. Llega un punto en que lo podría convertirse en una ventaja competitiva (intentar hacer bien las cosas), queda anulado por el escepticismo de un cliente demasiado acostumbrado a que eso no existe.

No sé cuál es la forma de cambiar esto. A mi me resultaría más agradable vivir en un mundo en el que la gente se responsabilizase de su trabajo y actuase con profesionalidad, pero hay que ser realista y asumir que los incentivos económicos son los que mandan.

Mientras los clientes estén dispuestos a convivir con este tipo de desarrollos, estas empresas seguirán existiendo. Aun así, no pierdo la esperanza de que, algún día, si hay suficiente gente actuando con un poco de sentido común, alguien se dará cuenta de que se puede trabajar de otra manera, mucho más productiva y satisfactoria.

Hasta entonces, siempre podré seguir escribiendo rants absurdos como éste. No solucionan nada, pero al menos ayudan a desahogarse.

Posts relacionados:

  1. Cuánto daño han hecho… los arquitectos de software
  2. Desarrollar es sólo el principio
  3. La otra podredumbre del software

Variable not found: Ya tenemos ganadores de los componentes de Grapecity

$
0
0
Certificado de premioLa Diosa Fortuna, materializada digitalmente como una instancia de la clase System.Random, ha seleccionado al azar los tres ganadores del sorteo de componentes Grapecity que iniciábamos la semana pasada.

Y los afortunados han sido:

Raul Carbonell @RaulCarbonell81
Sant Quirze del Vallès (Barcelona)
Jaime de Aquino @deaquino
Sevilla
Edgar Ricárdez @ericardezp
Coahuila de Zaragoza, México

¡Enhorabuena! En breve me pondré en contacto con vosotros para concretar cómo podéis obtener vuestro premio :)

Y para los que no habéis tenido suerte, muchas gracias por participar :)  Pero no desesperéis y estad atentos al blog que en un par de días volvemos, ¡¡esta vez repartiendo componentes de DevExpress!!

Ah, y no olvidéis que por ser lectores del blog ¡aún podéis conseguir vuestro libro gratis de O'Reilly!

Publicado en Variable not found

Variable not found: Enlaces interesantes 245

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

.NET

ASP.NET

.NET Core/ASP.NET Core

Azure / Cloud

Conceptos/Patrones/Buenas prácticas

Data

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Cross-platform

Otros

Publicado en Variable not found

Poesía Binaria: Generando la salida de nuestros programas con plantillas en C++ con Silicon en pocas líneas

$
0
0

photo-1456983887044-b5ecb1059660

A medida que el hardware y el software van evolucionando, van cambiando las preferencias a la hora de desarrollar un producto. Hace unos años, el objetivo principal era que el producto final funcionara, intentar hacer el mínimo número de operaciones para que el software corriera en un ordenador de la mejor forma posible. Desde hace unos años, el hardware es capaz de hacer muchas cosas y muy rápido, los lenguajes han evolucionado y se han optimizado mucho; por lo tanto, podemos aprovechar y hacer que desde el punto de vista del mantenimiento, legibilidad del código, hacer que el código sea poesía y hacer que todas las piezas encajen perfectamente.
Es decir, ya no se suelen ver sentencias goto en ningún código (quien busca encuentra, pero a no ser que el desarrollador sepa lo que hace y sin ellas se vea muy mermado el rendimiento se intentan evitar). Pero aún así, es común que en diferentes programas encontremos uso de programación orientada a objetos, modelo-vista-controlador, identificadores en cadena de texto en lugar de numéricos (o enums) en medio del código para hacernos fácil el mantenimiento o representación y el hecho de compartir el código con otros, crear clases lo más generales posible y luego particularizarlas con nuestras necesidades, incluso, interpretar muchas partes a través de scripts (es decir, utilizar un lenguaje ya existente o inventarnos el nuestro para programar ciertas partes, o dejar que el usuario pueda programarlas).

En este caso, vengo a tratar el tema de las plantillas, o lo que es lo mismo: queremos generar una salida con un formato determinado, imaginémonos un texto:

Hey Jugador1, has conseguido 123 puntos y has perdido

Imaginemos que estamos haciendo un juego y queremos generar ese mensaje (empezamos por algo sencillo), pero a partir de aquí podemos obtener varias combinaciones de mensajes que podemos resumir sustituyendo parte del texto por palabras móviles, es decir, cosas que en el futuro cambiaremos por lo que más nos convenga:

Hey %nombreJugador%, has conseguido %puntos% puntos y has %destino%

Así el jugador se puede llamar como queramos, puede tener el nombre que quiera, conseguir los puntos que quiera y lo que ha pasado con el, puede haber ganado o haber perdido.
Esto me recuerda horrores a un simple printf (o sprintf) en el que la cadena es: “Hey %s, has conseguido %d puntos y has %destino%”. Pero claro, puede que en otros idiomas, o porque luego veamos que quede mejor, el mensaje ahora sea. Has sacado %puntos% puntos. %nombreJugador% has %perdido%. Aquí el caso del printf ya no nos sirve, porque importa el orden de los elementos.

Reemplazar texto

Lo primero que podemos probar para nuestro sistema de plantillas, podemos verlo aquí. Es decir, un sistema que nos permita reemplazar cadenas por otras cadenas. De esta forma cuando encontremos:

  • %nombreJugador% : lo cambiaremos por el nombre del jugador
  • %puntos% : lo cambiaremos por los puntos conseguidos.
  • %destino% : lo cambiaremos por un “ganado” o “perdido”

Ahora no nos importa que nos cambien el orden de las palabras clave, porque da igual dónde encontremos una, ésta se sustituirá por su equivalencia. Podemos ver un ejemplo aquí (C++11):

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
#include <iostream>
#include <string>
#include <map>

usingnamespace std;

string replace2(string source, std::map<string,string>strMap, int offset=0, int times=0)
{
  int total =0;
  string::size_type pos=offset;
  string::size_type newPos;
  string::size_type lowerPos;

  do
    {
      string rep;
      for(std::map<string, string>::iterator i=strMap.begin(); i!=strMap.end();++i)
    {
      string fromStr = i->first;

      newPos = source.find(fromStr, pos);
      if((i==strMap.begin())||(newPos<lowerPos))
        {
          rep = fromStr;
          lowerPos = newPos;
        }
    }

      pos = lowerPos;
      if(pos == string::npos)
    break;

      string toStr = strMap[rep];

      source.replace(pos, rep.length(), toStr);
      pos+=toStr.size();

    }while((times==0)||(++total<times));

  return source;
}

int main()
{
  int puntuacion =100;
  int enemigo =90;

  string original ="Hey %nombreJugador% has ganado %puntos% puntos y has %destino%";
  map<string,string> mapa ={{"%nombreJugador%", "Gaspar"}, {"%puntos%", to_string(puntuacion)}, {"%destino%", (puntuacion>enemigo)?"ganado":"perdido"}};

  cout<<"Original string: "<<original<<endl;

  cout<<"Resulting string: "<<replace2(original, mapa)<<endl;

  return0;
}

Condicional en la plantilla

Por ahora nos vale, aunque poco a poco veremos la necesidad de hacer la lógica un poco más compleja. ¿Y si no nos limitamos a sustituir palabras, sino que introducimos algo de lógica en el sistema de plantillas? Esto nos permitiría entre otras cosas aislar por completo el idioma de nuestro código, eliminando las palabras ganado y perdido. En este caso, a la plantilla le damos todas las palabras, y ya el sistema de plantillas se encargará de devolvernos la cadena definitiva. Para este ejemplo usaré la biblioteca Silicon (la de arriba):

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
#include <iostream>
#include <string>
#include "silicon.h"

usingnamespace std;

int main()
{
  int puntuacion =100;
  int enemigo =90;

  string original ="Hey {{nombreJugador}} has ganado {{puntos}} puntos y has {%if puntos>enemigodestino}}ganado{/if}}{%if puntos<enemigodestino}}perdido{/if}}";
  Silicon t = Silicon::createFromStr(original);
  try
    {
      t.setKeyword("nombreJugador", "Gaspar");
      t.setKeyword("puntos", std::to_string(puntuacion));
      t.setKeyword("enemigo", std::to_string(enemigo));

      cout<< t.render()<<std::endl;
    }
  catch(SiliconException &e)
    {
      cout<<"Exception!!! "<<e.what()<< std::endl;
    }
}

Ahora vemos que la plantilla ha cambiado un poco. Vemos por ejemplo que las palabras clave, ahora vienen entre dobles paréntesis y, además, encontramos una simple lógica en su representación. El propio sistema de plantillas evalúa la expresión y decide qué palabra mostrar (está en sus primeras versiones, por ahora no tiene else…), pero al menos, cuando le pasamos las palabras clave al sistema, no hay que poner los caracteres comodín (% antes, {{, }} ahora). Además, este sistema nos permite incluso modificar la lógica sin necesidad de compilar (en el caso en que las plantillas se encuentren en un fichero, o incluso las puedas descargar de Internet en tiempo real).

Llamar a funciones para obtener datos pesados

Otra cosa curiosa es que podemos configurar ciertos textos como funciones. Es decir, como estamos dando flexibilidad a la hora de crear plantillas. Podemos también definir muchos keywords, algunos pueden salir siempre, otros algunas veces. Y puede que otros, para obtener el dato se demoren un poco: pensemos en que tenga que ser un valor calculado o descargar de la red un cierto dato antes de representarlo. Para hacer la simulación, vamos a hacer que el dato de obtención del record mundial se retrase un par de segundos. En este caso, veremos dos plantillas, una con el récord y otra sin él, y sólo debe retrasarse la que muestra el récord.

Por ejemplo, podemos ver el siguiente código:

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
#include <iostream>
#include <string>
#include "silicon.h"
#include <thread>
#include <chrono>

usingnamespace std;

std::string worldRecord(Silicon* s, std::map<std::string, std::string> args, std::string input)
{
  std::this_thread::sleep_for(std::chrono::seconds(2));
  return"42";
}

int main()
{
  int puntuacion =100;
  int enemigo =110;

  string original ="Hey {{nombreJugador}} has ganado {{puntos}} puntos y has {%if puntos>enemigo}}ganado{/if}}{%if puntos<enemigo}}perdido{/if}}";
    //    "{!block template=bloque.html/}\n"
  Silicon t = Silicon::createFromStr(original);
  try
    {
      t.setKeyword("nombreJugador", "Gaspar");
      t.setKeyword("puntos", std::to_string(puntuacion));
      t.setKeyword("enemigo", std::to_string(enemigo));
      t.setFunction("worldRecord", worldRecord);

      cout<< t.render()<<std::endl;
      t.setData(original+"\nEl récord mundial es de {!worldRecord/}");
      cout<< t.render()<<std::endl;
    }
  catch(SiliconException &e)
    {
      cout<<"Exception!!! "<<e.what()<< std::endl;
    }
}

Esto nos permitirá hacer muchas definiciones de posibles elementos que serán plasmados en la plantilla, pero que no siempre estarán presentes y sólo se procesarán cuando aparezcan.

Un pequeño archivo XML

Para este ejemplo me voy a basar en un archivo sitemap.xml. El mismo tendrá un formato tal como este:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xmlversion="1.0"encoding="UTF-8"?>
<urlsetxmlns="http://www.sitemaps.org/schemas/sitemap/0.9"xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
  <url>
    <loc>http://dominio.com/section1</loc>
    <priority>0.70</priority>
    <changefreq>daily</changefreq>
    <lastmod>2015-02-13T15:32:42+0200</lastmod>
  </url>
  <url>
    <loc>http://dominio.com/section2</loc>
    <priority>0.70</priority>
    <changefreq>daily</changefreq>
    <lastmod>2015-02-13T15:32:42+0200</lastmod>
  </url>
  <url>
    <loc>http://dominio.com/section3</loc>
    <priority>0.70</priority>
    <changefreq>daily</changefreq>
    <lastmod>2015-02-13T15:32:42+0200</lastmod>
  </url>
...
</urlset>

En este caso quiero separar toda la parte de XML de mi código, por lo que el XML será un archivo aparte, lo leeremos y lo usaremos para mostrar la plantilla. Aunque en este caso nos encontramos con una lista de elementos que puede ser muy grande. Vamos a crear dos archivos, sitemap.xml:

1
2
3
4
5
6
7
8
9
10
11
<?xmlversion="1.0"encoding="UTF-8"?>
<urlsetxmlns="http://www.sitemaps.org/schemas/sitemap/0.9"xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
{%collection var=sites}}
  <url>
    <loc>{{sites.loc}}</loc>
{%if sites.prio}}    <priority>{{sites.prio}}</priority>{/if}}
{%if sites.changefreq}}    <changefreq>{{sites.changefreq}}</changefreq>{/if}}
{%if sites.lastmod}}    <lastmod>{{sites.lastmod}}</lastmod>{/if}}
  </url>
{/collection}}
</urlset>

y ahora nuestro archivo C++:

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
#include <iostream>
#include <string>
#include "silicon.h"

usingnamespace std;

int main()
{
  Silicon t = Silicon::createFromFile("sitemap.xml");
  try
    {
      std::vector<Silicon::StringMap> sites ={{{"loc", "http://dominio.com/section1"}, {"changefreq", "daily"}} ,
                        {{"loc", "http://dominio.com/section2"}, {"changefreq", "daily"}, {"prio", "0.2"}},
                        {{"loc", "http://dominio.com/section3"}, {"changefreq", "weekly"}},
                        {{"loc", "http://dominio.com/section4"}, {"changefreq", "weekly"}, {"lastmod", "2016-06-01T12:27:19+0200"}}};

      t.addCollection("sites", sites);

      std::cout<< t.render()<<std::endl;
    }
  catch(SiliconException &e)
    {
      cout<<"Exception!!! "<<e.what()<< std::endl;
    }
}

De esta forma, deberá generarse un archivo XML con el formato especificado en el primer archivo, pero con los datos que tenemos en nuestro archivo C++. Tenemos que ver que dentro de la muestra de la colección hemos estado aplicando condiciones.

Generación de páginas web

Esta me la reservo para otro post, ya que podrá ser muy extensa, y tengo alguna que otra cosa preparada… Estad atentos.

Colaboración

Esta biblioteca podéis utilizarla como queráis para lo que queráis, sin garantías “as is”, podéis crear trabajos derivados, romperla, destrozarla y reconstuirla. Eso sí, aunque no es obligatorio, agradecería que me enviaseis cambios, correcciones, bugs, etc.
Hay partes del código que bien podrían ser reescritas, otras deberán ser mejoradas y actualizadas, pero poco a poco :)

Foto principal: Redd Angelo

The post Generando la salida de nuestros programas con plantillas en C++ con Silicon en pocas líneas appeared first on Poesía Binaria.

Variable not found: Sorteo: ¡componentes de DevExpress!

$
0
0
DevExpressDevExpress es, sin duda, una de esas compañías que identificamos como líderes en el mercado de componentes y herramientas para desarrolladores por la calidad de sus productos y por el amplio abanico de plataformas a las que se dirigen. De hecho, año tras año son reconocidos con premios y honores que los sitúan entre los mejores y más reconocidos del panorama actual. Es decir, hablamos de nuevo de uno de los grandes :)

Tras ponerme en contacto con ellos, les entusiasmó la idea de la celebración del décimo aniversario de Variable not found e inmediatamente ofrecieron para sortear entre los lectores del blog:
  • Una subscripción ASP.NET, valorada en casi 900$, que incluye componentes para ASP.NET Web Forms,extensiones para ASP.NET MVC, sistema de reporting y algunos otros extras.
     
  • Una suscripción DevExtreme Complete, valorada en cerca de 500$, que incluye los siguientes productos:

    • DevExtreme Web, widgets javascript/HTML5 de alto rendimiento para aplicaciones web, entre los que se incluyen Grids, Pivots, Charts, Forms, Calendar, etc.
        
    • DevExtreme Mobile, un framework Javascript/HTML5 optimizado para la creación de aplicaciones móviles con look&feel nativo para las principales plataformas, soporte touch, componentes de visualización, etc.

¿Y cómo participo en el sorteo?

De nuevo, vamos a facilitar la cosa para todos aquellos que ya habéis participado en sorteos anteriores, de forma que apenas tendréis que hacer nada ;)

Los que estéis interesados en participar sólo tenéis que conseguir "papeletas"; cada uno de vosotros podéis conseguir hasta cuatro papeletas, dependiendo de vuestra afinidad con Variable not found ;) Obviamente, cuantas más papeletas consigáis, más probabilidades tendréis de ganar el premio.
  • Para conseguir la papeleta que os da derecho a participar en el sorteo sólo tenéis queescribir un comentario en este post del blog indicando cuál de los dos productos os interesa (subscripción ASP.NET ó DevExtreme Complete), y opcionalmente, algún comentario adicional como por qué queréis que os toque, o qué plan tenéis para vuestras próximas vacaciones ;). Pero 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).
    Importante: como son dos productos distintos, al participar debéis indicar obligatoriamente cuál de las dos suscripciones es la que preferís, para que lo pueda tener en cuenta a la hora de realizar el sorteo.
Ojo: si incluís el 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 "com gmail arroba joselito".
Para que os quede más claro, este sería un ejemplo de comentario de un participante que sigue a Variable Not Found en todos sus perfiles posibles, por lo que participaría con todas las papeletas y que prefiere la suscripción ASP.NET de DevExpress:
Hola, soy Alberto, y me mola la suscripción ASP.NET porque trabajo principalmente en aplicaciones MVC y los componentes de DevExpress son una pasada. En cuanto a vacaciones, suspiro por pillarme un par de semanitas en agosto, a ver si puede ser ;)
Soy albertoruiperez en gemail terminando con un dot com.
+TW1+TW2+FB
No olvidéis incluir en el comentario los textos "+TW1", "+TW2", "+FB" para indicar los perfiles a los que seguís, pues tengo automatizado el proceso del sorteo y las papeletas se asignarán automáticamente en función de estas pistas incluidas en el comentario ;) Y aseguraos de que lo que indicáis es correcto, porque de no ser así seréis descalificados!

¿Cuándo se realiza el sorteo?

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

Ese día, una aplicación leerá automáticamente los comentarios del post y asignará papeletas en función de los perfiles seguidos (+TW1, +FB…). Se sorteará en primer lugar la suscripción ASP.NET, para lo que la aplicación elegirá al azar ganadores hasta que dé con el primero que haya expresado su preferencia por este premio; seguidamente, se hará lo mismo con la suscripción DevExtreme Complete.

Tras verificar que todo sea correcto, me pondré personalmente con los ganadores través de alguna de las vías que hayan indicado al participar. Si por cualquier motivo no fuera capaz de contactar con alguno de ellos en un tiempo razonable, el premio sería sorteado de nuevo entre los participantes. También lo iremos difundiendo a través del blog y los distintos perfiles sociales.

Pues nada más, ¡espero veros participando!

Publicado en Variable not found

Variable not found: Logging en ASPNET Core (actualizado a RC2)

$
0
0
ASP.NET CoreEste post es una reedición de un contenido anterior para actualizarlo a la Release Candidate 2 de ASP.NET Core. ¡A ver si se calma todo un poco y conseguimos que los contenidos valgan más de un par de meses! ;D

Uno de los requisitos más habituales que tenemos en cualquier aplicación medianamente compleja es la creación de logs donde guardar información cuando ocurran determinados eventos.

En ASP.NET "clásico" teníamos varias opciones, como utilizar las propias herramientas de tracing del marco de trabajo, o bien frameworks especializados de terceros como los célebres Log4Net, NLog o muchos otros, pero al final la idea era la misma, poder disponer de un componente en el que poder registrar sucesos como el siguiente:
public ActionResult RemoveInvoice(string id)
{
... // Remove the invoice 
    _logger.LogInformation($"Invoice {id} was removed by {User.Identity?.Name}");
return RedirectToAction("Index");
}
El nuevo ASP.NET Core viene equipado de serie con un sistema de logging interno, integrado en el propio marco de trabajo, que proporciona algunas funcionalidades pero, sobre todo, los mimbres básicos sobre los que montar sistemas de trazas más complejos y personalizables.

Dedicaremos este post a ver cómo se configura y utiliza este mecanismo que, como otros aspectos del framework, está construido pensando en su extensibilidad y hace uso intensivo del sistema de inyección de dependencias.

Nota: aunque la RTM se acerca, sigue siendo bueno recordar que todavía estamos utilizando una release candidate de ASP.NET Core y, por tanto, algunos detalles aún podrían variar antes de que aparezca la versión final del producto.

1. Creación y uso básico de un logger

Como comentaba algo más arriba, el sistema de logging hace uso de las herramientas internas de inyección de dependencias, y esto es algo que queda patente desde su configuración. De hecho, para configurar un logger lo primero que haremos es obtener una instancia de ILoggerFactory en algún punto inyectable, como el método Configure() de la clase de inicialización:
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddDebug();
...
}
ILoggerFactory es una factoría de loggers, es decir, un componente cuya misión es crear objetos ILogger que son los que realmente utilizaremos para registrar nuestros eventos, utilizando para ello una serie de proveedores configurables. La configuración que apliquemos a la factoría es la que heredarán más adelante los loggers que utilicemos desde la aplicación.

Por ejemplo, la llamada a AddDebug() que hemos visto anteriormente configura la factoría para que los loggers que sean creados desde ella utilicen como canal de salida la ventana de resultados de depuración de Visual Studio. Es decir, desde nuestro código registraremos eventos en el log, y los veremos aparecer por esta ventana de nuestro entorno de desarrollo.

Pero tenemos otras opciones para configurar a dónde irán a parar las trazas. Igual que antes hemos utilizado AddDebug(), tenemos también disponible AddConsole() para hacer que los mensajes aparezcan en la ventana de consola (útil cuando ejecutamos la aplicación web desde línea de comandos), que vayan directamente al registro de evento de Windows (obviamente esta opción sólo estará disponible sobre .NET 4.x en Windows), o crear nuestros propios destinos personalizados implementando proveedores personalizados, como de hecho ya existen para NLog, Loggr, Elmah.io, o Serilog.

Incluso podemos configurar nuestra factoría con más de uno de ellos para que los eventos se registren en distintos puntos.
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
    loggerFactory.AddDebug();
    loggerFactory.AddConsole();
    // Los eventos logados aparecerán en la consola y en la ventana de VS 
    ...
}
Bien, una vez configurada la factoría, el siguiente paso del proceso sería crear el objeto ILogger que usaremos para registrar eventos en los canales que hayamos configurado. Esto lo hacemos mediante el método CreateLogger() de ILoggerFactory, al que debemos suministrar un nombre de categoría.

Este nombre se suele utilizar para indicar el componente origen del evento, pero en realidad podemos utilizar cualquier string que nos ayude a puntualizar el contexto en el que ha sido registrado:
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddDebug();
ILogger logger = loggerFactory.CreateLogger("Startup");    

    // Usar logger para registrar eventos
...
}
También podemos utilizar una versión genérica de CreateLogger(), que usará como categoría el nombre del tipo que usemos en su invocación:
ILogger logger = loggerFactory.CreateLogger<Startup>();
En cualquier caso, tras ello, para registrar un mensaje informativo lo único que tendríamos que hacer invocar el método LogInformation() del ILogger pasándole el texto:
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddDebug();
ILogger logger = loggerFactory.CreateLogger<Startup>();
    logger.LogInformation("Application starting");

...
}
Observad que dado que la factoría ha sido configurada para que los loggers usen la ventana de depuración de Visual Studio mediante AddDebug(), al ejecutar la aplicación veríamos en ella algo similar a lo siguiente:
MyRc2App.Startup:Information: Application starting

Mensaje de información apareciendo en la ventana "Output" de Visual Studio

2. Niveles de traza

Por otra parte, como podríamos esperar, a la hora de registrar eventos en el log tenemos distintos niveles mediante los cuales indicamos la importancia de los mensajes y que pueden ser utilizados a posteriori para filtrar las trazas y evitar el exceso de información. ASP.NET Core define los siguientes niveles en la enumeración LogLevel:
  • LogLevel.Trace, el nivel más detallado con todo tipo de información técnica destinada a desarrolladores. Pueden contener información sensible, por lo que por defecto está deshabilitado y no se recomienda su activación en entornos de producción.
  • LogLevel.Debug, para mensajes de depuración sobre cambios o estado puntual de un componente, pero sin utilidad en el largo plazo.
  • LogLevel.Information, destinado a mostrar mensajes que indican el flujo de ejecución de una aplicación.
  • LogLevel.Warning deberíamos usarlo para registrar acontecimientos anormales en el flujo de ejecución que no paran el sistema pero que deberían ser estudiados, como puede ser la captura de una excepción controlada.
  • LogLevel.Error debería usarse para registrar errores en la ejecución (por ejemplo, excepciones no controladas) que abortan un proceso, pero que no impiden que la ejecución de la aplicación continúe.
  • LogLevel.Critical, reservado para errores críticos que requieren atención inmediata, como que un disco se haya quedado sin espacio o se haya perdido de forma permanente la conexión con la base de datos.
Intellisense mostrando métodos extensores de ILogger para registrar eventosPara cada uno de estos niveles encontraremos un método extensor en ILogger, de forma que podremos utilizarlos de forma muy sencilla y cómoda a la hora de registrar eventos: LogTrace(), LogDebug(), LogInformation(), etc.

Para evitar el exceso de ruido, a la hora de configurar los proveedores que vamos a utilizar para almacenar los logs podemos indicar el nivel mínimo de logging que soportará, de forma que todos los registros que se encuentren por arriba serán ignorados. Por ejemplo, si añadimos la siguiente línea a la configuración, configurará la factoría para que los loggers usen la ventana de depuración de VS, pero en ella sólo se muestren los eventos de tipo Warning, Error o Critical:
loggerFactory.AddDebug(minLevel: LogLevel.Warning);
Fijaos que esto, unido al hecho de que podemos configurar varios proveedores en la factoría, puede posibilitarnos escenarios muy interesantes, como registrar eventos en distintos orígenes en función del nivel de traza, o incluso de otros criterios más sofisticados.

3. Simplificar la creación del logger

Habréis observado que crear el logger desde cualquier punto de nuestra aplicación y usarlo sería bastante sencillo porque, una vez configurada, sólo habría que obtener esa instancia de ILoggerFactory   valiéndonos del inyector de dependencias, crear a continuación el objeto ILogger a partir de ella, y usar este último para registrar los eventos, como en el siguiente ejemplo:
public class HomeController : Controller
{
private readonly ILoggerFactory _loggerFactory;

public HomeController(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}

public IActionResult Index()
{
var logger = _loggerFactory.CreateLogger("HomeController");
logger.LogInformation("Index action executed");
return View();
}
}
Este código podemos simplificarlo un poco, a la vez que ganamos en organización, si utilizamos el servicio de inyección de dependencias para obtener directamente una instancia de ILogger para la clase actual. Observad que utilizamos una variante tipada ILogger<T>:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;

public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}

public IActionResult Index()
{
_logger.LogInformation("Index action executed");
return View();
}
}
El ejecutar la acción Index() del código anterior, en la ventana "Output" de Visual Studio podríamos observar que aparece el texto de la traza asociado a la clase HomeController:
MyRc2App.Controllers.HomeController:Information: Index action executed

Mensaje informativo en la ventana "Output" de Visual Studio

Y lo dejamos aquí, al menos de momento ;) Espero que el post os haya resultado útil para ver el funcionamiento básico del sistema de logging de ASP.NET Core y sus posibilidades. Más adelante a ver si me animo y vemos cómo crear un proveedor de log personalizado, por ejemplo para guardar las trazas en un buffer  en memoria o quizás en una base de datos, o tal vez enviarnos por email los errores críticos… las posibilidades, como siempre, infinitas :)

Publicado en Variable not found.
Viewing all 2730 articles
Browse latest View live