Weblogs Código

Blog Bitix

Cómo instalar y probar macOS con VirtualBox en Windows o GNU/Linux

September 25, 2016 09:00 AM

¿Queres comprar un Mac, tienes dudas o deseas probar su sistema operativo antes? Aunque el rendimiento será menor que una máquina real y la experiencia de usuario será peor, usando un hackintosh mediante VirtuaBox ya sea con Windows o GNU/Linux podremos probarlo en detalle y hacernos una idea de su funcionamiento.

Apple
macOS

Estaría leyendo alguna noticia, ahora no me acuerdo que me despertaría la curiosidad pero me pregunté si es posible usar de forma virtualizada macOS con VirtualBox. Usar lo que se conoce como hackintosh, esto es hackear el sistema operativo Macinstosh de los equipos de Apple para que se ejecute en cualquier un dispositivo no soportado. En la página web hackintosh puede encontarse información diversa sobre el tema como instrucciones, vídeos, comunidades, ….

Es política de Apple que su sistema operativo solo pueda ser ejecutado en sus equipos que los vende de forma conjunta a un notable precio, no se si alguien usa macOS en un sistema no Mac con garantías de que en alguna actualización el sistema deje de funcionar teniendo en cuenta la política de Apple para con sus productos.

Los pasos para instalar macOS en una máquina virtual con VirtualBox son los isguientes, hay que descargar un archivo con la imagen del disco duro de macOS y una vez creada la máquina virtual en VirtualBox ejecutar unos comandos para cambiar algunos parámetros del sistema de arranque EFI. Deberemos descomprimir la imagen del disco duro para obtener el archivo de extensión vmdk y proceder a crear la máquina virtual. Elegimos crear una máquina virtual de tipo macOS, cambiaremos algunas opciones, asignando unos 2 o 3 GiB de memoria, selecccionaremos el disco duro con la imagen vmdk descomprimida y cambiaremos la memoria asignada a la pantalla.

Configuración de la máquina virtual

Si usamos Windows deberemos ejecutar los siguientes comandos en modo administrador, sustituyendo macOS Sierra 10.12 por el nombre que le hayamos dado a la máquina virtual al crearla:

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/588b2cd99be69d340c79cafb55f9b334/raw/windows.cmd">windows.cmd</pre></a></noscript>

En el caso de Linux el archivo de comandos es similar e igualmente sustituiremos macOS Sierra 10.12 por el nombre que le hayamos dado a la máquina virtual al crearla:

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/588b2cd99be69d340c79cafb55f9b334/raw/linux.sh">linux.sh</pre></a></noscript>

Hecho estos dos pasos podemos proceder a iniciar la máquina virtual, veremos que empiezan a salir unos cuantos mensajes hasta que se inicia el sistema gráfico con la instalación y su asistente que constará de varios pasos.

Terminada la instalación entramos en el escritorio con el aspecto clásico y fondo de pantalla de macOS y las aplicaciones incorporadas en el propio sistema por defecto.

Como partidario del software libre y la privacidad no recomiendo usar un Mac pero si alguien quiere probar este sistema operativo antes de decidirse a hacer una compra usarlo de forma virtualizado es una buena ayuda para tomar una decisión y ver si nos gusta su sistema operativo aparte del propio equipo junto con su precio que podemos ver en las tiendas.

Deberemos tener en cuenta al probar macOS con VirtualBox que el rendimiento de la máquina virtual no será exactamente el mismo que en un equipo real por la sobrecarga impuesta por la virtualización realizada. La experiencia de usuario puede cambiar significativamente junto con el hecho de que los portátiles Mac tiene una pantalla bastante mejor y con más resolución que la mayoría de portátiles diseñados para Windows o GNU/Linux y un SSD de gran rendimiento además de la falta de su touchpad, todo esto puede marcar diferencias.

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

Blog Bitix

Autenticación con OAuth y Keycloak en un servicio REST con JAX-RS y Spring Boot

September 24, 2016 07:00 PM

Keycloak es un proveedor de OAuth que podemos usar en nuestras aplicaciones y servicios para proporcionar autenticación, autorización, SSO y también añadir seguridad a los servicios REST que desarrollemos como muestro en este artículo. OAuth tiene varias ventajas sobre usar autenticación Basic.

Keycloak
Java

Una forma de autenticar a los clientes de un servicio REST es usar autenticación Basic que se basa en añadir una cabecera en la petición en la que se incluye un usuario y contraseña. La autenticación Basic es sencilla pero para que sea segura ha de usar el protocolo seguro HTTPS.

Sin embargo, presenta otros inconvenientes y es que si al servicio van a acceder varios clientes y a uno queremos impedirle el acceso no podremos hacerlo sin cambiar el usuario y contraseña lo que obligará al resto de clientes actualizarse para usar las nuevas credenciales si las comparten, que no siempre es posible sobre todo si esos clientes están fuera de nuestro control. Para solventar el segundo problema tenemos la posibilidad de segurizar el servicio REST con el protocolo OAuth.

Teniendo un servicio web REST implementado con JAX-RS y Spring Boot añadirle seguridad con OAuth mediante el proveedor Keycloak es lo que muestro en este artículo. En el servicio REST bastará que usemos el adaptador para Spring Boot de Keycloak y añadamos en Keycloak cierta configuración que consistirá en un realm y el registro de un cliente. Para acceder al servicio REST usaremos el flujo client_credentials que nos permitirá obtener un token usando las credenciales del cliente.

Iniciado Keycloak con Docker y Docker Compose accedemos al panel de administración con el navegador, en mi caso en http://localhost:9080 con el usuario admin y contraseña admin según lo indicado en el archivo docker-compose.yml.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/d3cd61c429b60c83531b624245f77bd4/raw/docker-compose.yml">docker-compose.yml</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/d3cd61c429b60c83531b624245f77bd4/raw/docker-compose-up.sh">docker-compose-up.sh</pre></a></noscript>

Creamos un realm, en el ejemplo llamado springbootjaxrs y un cliente con id client, además crearemos un rol api y se lo asignaremos al cliente.

Una vez realizada la configuración en el servidor de OAuth/Keycloak obtendremos la configuración para el adaptador de Keycloak para el servicio REST desde la pestaña Installation que añadiremos en el fichero de configuración de Spring Boot application.yml. Además, indicaremos que el cliente solo aceptará access tokens mediante la opción bearer-only de modo que no hará redirecciones para autenticar.

Indicaremos también el rol que deberá poseer el cliente para acceder al servicio REST junto que URLs del servicio estarán autenticadas por OAuth. Añadida la configuración al archivo application.yml el servicio REST es totalmente inconsciente de la autenticación que se realizará con OAuth y Keycloak.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/d3cd61c429b60c83531b624245f77bd4/raw/application.yml">application.yml</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/d3cd61c429b60c83531b624245f77bd4/raw/MessageResource.java">MessageResource.java</pre></a></noscript>

Iniciado Keycloak y el servicio REST con el comando ./gradlew run podemos iniciar el proceso de obtención de un access token y llamar al servicio proporcionando el access token obtenido y ver que pasa si no proporcionamos token o uno modificado o inválido. Para obtener el access token podemos emplear curl accediendo al endpoint de Keycloak para obtenerlos.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/d3cd61c429b60c83531b624245f77bd4/raw/curl-token.sh">curl-token.sh</pre></a></noscript>

Obtenido el access token si no lo proporcionamos en la llamada al servicio REST observaremos que la respuesta que obtenemos es un código de estado HTTP 401 indicando que se necesitan proporcionar las credenciales que con OAuth es un token.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/d3cd61c429b60c83531b624245f77bd4/raw/curl-401.sh">curl-401.sh</pre></a></noscript>

Proporcionando el token mediante una cabecera de la petición el servicio nos devolverá los datos que proporciona. Si el token no es válido obtendremos un error HTTP 401.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/d3cd61c429b60c83531b624245f77bd4/raw/curl.sh">curl.sh</pre></a></noscript>

Para usar Keycloak en una aplicación Java con Spring Boot deberemos añadir algunas dependencias al proyecto que usando Gradle como herramienta de construcción serían las siguientes.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/d3cd61c429b60c83531b624245f77bd4/raw/build.gradle">build.gradle</pre></a></noscript>

Un buen libro sobre OAuth que he leído es Mastering OAuth 2.0 que explica detalladamente el protocolo OAuth junto con el resto de formas de obtener un token además del mostrado en este artículo usando las credenciales del cliente.

En el siguiente artículo mostraré un cliente en Java del servicio REST autenticado con OAuth que haga las mismas llamadas que con curl pero usando código Java mediante la librería HttpClient.

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

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

Una sinfonía en C#

¿Cómo verificar la integridad de los scripts usando subresource integrity?

September 21, 2016 06:51 PM

Los CDN nos permiten tomar recursos como archivos Javascript de terceros (léase frameworks o librerías) sin necesidad de hostearlos nosotros y delegando esa reponsabilidad en servidores más robustos, con replicación, mejor capacidad y con un potencial uso de cache, sin embargo esto podría ser riesgoso.

Por ejemplo si el CDN es hackeado o de alguna manera las peticiones redireccionadas podemos estar potencialmente en peligro de cargar archivos maliciosos en nuestro sitio web, por suerte hay una manera de evitarlo.

Integridad de subrecursos

La integridad de subrecursos (SRI) es una característica de seguridad que permite a los navegadores verificar que un recurso recuperado (de un CDN o cualquier otro origen) no ha sido manipulado permitiendo, para ello, espeficar un hash que el navegador utilizará.

Sencillamente podemos indicar en nuestro tag script un hash calculado con algún algorítmo conocido para que el navegador verifique la integridad del recurso que se intenta cargar, veamos el caso de jQuery por ejemplo:

Llamada “normal” al CDN de jQuery

<script src="https://code.jquery.com/jquery-3.1.0.min.js">

 

El problema acá es que no estamos verificando que el archivo jquery-3-1-0-min.js sea lo que esperamos,

Llamada verificando la integridad del recurso

La forma de agregar la verficación de integridad sería la siguiente:

<script src="https://code.jquery.com/jquery-3.1.0.min.js" integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s=" crossorigin="anonymous"></script>

Nótese que agregamos el atributo “integrity” con el valor que indica el hash para verificar la integridad del archivo.

Si intentamos carga el recurso y el hash es incorrecto pasa esto:

image

¿Cómo podemos calcular el hash?

Bien, hay varias formas,:

Y listo, basante simple, más información sobre SRI en al sitio de Mozilla.

Nos leemos.

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

Blog Bitix

Monitorizar con eventos de Google Analytics una página web

September 19, 2016 09:00 PM

Conociendo cómo usar los eventos de Analytics podemos conocer información interesante acerca de qué forma los usuarios interactúan con nuestra propia página web. Cualquier cosa que podamos realizar con JavaScript o ante cualquier evento que podamos reaccionar podemos medirla con Analytics.

Google Analytics

No se mucho de Google Analytics únicamente lo que he aprendido aplicándolo en mi propia bitácora. Cuando cambié de herramienta para generar de forma estática la bitácora pude personalizar en mucha mayor medida que lo que podía primeramente con Blogger y después tenía con Octopress.

Google Analytics además de proporcionarnos diversa información interesante sobre las visitas que recibimos en una página web puede servirnos para analizar el comportamiento de los usuarios, como interaccionan con la página, qué acciones realizan o que funcionalidades son usadas. La forma con la que podemos agregar información propia de la aplicación o página web es mediante los eventos de Analytics. Después de instalar el script de Analytics podemos enviar eventos simplemente con la siguiente linea de código JavaScript.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c66532a6eaab846b579ff55b902e874f/raw/ad-enter.js">ad-enter.js</pre></a></noscript>

La información del evento de compone de categoría (category), acción (action), etiqueta (opt_label), valor (opt_value) y si no supone interacción (opt_noninteraction). Deberemos proporcionar valores según queramos estructurar los eventos obligatoriamente para categoría y acción siendo el resto opcionales. En mi bitácora uso Analytics para además de visualizar la información que proporciona sobre visitas, ubicación de los usuarios, idioma, plataforma y navegador que usan, páginas más visitadas, origen de las visitas para lanzar unos cuantos eventos que me proporcionen información sobre las pulsaciones que se realizan en el menú de categorías y en los enlaces de redes sociales, en la lista de artículos recientes, artículos destacados y en el widget de ShareThis y si se hace en el del inicio del artículo o en el del final. En la sección Comportamiento > Eventos se agrega toda la información de los eventos, además podremos monitorizar en tiempo real los eventos que se estén produciendo en la sección Tiempo real > Eventos.

El parámetro _optnoninteraction afecta al porcentaje de rebote, un evento interactivo se considerará como una acción que ha realizado el usuario después de visitar la página, si ese evento lo consideramos como un objetivo podemos hacer que esa interacción no se considere en el porcentaje de rebote. Por ejemplo, si el usuario permanece en la página 30 segundos podemos lanzar un evento que indique tal circunstancia con un timeout y esa visita no se considere en el porcentaje de rebote.

Podemos medir cualquier cosa que deseemos incluso podemos conocer cuantos usuarios usan un bloqueador de anuncios como AdBlock. Este es el código JavaScript que uso para conocer cuantos usuarios lo tiene activado o no.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/c66532a6eaab846b579ff55b902e874f/raw/ad-block.js">ad-block.js</pre></a></noscript>

En la sección Seguimiento de eventos de la documetación de Google Analytics y en el resto de secciónes hay más detalles sobre esta herramienta. Para cualquier cosa que podamos reaccionar mediente un evento con JavaScript podemos medirla con Analytics, sirviéndonos para extraer información valiosa sobre los usuarios que nos permitan medir, entender y luego mejorar la experiencia de usuario de nuestra propia página web.

Como para cualquier otra cosa en la que queramos profundizar una buena forma es con algunos libros específicos dedicados al tema. Los siguientes son dos libros de los muchos libros sobre Google Analytics disponibles en Amazon.

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

Una sinfonía en C#

¿Cómo usar Visual Studia Code como diffviewer para GIT?

September 19, 2016 06:51 PM

Con las sucesivas versiones VSCode es cada vez más potente y lo usamos para más cosas, una para la cual empecé a usarlo hace poco es para hacer diff de versiones usando Toirtoise GIT.

Básicamente cuando comparamos dos versiones de un archivo vemos algo así:

image

Como se ve tenemos la comparación a todo color y hasta una bonita barra de navegación a la derecha para ver los cambios a lo largo de todo el archivo.

¿Cómo configuramos Tortoirse GIT para usar VSCode?

Tenemos que ir a la configuración de Tortoise

image

Y en la opción de “Diff Viewer” elegimos “external” y buscamos donde tenemos instalado VSCode y agregamos el modificador “—diff” en mi caso la línea de comando queda así:

C:\Program Files (x86)\Microsoft VS Code\Code --diff

Y listo, al llamar a diff de GIT nos muestra VSCode. Nos leemos.

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

Poesía Binaria

Crea tus propias webs dinámicas en C++ de forma fácil y usando plantillas para no compilar a cada cambio

September 19, 2016 08:10 AM

Screenshot 12-08-2016-020848
Esto forma parte de un pequeño proyecto que mantengo desde hace algo más de un año. El objetivo es crear un sistema con el que servir webs desde C++, que sea más o menos fácil de mantener y generar, flexible, que soporte enrutadores, plantillas, hosts virtuales con el fin de poder utilizarlo para diferentes tipos de aplicaciones a modo de panel de control web.

Sobre todo está pensado para aplicaciones internas y no para desarrollos web públicos, por temas de seguridad y rendimiento cuando la carga aumenta considerablemente, aunque sí que podría ser utilizado sin problemas en segundo plano por nuestras aplicaciones web por eso de que en ciertas operaciones, un programa hecho en C++ rendirá mucho mejor que cualquier Javascript, Java, PHP, etc. Será más difícil de hacer y optimizar, pero correrá con más soltura y aprovechará la memoria de manera más eficiente.

Para conseguir esto, he utilizado dos proyectos de los que ya os he hablado en el pasado: Glove, que es una envoltura para sockets en C++11 con el que podemos crear un servidor web rápidamente (GitHub) y Silicon, un sistema de plantillas que nos permite separar la salida web de nuestro código en C++ (y eso nos permite también hacer pequeños cambios en la salida sin tener que compilar de nuevo). (Github).

Ambos proyectos están juntos para poder probarlos desde un proyecto en GitHub llamado SiliconGlove, de todas formas, aquí explico un poco cómo funciona todo.

El sistema tiene poco más de 100 líneas (sin contar las plantillas, que hice basándome en el tema StartBootstrapLandingPage.

Inicialización

Lo primero que tenemos que hacer es iniciar el servidor web con esta línea:

1
GloveHttpServer serv(8080, "", 2048);

Creamos el objeto serv, que será nuestro servidor. En este caso, trabajaremos en el puerto 8080. El segundo parámetro será la IP desde la que escuchamos, con lo que podemos limitar la escucha a un dispositivo concreto (si tenemos varios dispositivos de red), y el tercer parámetro será el tamaño del buffer, podremos jugar con este parámetro para conseguir mejores resultados, pero 2048 no es un mal valor).

Luego, debemos inicializar el sistema de plantillas, en este caso, estableceremos las rutas internas de css y js (para encontrarlos fácilmente, así como establaceremos ciertos valores por defecto. Todo esto, si miramos el proyecto en GitHub, lo podremos ver dentro de la función setypSiliconGlobals():

1
2
3
4
5
6
7
8
9
10
11
  SiliconWeb::load();
  SiliconWeb::cssUrl("css");
  SiliconWeb::jsUrl("js");
  Silicon::setMaxBufferLenGlobal(65535);
  Silicon::setGlobalKeyword("TwitterLink", "https://twitter.com/gasparfm");
  Silicon::setGlobalKeyword("GithubLink", "https://github.com/gasparfm/siliConGlove");
  Silicon::setGlobalKeyword("LinkedInLink", "https://es.linkedin.com/pub/gaspar-fernández/14/563/537");
  /* Don't render JS and CSS immediately */
  Silicon::setGlobalKeyword("_renderResources", "0");
  Silicon::setGlobalKeyword("PageTitle", "glove+siliCon test");
  Silicon::setGlobalKeyword("WebAuthor", "Gaspar Fernández");

Para Silicon tenemos otro buffer de datos y, si vemos que el tamaño de nuestras plantillas aumenta mucho, debemos pensar en aumentar este valor de 65535. Esto existe para optimizar un poco en tiempo y en memoria el sistema. Casi todas las palabras clave dentro de setGlobalKeyword() serán palabras que se sustituirán directamente en la plantilla, es decir, cuando en la plantilla llamemos a TwitterLink, saldrá mi enlace de Twitter automáticamente. Aunque encontramos valores con una barra baja (_) delante que serán configuraciones del sistema de plantillas, por ejemplo _renderResources, define si un recurso se pinta nada más llamarlo o no. En este caso, como no se pintan, podemos acumular todos los JS y CSS dentro de las plantillas, y sólo se harán efectivos cuando llamemos a una orden específica para pintarlos. Lo veremos más adelante.

Enrutador

Una parte importante de un sistema web, si no queremos sufrir mientras lo implementamos es un enrutador. Ya que todas las peticiones web entrarán al mismo sitio, tenemos que definir quién procesará cada una y es este enrutador el que se encarga de ello. Debemos definir qué hacer cuando llamemos a http://host/css/xxxx , http://host/js/xxxx , http://host … para ello podemos definir qué función se llamará para procesar cada una de las llamadas, de la siguiente manera:

1
2
3
4
5
6
7
8
  serv.addRoute("/", webIndex);
  serv.addRoute("/hello/$anycon/$anything", hello);
  namespace ph = std::placeholders;
  serv.addRoute("/css/$filename", std::bind(GloveHttpServer::fileServerExt, ph::_1, ph::_2, "resources/css/"));
  serv.addRoute("/fonts/css/$filename", std::bind(GloveHttpServer::fileServerExt, ph::_1, ph::_2, "resources/fonts/css/"));
  serv.addRoute("/fonts/fonts/$filename", std::bind(GloveHttpServer::fileServerExt, ph::_1, ph::_2, "resources/fonts/fonts/"));
  serv.addRoute("/js/$filename", std::bind(GloveHttpServer::fileServerExt, ph::_1, ph::_2, "resources/js/"));
  serv.addRoute("/img/$filename", std::bind(GloveHttpServer::fileServerExt, ph::_1, ph::_2, "resources/images/"));

Así cuando llamemos a la web principal, lo procesará una función llamada webIndex (la veremos más adelante). Aunque esto no tiene gracia si las rutas fueran fijas, es decir, si definimos /css/estilos.css y tuviéramos que procesarlo de forma fija, siempre, porque si incluimos varios archivos css en la misma ruta deberíamos definirlos uno a uno. Por ello, si introducimos un símbolo de dólar ($) en la ruta, el sistema lo tomará como una palabra clave. En otras palabras, se creará un parámetro dinámico al que nos referiremos como ‘anycon’, ‘anythink’, o ‘filename’, y luego la función que procese la petición sólo tendrá que jugar con el nombre que le hemos dado a la palabra clave. Esto nos puede dar mucha flexibilidad (luego veremos lo fácil que es desde la función hello).

Por otro lado, el sistema tiene funciones predefinidas, como servir un fichero directamente. Si es un CSS/JS y no vamos a hacer nada con él, lo podemos devolver directamente, para ello tenemos la función fileServerExt(). En este caso, con bind() le pasamos un argumento extra al callback, en este caso la ruta donde de verdad se encuentra el archivo. Con esto, aunque a nuestro servidor le pidan algunos archivos desde /fonts/css/fuente.ttf , en realidad lo estaremos pidiendo a resources/fonts/css/fuente.ttf , por lo que nuestra aplicación puede tener todo mucho mejor organizado.

Sirviendo el index

Para servir el index, en este caso, sólo tenemos que cargar un archivo de plantilla base (layout), sera una plantilla general para todas las subpáginas, aunque ahora sólo tenemos una, y luego cargará una plantilla específica para la página actual. Además, definiremos palabras clave locales para nuestra plantilla (cuando ésta se procese, se juntarán las palabras clave locales y las globales). Para servir la página haremos lo siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void webIndex(GloveHttpRequest &request, GloveHttpResponse& response)
{
  Silicon s = Silicon::createFromFile("index.html", "templates");
  s.setKeyword("PageSection", "Home");
  s.setKeyword("SectionsBase", "");
  try
    {

      /* setLayout soon will be global too, so we will be able to
     do it just once. */

      s.setLayout("layouts/mainLayout.html");
      response << s.render();
    }
  catch (SiliconException e)
    {
      response.code(500);
      response.responseVar("errorMessage", std::string("There was a problem: ")+e.what());
    }
}

Cogiendo palabras clave del enrutador

Esto lo podemos ver en la función hello():

1
2
3
4
5
6
7
8
9
10
11
void hello(GloveHttpRequest &request, GloveHttpResponse& response)
{
  std::cout << "TESTING"<<std::endl;
  response << "You are here: "<<request.getLocation()<<"\n";
  for (auto x : request.special)
    {
      std::cout << "ARG "<<x.first<< "=>"<<x.second<<"\n";
    }
  response << "This is the response\n";
  response << "This is another tesxt" << std::endl;
}

Vemos que request, tiene una variable llamada special con la que accede a las palabras clave del enrutador. En este ejemplo, las listamos, pero podríamos poner perfectamente:

1
std::cout << request.special["anycon"] << std::endl;

Y esto nos puede ayudar a tener ordenados los argumentos de entrada, comprobar que se pasan y procesar una salida adecuada.

Plantillas

Dentro de las plantillas, podemos incluir CSS y JS donde queramos:

{!includeCss file=”bootstrap.min.css” /}
{!includeCss file=”landing-page.css” /}
{!includeCss file=”http://fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic” /}
{!includeJs file=”jquery.js” /}
{!includeJs file=”bootstrap.min.js” /}

Del mismo modo, podemos hacer el render de CSS y JS donde queramos (porque _renderResources vale 0:





{!renderCss/}

Y, como también vemos, incluir variables con {{nombreDeVariable}}. Del mismo modo, si estamos en una plantilla base o layout, podemos incluir la información procesada de la plantilla de sección si incluimos {{contents}} , el texto se puede configurar si desde nuestro programa en C llamamos a setContentsKeyword().
Incluso incluir otras plantillas:

{!block template=”blocks/nav.tpl”/}

Sólo queda compilar, en el proyecto en GitHub, tenéis un ejemplo de Makefile que podéis utilizar para hacer pruebas rápidas.

Cosas que se pueden hacer

Aunque en el ejemplo sólo se demuestran enrutadores y plantillas, en Glove, se pueden utilizar conexiones seguras HTTPS (sólo hay que introducir los certificados), siliCon soporta la creación de funciones para procesar contenidos, condiciones, colecciones y muchas más cosas que nos harán el desarrollo mucho más fácil. Sólo tenemos que ver los ejemplos incluidos en los dos proyectos.

Si queréis un panel de control para vuestros proyectos, os recomiendo echarle un ojo a la plantilla AdminLTE. Tiene muchas características interesantes y podemos integrarla perfectamente dentro de Glove+Silicon para nuestros sistemas de control.

Un extra más

Si queremos incluir dentro de nuestro proyecto web una llamada a Glove. Por ejemplo, desde una web de producción, o desde un subdominio. Una forma muy recomendable de hacerlo es, por ejemplo, a través de Apache. De esta forma, Apache se encargará de la seguridad en las peticiones, y de pasarnos sólo lo que debe (sin que el usuario final interactúe directamente con nuestro programa), además, podemos tener varios servicios corriendo y acceder a ellos desde una misma dirección web (sin necesidad de cambiar puertos).

Para ello tenemos que activar en Apache los módulos proxy y proxy_http:

sudo a2enmod proxy
sudo a2enmod proxy_http
Considering dependency proxy for proxy_http:
Module proxy already enabled
Enabling module proxy_http.
To activate the new configuration, you need to run:
service apache2 restart

Y dentro de nuestro VirtualHost añadir la línea que comienza por ProxyPassMatch:

ServerAdmin webmaster@localhost
DocumentRoot /home/gaspy/www
ProxyPassMatch ^/glove/(.*)?$ http://127.0.0.1:8080/$1

De esta forma, nosotros, desde fuera, accederemos a http://localhost/glove/ y Apache, internamente, accederá a http://localhost:8080. Así, podemos cerrar el puerto 8080 para prevenir ataque externos.

The post Crea tus propias webs dinámicas en C++ de forma fácil y usando plantillas para no compilar a cada cambio appeared first on Poesía Binaria.

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

Variable not found

Enlaces interesantes 251

September 19, 2016 06:45 AM

Enlaces interesantesPues sí, como comentaba el amigo Gustavo en el post de despedida preveraniego, ya iba siendo hora de volver al frente de batalla. Y si he tardado no es porque haya estado desde entonces tumbado en una hamaca (¡más quisiera!), sino más bien por lo contrario. En breve os contaré más sobre el proyecto en el que ando metido, porque seguro que a muchos os va a interesar :)

Pero bueno, retomando las buenas costumbres, ahí lleváis los enlaces recopilados durante la semana pasada. Como siempre, espero que os resulten interesantes ;-)

.NET

.NET Core / ASP.NET Core

Azure / Cloud

Conceptos/Patrones/Buenas prácticas

Data access

Html/Css/Javascript

Visual Studio/Complementos/Herramientas

Otros

Y con esto, ¡queda inaugurada oficialmente la temporada 2016-2017 de Variable Not Found!

Publicado en Variable not found

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

Blog Bitix

Ejemplo de API REST en Java con JAX-RS y Spring Boot

September 17, 2016 10:00 AM

Java
Spring Framework

En Java a través de JAX-RS, una de entre las varias especificaciones de JavaEE, podemos desarrollar servicios web basados en REST y JSON. Estos servicios web al usar la infraestructura de la web y el protocolo HTTP podemos hacer uso de facilidades que proporciona como cacheo, protocolo seguro, HTTP/2, compresión o autenticación. Usando Spring Boot podemos desarrollar servicios web autocontenidos al igual que podemos hacer con las aplicaciones web tradicionales.

Para facilitar el inicio de los proyectos podemos usar Spring Initializr seleccionando los módulos web y JAX-RS con la implementación de referencia Jersey. Al proyecto creado deberemos añadir los servicios que queramos proporcionar. En el ejemplo añadiré uno muy sencillo que devuelva un nuevo mensaje creado en un servicio inyectado en la clase del recurso del servicio REST.

Esta es la definición del bean del servicio que creará el mensaje para el contenedor de inversión de control, también definimos el recurso del servicio REST para Jersey.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/76862386194b211fc775b5fb36732bc9/raw/Main.java">Main.java</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/76862386194b211fc775b5fb36732bc9/raw/JerseyConfig.java">JerseyConfig.java</pre></a></noscript>

El servicio lo definimos en una interfaz y una clase que la implementa.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/76862386194b211fc775b5fb36732bc9/raw/MessageService.java">MessageService.java</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/76862386194b211fc775b5fb36732bc9/raw/DefaultMessageService.java">DefaultMessageService.java</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/76862386194b211fc775b5fb36732bc9/raw/Message.java">Message.java</pre></a></noscript>

Es habitual que los servicios REST produzca como resultado un JSON como formato para devolver los datos. No necesitaremos hacer nada especial para convertir el Java Bean de la clase Message a JSON, de ello se encargará automáticamente JAX-RS. Con anotaciones como @QueryParam podemos obtener los parámetros del query string, de la URL o cabeceras enviadas.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/76862386194b211fc775b5fb36732bc9/raw/MessageResource.java">MessageResource.java</pre></a></noscript>

Iniciada la aplicación con ./gradlew run y con la siguiente comando de curl y URL obtendremos el mensaje en formato JSON en la salida.

<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/76862386194b211fc775b5fb36732bc9/raw/curl.sh">curl.sh</pre></a></noscript>
<noscript><pre><a href="https://gist.githubusercontent.com/picodotdev/76862386194b211fc775b5fb36732bc9/raw/out.txt">out.txt</pre></a></noscript>

Al diseñar APIs REST más complejas que este sencillo ejemplo conviene conocer el término HATEOAS. Deberemos definir como organizar la información devuelta por los diferentes que los libros RESTful Web APIs y REST in Practice además de artículos con consejos sobre como diseñar APIs RESTful.

Una vez que disponemos del servicio REST podemos añadir autenticación y autorización con Keycloak como proveedor de OAuth.

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

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

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

Práctica fundamentos de la programación

September 15, 2016 08:51 AM

Por esas cosas de la vida, hace unos meses me vi implicado en un cuestionable favor, pero justificado por motivos de fuerza mayor. Se trata de esas prácticas universitarias, en este caso la correspondiente a la asignatura de fundamentos de la programación en la UPF (Universitat Pompeu Fabra) del curso 2015-2016 para la recuperación del […]

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

Ingenieria de Software / Software Engineering / Project Management / Business Process Management

CRM | Microsoft Dynamics CRM

September 14, 2016 11:45 AM

Microsoft's big win over Salesforce: HP signs up to six-year cloud CRM deal http://flip.it/Kih4c3

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

Una sinfonía en C#

Javascript:¿Qué pasa cuando se mezclan el tipado débil y la concatenación?

September 13, 2016 01:34 PM

Todos sabemos que Javascript es debilmente tipado, es decir, existen tipos de datos pero podemos hacer cosas como cambiar el tipo de una variable:

var a = "hola";
console.log(a);
a = 1;
console.log(a)

Y no pasa nada, también podemos comparar diferentes tipos sin mucho problema:

if("hola" == 1){
 //hacer algo
}

Y tampoco pasa nada, de hecho en este caso la comparación resulta ser false, pero podría ser true por la conversión de tipos:

if("1"==1){
//hacer algo
}

Esto último da como resultado true.

El tema del que quiero hablar es una curiosidad que es consecuencia de esto mismo; en el último if lo que hace Javascript es convertir comparar sin importar el tipo, es decir, hace una conversión para saber la equivalencia entre los dos valores, algo similiar pasa cuando concatenamos strings

"hola " + 1

El resultado es "hola 1", ya que Javascript convierte el 1 en un string, hasta acá todo bien, veamos otro ejemplo:

"123"+45

da como resultado "12345", es decir un string concatenado, pero...si hacemos:

"123"-45

Da como resultado 78, porque el signo - no sirve para concatenar strings, pero sí para restar, entonces en el caso de la suma Javascript convierte el 45 en un string y los concatena, pero en el caso de la resta convierte el "123" en un número y los resta, awesome.

Nos leemos pronto.

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

Poesía Binaria

Cómo empotrar datos dentro de un ejecutable hecho en C

September 12, 2016 08:36 AM

photo-1453179592584-e2587867cfff

En nuestras andanzas como programadores, seguro que nos hemos encontrado alguna vez en esta situación. Tenemos un programa que vamos a distribuir, pero que tiene ciertos archivos asociados (imágenes, texto, scripts, etc) que deben ir junto con el programa.
En un primer momento podemos distribuir los archivos junto con el programa, y es una buena solución hasta que a alguien le da por cambiar esos archivos y consiguen que nuestro programa haga cosas diferentes a aquellas para las que ha sido pensado originalmente.

Esto se ha hecho durante años para almacenar este tipo de recursos, incluso algunos IDEs y compiladores lo hacen sin que nosotros hagamos nada. Pero somos valientes, y lo haremos con GCC.

Un poco más de contexto

Tal vez para imágenes no sea demasiado crítico, pero sí para código. Es decir, muchas veces, aunque hagamos un programa en C, éste a su vez tendrá fragmentos programados en LUA, Python, AngelScript, o incluso SQL. Y claro, si incluimos estos scripts en el código estamos forzando a recompilar el programa cuando hay un cambio en estos scripts, cosa que puede tardar mucho, y no es necesaria (lo mismo pasa con iconos, imágenes, etc).
Con recompilar el programa, me refiero a compilar un archivo .c o lo que es peor, realizar un cambio en un .h que se incluya en varias partes. Si habéis trabajado con algún programa grande, sabréis a lo que me refiero, un pequeño cambio puede suponer tener parado el ordenador varios minutos.

Lo que podemos hacer, es que en modo depuración, los recursos se lean desde los archivos externos, pero cuando el programa sea definitivo se lea de lo que tenemos almacenado en el ejecutable.

Un primer ejemplo

Vamos a empezar empotrando un pequeño texto dentro de un archivo ejecutable. Para ello, nos serviremos tanto de GCC como de objcopy. Es importante saber que este método sólo funcionará con GCC/G++, con otro compilador, debemos hacer las cosas de otra manera.
Lo primero será hacerlo con archivos de texto, para ello, crearemos un archivo llamado (pruebas.txt) y escribiremos dentro un texto.
Luego haremos este programa en C:

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

extern char _binary_pruebas_txt_start;
extern char _binary_pruebas_txt_end;

int main(int argc, char* argv[])
{
    char* c = &_binary_pruebas_txt_start;

    printf ("------------- Datos empotrados en mi ejecutable ----------\n");
    while (c != &_binary_pruebas_txt_end)
        printf("%c", *c++);
    printf ("--------- Fin de datos empotrados en mi ejecutable --------\n");
   
    return 0;
}

Ahora vamos a compilar el archivo pruebas.txt y el ejecutable:

objcopy --input binary --output elf64-x86-64 --binary-architecture i386 pruebas.txt pruebas.o
gcc -c main.c
gcc -o main main.o pruebas.o

Y listo, cuando lancemos ./main nos escribirá en pantalla el mensaje que tenemos configurado.

Eso sí, tenemos que tener especial cuidado con la arquitectura. Este ejemplo es para x86-64, si quisiéramos una salida para x86 en 32bit pondríamos elf32-i386.

Otro pequeño ejemplo con idea

Contamos con que no manipulen nuestro archivo ejecutable cambiando los datos que contiene, aunque podríamos introducir mecanismos como hacer que los primeros bytes sean un hash y cuando arranque nuestro programa comprobar que todo está bien. Pero este tipo de cosas puede servirnos para rellenar información en un struct, por ejemplo:

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

extern char _binary_struct_data_start;
extern char _binary_struct_data_end;

struct TDatos
{
    uint32_t id;
    char url[100];
    char nombre[100];
};

int main(int argc, char* argv[])
{
    struct TDatos datos;
   
    char* c = &_binary_struct_data_start;
    memcpy(&datos, c, sizeof(struct TDatos));

    printf ("ID: %d\n", datos.id);
    printf ("URL: %s\n", datos.url);
    printf ("Nombre: %s\n", datos.nombre);
   
    return 0;
}

Eso sí, ahora tenemos que hacer un archivo binario en el que incluyamos:

  • 4 bytes (ID, un número, que tal vez en texto sea ilegible).
  • 100 bytes de texto (url, hay que tener cuidado y meter un terminador, 0x00 cuando termine el texto).
  • 100 bytes de texto (nombre, incluyendo un terminador como antes).

Podemos generar el fichero de datos de varias maneras: una de ellas sería creando otro programa en C que escriba los datos en un archivo binario, otra forma puede ser utilizar un editor hexadecimal, como el pantallazo que muestro a continuación (Sí, es Emacs como editor hexadecimal, que Emacs vale para todo):
Screenshot 12-09-2016-020913.
Luego llamamos a este archivo struct.data, creamos el objeto con objcopy y compilamos el programa enlazando el objeto. El resultado será algo como:

objcopy --input binary --output elf64-x86-64 --binary-architecture i386 struct.data struct.o
gcc -c main.c
gcc -o main main.o struct.o
./main
ID: 65
URL: http://totaki.com/poesiabinaria
Nombre: Poesía Binaria

Alternativa para depuración

Si queremos hacer, como dije al principio que el dato se coja de un archivo sólo si estamos en modo depuración y si no, se coja del ejecutable, debemos hacer algo como esto (es una idea, nada más, no está optimizado ni nada):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#define DEBUG 1
#define FREE_RESOURCE(res) if (DEBUG) free(res)
#define GET_RESOURCE(res, tam, resource_name)                                                       \
    {                                                                                                                                           \
        if ( (DEBUG) && (file_exists(# resource_name ".data")) )                        \
            tam = get_resource(&res, # resource_name ".data");                              \
        else                                                                                                                                \
            {                                                                                                                                   \
                res = & _binary_ ## resource_name ## _data_start;                               \
                tam = (& _binary_ ## resource_name ## _data_end) -                          \
                    (& _binary_ ## resource_name ## _data_start);                                   \
            }                                                                                                                                   \
    }


extern char _binary_text_data_start;
extern char _binary_text_data_end;

/* Existe el archivo ? */
short file_exists(char *filename)
{
    FILE* fd = fopen(filename, "r");
    if (fd)
        {
            fclose(fd);
            return 1;
        }
    else
        return 0;
}

size_t get_resource(char** res, char* filename)
{
    FILE *f = fopen(filename, "rb");
    printf ("%p\n", f);
    fseek(f, 0, SEEK_END);
    size_t fsize = ftell(f);
    fseek(f, 0, SEEK_SET);  //same as rewind(f);

    *res = malloc(fsize + 1);
    fread(*res, fsize, 1, f);
    fclose(f);

    (*res)[fsize] = 0;
    return fsize;
}

int main(int argc, char* argv[])
{
    char* data;
    long tam;
    GET_RESOURCE(data, tam, text);
    printf ("El recurso ocupa: %ld\n", tam);
    printf ("Datos: %s\n", data);
    FREE_RESOURCE(data);                    /* Sólo libera memoria cuando estamos en depuración */
   
    return 0;
}

Y el fichero texto.data podrá contener lo que queráis. En este caso veremos que cuando compilamos y DEBUG es 0, SIEMPRE cogeremos la información empotrada en el ejecutable, pero cuando DEBUG vale 1 y además el fichero texto.data existe, leeremos el fichero y cogeremos de ahí la información. Si cuando dejamos de utilizar el recurso llamamos a FREE_RESOURCE, liberaremos el puntero que se reserva en modo depuración, pero en real no hace nada.

Nota de la foto: ¿Por qué frutas? Considero trozos de datos o información a las frutas, y cada una de ellas debe ser empotrada en un ejecutable sin perder sus propiedades.

Foto: Roman Davayposmotrim

The post Cómo empotrar datos dentro de un ejecutable hecho en C appeared first on Poesía Binaria.

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

Koalite

Por qué no utilizo métricas

September 12, 2016 05:06 AM

Sería el año 2006 más o menos cuando leí Pragmatic Programmer, el libro que más me ha influido como desarrollador. Por su culpa decidí montar un servidor de integración continua que a día de hoy sigue siéndome de extrema utilidad lanzando vetustos scripts de msbuild que conviven con los mil sistemas de compilación de Javascript.

Lo que se ha caído de ese servidor, o mejor dicho, de los scripts varios que ejecuta, es el cálculo de métricas varias sobre el código.

Al principio me molestaba en calcular métricas sobre el código fuente (utilizaba cosas como Source Monitor para ello), que me indicaran número de líneas de código, complejidad ciclomática, nivel máximo de anidamiento, profundidad de jerarquías…., en fin todo tipo de datos para disfrutar con un poco de porno de estadísticas. Además, analizaba la cobertura de código que alcanzaban mis tests (con NCover, si no recuerdo mal), y tenía configurados mis avisos si no llegaban a determinados niveles.

Nunca les hice excesivo caso, pero era bonito tenerlas y consultarlas de vez en cuando, e incluso a veces me servían para ver áreas que podía mejorar refactorizando el código o añadiendo más tests.

Hoy en día no uso este tipo de indicadores y no los echo en absoluto de menos, pero antes de ver por qué yo no consigo sacarles mucho partido, vamos a ver qué razonamientos hay detrás del uso de métricas y por qué, a lo mejor a ti, sí que te resultan útiles.

Si no lo mides, no lo puedes mejorar

Es algo aceptado generalmente. Para poder mejorar algo, necesitas poder medirlo, porque es la única manera de saber si estás mejorando o no.

La idea de las métricas es crear una serie de valores que actúen como proxies de lo que realmente se quiere medir. Normalmente, lo que se quiere medir son cosas como la facilidad para mantener el código, la propensión a contener errores o la fiabilidad.

Para ello, se parte de características del código fácilmente medibles y se asume cierta relación entre ellas y la cualidad que realmente queremos medir. Por ejemplo, en general el código que tiene más complejidad ciclomática es más difícil de mantener. El código con un ratio de comentarios adecuado es más fácil de mantener. Las clases con más líneas de código son más propensas a contener errores. El código cubierto por tests suele tener menos fallos.

Desde un punto de vista puramente estadístico, las métricas pueden llegar a ser muy fiables. Sobre todo si tenemos una muestra lo suficientemente grande y representativa de código que nos permita afinar los valores a partir de los cuales debemos preocuparnos.

Ayuda bastante en ese sentido aplicar técnicas de análisis forense del código que nos ayuden a identificar áreas especialmente problemáticas. Lo bueno de estas técnicas es que trabajan sobre hechos reales, porque están analizando la historia del código, y no se limitan a establecer hipótesis en base al aspecto actual del mismo.

Cuando estamos trabajando con bases de código muy grandes, o con equipos con gente con poco conocimiento desigual, o con mucha rotación de personal, las métricas son una buena forma de mantener un cierto control sobre lo que se está haciendo. Por una parte podemos marcar límites a las barbaridades que hacemos (“no puede haber contructores con más de 10 parámetros”), y por otra nos permiten señalizar potenciales problemas y nos dan una pista de dónde podemos empezar a dedicar esfuerzos para mejorar la salud de nuestro proyecto, como explica Jorge Sánchez.

Lo que mides, es lo que consigues

Es el mayor peligro de empezar a medir cosas y tratar de optimizarlas. Si lo haces bien, te arriesgas a conseguir mejorar esas métricas. Y sólo eso. Por eso es fundamental no olvidar que lo que quieres mejorar no son las métricas sino lo que ellas representan.

En un mundo ideal, estas métricas que hemos elegido como proxy reflejarían perfectamente las cualidades que buscamos en el software, pero en el mundo real, no siempre es así. Puede que ese método con 4 ifs sea más fácil de entender así. O que lleve funcionando 8 años y no haya dado ni un sólo problema. A lo mejor es código autogenerado. ¿El ratio de comentarios? Otro factor muy relativo que depende mucho del tipo de comentario.

En realidad, esto no debería ser un problema. No deberían tomarse las métricas como reglas rígidas, sino como indicadores de cosas que tal vez estén mal. Se supone que deberían servirnos para llamar la atención sobre ellas y decidir si necesitamos solucionarlas o no.

Cuando sí que se puede convertir en un problema es cuando empezamos a evaluar o valorar a los desarrolladores en base a esas métricas.

Entonces es probable que se preocupen más de conseguir un 100% de cobertura de código en los tests, que de escribir tests que realmente sean útiles. Incluso aunque sólo usemos las métricas a título informativo, es fácil que si las estás viendo continuamente te acaben condicionando a la hora de organizarte el trabajo para intentar mejorarlas. Nos gusta jugar y mejorar nuestra puntuación.

No consigo sacarles partido

Con lo que hemos estado viendo hasta ahora, parece razonable pensar que calcular métricas sobre el código, si se hace con sentido común, es una herramienta práctica para desarrollar software.

Pese a ello, no soy capaz de sacarles suficiente partido como para que me compense ralentizar la compilación obteniendo métricas y asumir el riesgo de acabar jugando contra ellas en lugar de centrado en conseguir lo que realmente considero importante.

En mi caso, trabajo en un equipo pequeño, donde todos somos muy conscientes de lo que queremos conseguir y de los valores que queremos reflejar en nuestro código, por lo que el componente de control no me resulta útil.

Trabajo con una base de código relativamente grande, en la que el número de falsos positivos es importante.

Esos casos que mencionaba antes, de clases muy grandes pero que tienen su justificación, o de código feo pero que funciona y nunca hay que modificarlo, aunque son infrecuentes, existen, y si tienes un volumen de código suficiente, son los que acaban copando todos los listados de “métodos más inmatenibles”.

Ello implica que si no quieres estar revisando una y otra vez lo mismo, necesitas mantener algún tipo de configuración en las herramientas de análisis estático para ignorar esos bloques de código, lo que complica el mantenimiento y te acaba llevando al otro extremo, el de los falsos negativos por culpa de haber marcado como “ignorables” partes de la aplicación que no deberían serlo.

Al final le acababa haciendo caso a las métricas para manteneras bonitas, pero no porque realmente me aportaran demasiado. Ya sabíamos de sobra las partes de la aplicación que eran difíciles de tocar y mantener, o dónde se solían concentrar los bugs.

De hecho, había ocasiones en que la solución que más nos gustaba podía ir en contra de las métricas de calidad que habíamos establecido, por ejemplo aumentando acoplamiento para conseguir una mayor cohesión, pero tener las métricas encima nos condicionaba, aunque fuera inconscientemente, a usar soluciones menos atractivas pero con mejor puntuación.

El problema para mi, en definitiva, es que las métricas analizan el código, y el código importa, pero el contexto más.

Cuanto menos contexto tienes, más valiosas se vuelven las métricas, porque al menos te aportan alguna información. Si puedes permitirte estar encima de las cosas y confiar en el sentido común de los que trabajan contigo, la utilidad de las métricas disminuye bastante porque puedes observar directamente la realidad sin necesidad de proxy.

No hay posts relacionados.

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

Blog Bitix

Artículo #2 de Yo apoyo al software libre

September 09, 2016 09:30 PM

Recibidas nuevas transferencias de Google y Amazon por la publicidad AdSense y los enlaces de afiliado respectivamente que incluyo en esta bitácora he realizado unas pequeñas nuevas donaciones económicas a varios proyectos de software libre que uso habitualmente.

Firefox
Wikipedia

En diciembre de 2015 escribía un artículo sobre la primera donación económica que hacía un proyecto de software libre. En esa primera donación compré un par de camisetas a la Free Software Foundation Europe o FSFE. Pasados ocho nuevos meses desde entonces me llegó una nueva transferencia de Google por la publicidad AdSense que incluyo en esta bitácora de alrededor de 80€, hace unos meses recibí otra por los enlaces de afiliado de Amazon que en este caso fue de alrededor de 25€. Como la bitácora no me genera ningún tipo de gasto ni para el hospedaje ni para el dominio (salvo buena parte de mi tiempo, que no es poco) me planteo hacer una nueva donación a algún proyecto o algunos proyectos.

Pensando que proyectos serían los siguientes y que cantidad me he decidido por los siguientes Arch Linux, Arch Linux ARM, Firefox y Wikipedia con 10€ cada uno para un total de 40€, que al final solo han sido 20€ porque el medio para hacer el pago utilizando de Software in the Public Interest tanto en Arch Linux como en Arch Linux ARM por algún motivo no me acepta la tarjeta bancaria virtual, en la siguiente donación quizá lo intente de nuevo o de otra forma por ejemplo comprando una camiseta en FreeWear.

Como sistema sistema operativo uso GNU/Linux y la distribución Arch Linux tanto a modo personal en mi portátil y en el trabajo y a pesar de ser una distribición rolling release o en constante actualización raras han sido las veces que he tenido algún problema desde hace ya más de 6 años. Esta es la distribución con la que al final personalmente he acabado más contento después de pasar por Fedora, Debian y Ubuntu. Arch Linux ARM lo utilizo en una Raspberry Pi 1 modelo B (la que tiene 256 MiB de memoria) para hacer descargas y también muy contento ya que tampoco me da problemas. Firefox es el navegador de mi preferencia después de una no muy extensa época usando Chromium, lo uso a modo personal y en el trabajo como desarrollador web. Finalmente, aunque no sea un proyecto de software libre es un proyecto colaborativo de libre acceso y desde hace tiempo una gran fuente de conocimiento acumulada de la que suelo incluir muchos enlaces en esta bitácora, es la Wikipedia.

Las cantidades que he donado no son muy elevadas pero espero que ayuden a estos proyectos a continuar su desarrollo y seguir mejorando. Esta de las pocas veces que «pago» algo por el software que utilizo exceptuando las veces en las que lo he hecho por el impuesto Windows.

Hubo una época que usaba el sistema operativo de Microsoft sin licencia de Windows XP. Hoy en día Windows 10 y Office 2016 siguen siendo fáciles de usar sin licencia un buen porcentaje de usuarios tampoco pagará por el software que usa lo que en realidad afecta negativamente al software libre ya que le impide ganar cuota de uso. El software libre no es sinónimo de gratis, aunque en la mayoría de los casos lo es, sino que proporciona a sus usuarios las 4 libertades explicadas en ¿Qué es el software libre?.

Estas son las pruebas fehacientes que muestran las donaciones que he hecho a los dos proyectos anteriores.

Donación Mozilla
Donación Wikipedia

Probablemente dentro de alrededor de otros 8 meses cuando reciba nuevas transferencias de Google y Amazon haré una nueva donación a otra serie de proyectos que uso quizá en ese caso a LibreOffice, VLC, GNOME, GIMP, … o lo intente de nuevo con Arch Linux. Y estos serán proyectos muy conocidos que no necesiten tanta colaboración económica seguro que hay muchos proyectos menos conocidos pero muy importantes que también necesitan financiación.

Puede que ni siquiera uses GNU/Linux o software libre pero al visitar esta bitácora puedes considerar que tú también has colaborado con el software libre ;) y simplemente usarlo o promocionarlo ya es una buena forma de apoyarlo. Si lo hicieses, ¿a que proyectos harías tú una donación?

Yo apoyo al software libre

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

HardBit

Ejecutando Node.js en una maquina virtual de Windows Azure extra small

September 05, 2016 05:25 PM

A principio de año lei un articulo (how to) de como instalar node.js en una maquina virtual en Amazon, esta maquina virtual es una micro la mas pequeña del IaaS de Amazon, con la llegada de los nuevos servicios de Windows Azure voy a replicar la idea es replicar exactamente lo mismo pero usando Windows Azure IaaS.

1.- Nos autenticamos en Windows Azure y vamos a la opción de nueva maquina virtual como lo muestra la siguiente imagen.

2.- Una vez realizado esto vamos a escoger el SO en este caso usare un openSUSE y el tamaño de la maquina virtual sera extra small.

3.- Le asignamos un DNS name y entonces creamos la maquina virtual.

4.- Añadiremos un endpoint con el puerto 80 para poder ver nuestro demo de node.js como muestra la siguiente imagen.

5.- El siguiente paso es conectarnos por medio de SSH para realizar las instalaciones de las herramientas necesarias para compilar node.js para eso obtendremos los datos del servidor SSH.

6.- Una vez con los datos del servidor SSH nos conectamos con las credenciales que otorgamos al crear nuestra maquina virtual.

7.- Una vez realizado este paso, vamos ahora si a instalar las herramientas con el gestor de paquetes zypper.

sudo zypper install gcc-c++ make
sudo zypper install openssl-devel
sudo zypper install git
git clone git://github.com/joyent/node.git
cd node
git checkout v0.8.8
./configure
make
sudo make install

8.- Una vez instalado node.js vamos a agregar la siguiente linea que contiene las rutas de bin al archivo sudoers en el apartado Defaults Specifications

Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

Para realizar este paso ejecutamos lo siguientes comandos, en este caso uso vi para realizar la modificación

sudo su
vi /etc/sudoers

 

9.- El siguiente paso es crear nuestro ejemplo de nodejs por lo que nos salimos de su con el comando exit y vamos a nuestro directorio raiz

cd ~/mk

dir site

cd site

vi server.js

Lo siguiente es agregar el código al archivo server.js

var sys = require( “sys” );
var http = require( “http” );

// Create our HTTP server.
var server = http.createServer(
function( request, response ){

// Create a SUPER SIMPLE response.
response.writeHead( 200, {“content-type”: “text/plain”} );
response.write( “Hellow world from Windows Azure!\n” );
response.end();

}
);

// Point the HTTP server to port 80.
server.listen( 80 );

// For logging….
sys.puts( “Server is running on 80” );

10 .- Una vez realizado este paso abriremos el puerto mediante iptables con el siguiente comando

sudo /usr/sbin/iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to 80

11.- El siguiente paso es instalar el paquete forever para que siempre este en linea nuestro servidor node.js para por lo que ejecutamos el siguiente comando

sudo npm install forever

12.- Una vez realizado este proceso vamos a crear un archivo de nombre start que nos servira para iniciar node.js y donde pondremos el siguiente codigo

#!/bin/bash

# Invoke the Forever module (to START our Node.js server).
./node_modules/forever/bin/forever \
start \
-al forever.log \
-ao out.log \
-ae err.log \
server.js

Le damos permisos de ejecución al archivo con chmod +x ./start

13.- Y por ultimo ejecutamos nuestro servicio con privilegios elevados.

sudo ./start

Y con esto nuestro servidor node.js ya se estará ejecutando en mi caso en la url http://vmnodejs.cloudapp.net

Es importante mencionar que Windows Azure cuenta en sus Cloud Services (Web Roles) con un ambiente de Node.js y libs para usar el blob storage y demás, pero este es un ejemplo de como poder personalizar nuestro servidor Linux en el IaaS de Windows Azure 😉

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

Poesía Binaria

Creando un plugin epara WordPress: localizar el plugin e insertar traducciones (cuarta parte)

September 05, 2016 08:11 AM

simterm
Estoy haciendo un pequeño tutorial de cómo me lo he montado para crear un plugin de WordPress: simterm. Podéis echar un vistazo al plugin desde la página anterior, y probarlo si queréis :)

Esta es la cuarta parte, enfocada a la localización de plugins. Podéis acceder desde aquí a:

  • Primera parte. Introducción y conceptos básicos de plugins de WordPress y algunas manías personales.
  • Segunda parte. Enfocada a la pantalla de configuración de nuestro plugin.
  • Tercera parte. Enfocada a la inclusión de recursos CSS y JS y a los shortcodes.

El proceso de localización (l10n) de WordPress está basado en los principios de gettext. Si quieres, puedes ver otros posts de traducciones con gettext aquí: Traducciones Gettext para nuestros proyectos en PHP y 5 consejos para internacionalizar nuestros programas con gettext en PHP). De todas formas, WordPress tiene sus propias herramientas, parecidas, pero propias.

El proceso de localización de un plugin

La localización se basa en archivos .po y .mo que podemos editar con poedit (ver los posts enlazados un poco más arriba). En estos ficheros habrá una asociación entre el mensaje en un idioma neutral (yo suelo utilizarlo en inglés) y los mismos mensajes en un idioma de destino. Esto nos facilitará la vida a la hora de crear el código, puesto que sólo tenemos que escribir en un idioma, olvidándonos de establecer convenciones, ni crear variables específicas ni nada, sólo añadiendo una función. Lo más importante que tenemos que tener en cuenta es el dominio de las traducciones. Este dominio será algo así como nuestro módulo (plugin, tema, parte en la que utilizamos la traducción), y luego el idioma, en mi caso es_ES (que será español-España, como también tendremos es_MX (para español Mexico), es_AR (español Argentina), etc.

Para ordenar un poco nuestros archivos, dentro del directorio o carpeta del plugin crearemos otro directorio llamado langs/ (o languages/, l10n/, etc), el objetivo de esto es separar los archivos de nuestro plugin de las traducciones. Los archivos de las traducciones, si por ejemplo nuestro dominio (que podemos darle el mismo nombre que al plugin), se llama myplugin, los archivos de traducción se llamarían:

Para español España
langs/myplugin-es_ES.po
langs/myplugin-es_ES.mo
Para francés de Francia
langs/myplugin-fr_FR.po
langs/myplugin-fr_FR.mo
Para chino de Singapur
langs/myplugin-zh_SG.po
langs/myplugin-zh_SG.mo

Algo muy bueno que tiene este sistema es que si alguien quiere traducir el plugin, no tiene por qué saber PHP, ni tiene que pelearse con los archivos del plugin. Sólo tiene que generar los archivos .po y .mo

Lo que tenemos que hacer en el código

En nuestro plugin, tenemos que decir de alguna forma que es traducible, y decirle el dominio de traducciones del que hemos hablado antes. Además, en WordPress hay que decírselo dos veces (tiene su lógica).

La primera vez que hay que hablarle a WordPress sobre traducciones es para que cuando un plugin no esté instalado, sepa de dónde sacar sus mensajes. Sobre todo para la descripción del plugin, para que ésta pueda escribirse en el idioma que debe, que esto queda muy bien. Para ello tenemos que escribir esto en el archivo principal de nuestro plugin (donde están las cabeceras), fijémonos sólo en Text Domain y Domain Path:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
/**
 * Plugin Name: SimTerm
 * Plugin URI:  http://gaspar.totaki.com/en/php-project/simterm/
 * Description: Simulates terminal input/output for tutorials
 * Version: 0.1.0
 * Author: Gaspar Fernández
 * Author URI: http://totaki.com/poesiabinaria/
 * License: GPL3
 * Text Domain: simterm
 * Domain Path: /languages/
 */

Text Domain especifica el dominio, y se llama casi igual que el plugin, pero todo en minúsculas. Podría tener el nombre que quisiéramos, pero debe ser único para todo WordPress si no queremos que éste se confunda buscando las traducciones.
Domain Path especifica el directorio dentro del plugin donde están los archivos de traducciones.

La segunda vez que le hablamos a WordPress sobre traducciones, debe ser nada más cargado el plugin, escribiendo algo como esto:

1
2
<?php
  load_plugin_textdomain( 'simterm', false, dirname( plugin_basename( __FILE__ ) ).'/languages/' );

Con esta línea hacemos que se cargue el dominio de traducciones, en la ruta especificada para nuestro plugin, cuando éste ya está cargado. Es decir, esto es lo más importante.

Aunque el dominio puede que no siempre nos interese cargarlo. Si nuestro plugin, sólo es accesible desde administración (o los mensajes traducibles los escribe en la zona de administración podemos cargarlo de la siguiente forma:

1
2
3
4
5
6
7
<?php
add_action( 'admin_init', 'load_textdomain' );

function load_textdomain()
{
  load_plugin_textdomain( 'simterm', FALSE, dirname( plugin_basename( __FILE__ ) ).'/languages/' );
}

Por lo que sólo se cargará cuando se inicialice la zona de administración. Si, por ejemplo en add_action() sólo ponemos ‘init’, se cargará siempre.

Cuando quiero que un texto se traduzca…

Tenemos que escribir algo más que el propio texto. WordPress utiliza entre otros, la función __() que tiene dos argumentos. El primero es el texto a traducir, y el segundo el dominio. Por lo que cada cosa que queramos traducir quedaría:

1
2
<?php
echo __('Plugin options', 'simterm');

Y se representará en el idioma del WordPress en que se ejecute (si dicho idioma está disponible en nuestro plugin), o en el idioma original (si el idioma no se encuentra).

Encontramos varias funciones de WordPress para representar traducciones, además de __() que presenta una traducción simple, es decir, un texto en un idioma original por un texto traducido. Tenemos:

  • _e($texto, $dominio) : que es lo mismo que echo __($texto, $dominio);
  • _n($singular, $plural, $numero, $dominio) : presentará una traducción en función de $numero ya sea 1 o superior, para especificar plurales.
  • _x($texto, $contexto, $dominio) : Selecciona la mejor traducción en función del contexto, porque una misma palabra puede significar varias cosas y eso hace las traducciones muy duras.
  • Hay muchoss más, incluso existen esc_html__(), esc_html_x() para devolver cadenas escapadas, y mucho más.

Cuando queremos traducir un texto con variables dentro…

Un texto con variables puede ser. “Tu IP real es: xxx.xxx.xxx.xxx” por lo que, dentro del mensaje traducido debemos escribir algo que de paso a la variable. Esto lo podemos hacer con sprintf() de la siguiente forma:

1
2
<?php
echo sprintf(__('Tu IP real es %s', 'dominio'), $ip);

El problema aquí viene cuando hay varias variables. Como “Tu IP real es xxx.xxx.xxx.xxx y conectas desde: España”, en algunos idiomas puede tener más sentido decir: “Conectas desde España con esta IP: xxx.xxx.xxx.xxx” y con el uso habitual de sprintf podemos tener un problema, ya que depende de la posición donde se encuentre la variable. Aunque podríamos hacer lo siguiente:

1
2
<?php
echo sprintf(__('Tu IP real es %s$2 y conectas desde: %s$1', 'dominio'), $pais, $ip);

Es recomendable, si utilizamos programas que automáticamente recorran los textos traducibles (como poedit) hacer una llamada a __($texto, $dominio) siendo $texto la descripción de nuestro plugin, tal y como aparece en el comentario principal. Así el programa nos detectará la traducción.

Una pequeña advertencia

Si en tu plugin, vas a poner URLs, como URL de donación, de la página de tu plugin, tu e-mail (no es recomendable, pero quién sabe), nombre de la licencia, tu nombre, etc. Utiliza variables para ello y no las incluyas en la traducción. Puede que un traductor a un idioma extraño del que no tengas ni idea cambie algún dato.

Hasta aquí una breve introducción…

Si queréis más documentación, podéis visitar la página de internacionalización de WordPress.

The post Creando un plugin epara WordPress: localizar el plugin e insertar traducciones (cuarta parte) appeared first on Poesía Binaria.

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

Koalite

Conviviendo con la Ley de Conway

September 05, 2016 05:06 AM

Según la Wikipedia, la Ley de Conway dice que las organizaciones que diseñan sistemas sólo pueden producir diseños que repliquen las estructuras de comunicación de la propia organización.

Quizá la forma más gráfica de verlo es este ejemplo de Eric S. Raymond:

Si tienes cuatro equipos de trabajando desarrollando un compilador, lo que conseguirás es un compilador de 4 fases.

Es razonable. Para hacer que un sistema funcione, todos los que participan en su desarrollo deben comunicarse para poder colaborar y los canales de comunicación marcarán mucho lo que se puede hacer y lo que no. Si quieres poner tres equipos separados a trabajar en el proyecto, no te quedarán muchas más opciones que dividirlo en, al menos, tres bloques independientes en los que puedan trabajar esos equipos, desacoplando al máximo esos bloques y estableciendo unos interfaces rígidos entre ellos.

No hace falta pensar en empresas muy grandes para que ocurra esto. Cualquiera que haya tenido que integrar su software con el de otras empresas lo habrá vivido. Acabas colaborando con distintos departamentos de desarrollo y eso te lleva a diseños que permitan acotar muy bien la responsabilidad de cada uno. Es mucho más fácil coordinarse entre varias empresas para desarrollar un sistema distribuido que para hacer una aplicación monolítica, incluso aunque la solución más simple al problema fuese hacer una única aplicación monolítica.

Todo esto además se manifiesta en los distintos niveles del diseño, desde la arquitectura general el sistema, hasta la separación del código en módulos, clases, métodos o funciones. Si estás programando por parejas con un compañero en la implementación de un módulo y decidís que es mejor poder avanzar en paralelo, acabaréis acordando alguna estructura (por ejemplo, clases) con un interfaz fijo que os permita separaros y seguir programando cada uno por vuestro lado. Si os hubieseis mantenido juntos, tal vez no hubiera sido necesaria ese interfaz y el diseño podría haber sido diferente.

Las consecuencias negativas

En ocasiones se percibe la Lay de Conway como algo negativo, y lo cierto es que puede llegar a serlo.

Un caso claro es el que comentábamos antes de la coordinación de varias empresas, donde llegar a una colaboración muy estrecha a nivel de código es sumamente complejo y la única opción viable muchas veces es partir el sistema en tantos subsistemas como empresas estén colaborando, independientemente de que sea la mejor opción.

Otro caso frecuente se produce cuando tenemos equipos muy especializados. Por ejemplo, muchas veces la gente encargada del diseño gráfico no es la misma que la encargada del desarrollo, y si analizas el código casi puedes ver una línea clarísima que separa las partes hechas por cada uno. Esto hace que cuando hay que realizar cambios sea todo mucho menos ágil y que la experiencia de usuario se resienta porque hace falta separar muy bien la parte de diseño de la parte de implementación para que ambos equipos puedan trabajar por separado.

Pero el caso más paradigmático es, sin duda, el de las empresas formadas por “expertos” en determinadas tecnologías, que además suelen son “Golden Enterpise Partner” de los fabricantes de turno. Si una empresa tiene un equipo de SharePoint Ninjas, otro de Dynamics Samurais y algunos Azure Rockstars, puedes estar seguro de cuál será la solución que darán a cualquier problema. Ley de Conway en su máxima expresión.

Asumir lo inevitable

Tampoco hay que ver la Ley de Conway como algo necesariamente negativo. Más bien hay que verlo como algo inevitable. Algo que no es ni bueno ni malo, simplemente, es, y hay que aprender a vivir con ello.

En un mundo ideal, cada vez que afrontásemos un desarrollo podríamos reconfigurar la organización que lo lleva a cabo para alinearla con los requisitos del desarrollo y alcanzar la solución óptima de la manera más eficiente posible.

Pero claro, eso es en un mundo ideal.

En el mundo real, trabajamos en estructuras ya creadas que no podemos cambiar de la noche a la mañana, y es mejor ser consciente de los puntos fuertes y débiles de estas estructuras para intentar aprovecharlos a nuestro favor, o al menos intentar que nos frenen lo menos posible.

Eso no quiere decir que no puedas o no debas intentar mejorar la estructura de la organización para adecuarla al tipo de productos o proyectos que desarrollas, pero igual que reescribir una aplicación desde cero suele ser una mala salida y es mejor ir haciendo mejoras incrementales, en este caso suele ser más fácil realizar cambios graduales que montar una revolución.

En función de cómo esté organizada la empresa, hay arquitecturas que pueden resultar más adecuadas que otras. Por ejemplo, una arquitectura basada en microservicios puede ser muy práctica cuando necesitamos repartir el trabajo entre muchos equipos casi independientes. Sin embargo, si se trata de un equipo pequeño, que mantiene una comunicación muy estrecha, apostar por un monolito majestuoso puede suponer un sistema más sencillo de comprender y desplegar.

Es similar a lo que ocurre con lenguajes de programación. Puede que tu proyecto se preste especialmente a desarrollarlo sobre Erlang, pero si tienes un equipo de 20 personas para hacerlo y ninguno tiene ni idea de Erlang, tal vez sea preferible buscar otra alternativa antes que despedir a todo el equipo y contratar un grupo de expertos en Erlang.

Por otra parte, ir ajustando la estructura de la empresa al tipo de desarrollos que suele realizar permite mejorar la eficiencia. Por ejemplo, si nuestros desarrollos implican el desarrollo de backends y aplicaciones para dispositivos móviles, parece razonable poder trabajar en paralelo en ambas y tener equipos preparados para ello. O si desarrollamos 4 productos diferentes, poder avanzar en todos ellos simultáneamente.

Ello no tiene por qué acabar en una especialización excesiva de los miembros del equipo (de la que no soy muy partidario, por aquello de tener equipos tolerantes a fallos). Es posible que las mismas personas asuman (o compartan) distintos roles en función del proyecto.

Conclusiones

La estructura del sitio en que trabajamos va a afectar a la forma en que desarrollamos. Eso es algo inevitable y que debemos tener en cuenta a la hora de tomar decisiones sobre el diseño de una aplicación.

No podemos pretender cambiar por completo la estructura y la forma de trabajar de un sitio sólo porque se haya puesto de moda una arquitectura o metodología de trabajo determinado, pero tampoco debemos ser excesivamente conformistas y, si la entorno existente no permite resolver los problemas de manera eficiente, habrá que buscar la forma de cambiarlo.

Al final, como siempre, se trata de buscar un compromiso que nos permita sacar partido a lo que ya tenemos mientras lo vamos mejorando. Nadar y guardar la ropa, que diría mi abuelo.

No hay posts relacionados.

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

Navegapolis

Scrum Level: Evaluación y mejora de la agilidad

September 04, 2016 08:52 AM

scrum level portadaCon el nombre de Scrum Level hemos reunido y estructurado el conocimiento para la gestión ágil de proyectos, equipos y organizaciones sintetizado durante estos años en Scrum Manager, y empleado en proyectos reales de asesoría y mejora a empresas, por el equipo de profesores y colaboradores.

Hemos preparado con ilusión el material para difundirlo y compartirlo de forma abierta con todos los profesionales a los que os pueda resultar útil para conocer el nivel de agilidad en una organización, y cómo mejorarlo.
Está ya disponible en versión 1.0 en scrumlevel.com.

Como promotor y parte del equipo que lo ha hecho posible, espero que sea útil :-)

 

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

Blog Bitix

Sobre los ínfimos impuestos que paga Apple

September 02, 2016 09:30 PM

Apple

El 30 de agosto de 2016 la Comisión Europea anunciaba que Apple debía devolver a Irlanda la cantidad correspondiente obtenida por las ventajas fiscales que considera irregulares, una cantidad astronómica de unos 13000 millones de euros mas los intereses desde 2003. Si ya Irlanda ofrece una fiscalidad ventajosa al tener un tipo impositivo del 12,5% de los beneficios, Apple con acuerdos conseguía pagar un 1% y un 0,005%. Acuerdos que la comisión Europea considera irregulares porque solo se aplica a algunas empresas como Apple siendo una desventaja y trato de favor respecto a otras empresas establecidas en Irlanda. Esta fiscalidad ventajosa es el motivo de que otras muchas empresas tecnológicas de EEUU tengan su sede europea en Irlanda, en España por ejemplo debería haber pagado un 25%.

Algunos medios informaban así de la noticia:

Horas después Apple en su web publicaba una carta firmada por Tim Cook indicando lo mucho que contribuye en empleos e inversiones en Europa que se verán amenazadas además de afirmar que no ha recibido ninguna ventaja fiscal de la que se le acusa.

Carta de Apple a su comunidad en Europa

Hasta aquí los hechos.

Lo primero que hay que destacar es que en realidad la Comisión Europea no le pone una multa a Apple ni a Irlanda por cometer una irregularidad sino que simplemente le obliga a devolver lo que debería haber pagado y no durante todo el tiempo que cometió la irregularidad sino simplemente desde el 2003, las ventajas fiscales se remontan a 1991. Pagar menos impuestos de los que debe le sale barato a Apple, si no le obligan esos miles de millones que no paga en impuestos, si le obligan solo tiene que devolver lo que debería haber pagado igual que si no hubiera hecho la trampa y solo a partir de una fecha en que la situación no ha prescrito. Toda una oportunidad para obtener máximos beneficios.

La carta de Tim Cook demuestra el tono con el que actúa y por el medio en el que la publica, en su propio sitio web, parece más bien dirigida a salvar su imagen entre sus usuarios y clientes que a la Comisión Europea. «la dirección de Apple supo ver un lugar rico en talento» a lo que seguidamente se atribuye también ser ejemplo para otras multinacionales, ya sería más bien por las ventajas fiscales del lugar. Un buena parte de la carta está dirigida a expresar la cantidad de empleos e inversión que según Apple genera ya sea directamente, que solo son unos paupérrimos 6000 para su volumen de negocio, y un millón y medio según ellos entre desarrolladores de aplicaciones y pequeñas y medianas empresas que dependen de Apple. Por este mensaje parece que Apple se debe consentir su irregularidad en aras de mantener esta actividad que alardea de generar. En la carta por supuesto dice que su ingeniería fiscal está de acuerdo a la legalidad y que no ha recibido las ventajas fiscales de las que le acusa la Comisión Europea. Comisión Europea que no debe estar de acuerdo después de años de observación e investigación.

Apple junto con Estados Unidos e Irlanda recurrirán la resolución. Irlanda con su tipo impositivo reducido y prácticamente inexistente para Apple en 2010 fué rescatada por importe de 45000 millones de euros. Estados Unidos interviniendo en un asunto para proteger los intereses de una de sus empresas más grandes. Y todo esto sin el infame acuerdo de inversiones y libre comercio TTIP que el estado norteamericano quiere acordar con la Unión Europea con el que esta disputa se resolvería en un tribunal supranacional que reduciría la soberanía de la Unión Europea y sus estados miembro. Parece que son los EEUU los que más intereses tienen y rápido en aprobar el TTIP ya que con seguridad les sea muy y más ventajoso para ellos y sus empresas. En época de paz una forma de dominio y nueva forma de guerra fría es la económica. Si EEUU es capaz de espiar a ciudadanos y presidentes de gobiernos aliados no sería de extrañar que espiase también a empresas extranjeras para proteger a la suyas y darles ventajas competitivas o su economía capitalista.

En este caso la elegida ha sido Apple siendo la empresa de referencia pero otras empresas tecnológicas norteamericanas emplean la misma ingeniería fiscal para reducir a la mínima expresión los impuestos que pagan en sus actividades en todo el continente europeo. ¿Habrá alguna siguiente obligada a pagar los impuestos que le correpondían?. Ingeniería fiscal que no está al alcance de las pequeñas y medianas empresas ni de los ciudadanos y por ello es injusta. No es casualidad y tampoco es porque los irlandeses sean especialmente listos, talentosos o más trabajadores que otras empresas como Microsoft, Google, Amazon o Facebook entre otras grandes también tengan su sede europea en Irlanda.

Hay otras disputas como en el caso de Google acusada de monopolio en Europa que puede acarrearle en este caso sí alguna cuantiosa sanción económica. O la privacidad de los ciudadanos europeos por parte de Facebook.

Es tu decisión y responsabilidad también sabiendo esta información de que empresas y productos consumes. Si esta es la legalidad no se a que esperan los políticos honestos, con coraje y determinación para cambiarla y hacerla justa.

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

Adrianistán

Phaser.js Hispano, aprende a hacer videojuegos en HTML5

September 01, 2016 09:00 AM

Phaser.js Hispano es un sitio web, de mi propia creación, donde escribo tutoriales para aprender a usar Phaser, una de las librerías más populares para crear juegos 2D con JavaScript.

Phaser

Su éxito se basa en su simplicidad. No trata de reinventar la rueda con conceptos extraños e innovadores. Simplemente hace lo que muchas otras librerías hacen, de un modo claro, sin complicaciones. Fue creado por Richard Davey, alias photonstorm. Comenzó como una librería privada suya, pues él realiza juegos de navegador como trabajo. Con el tiempo fue mejorando, se hizo opensource y ahora cuenta con muchos usuarios aunque gran parte del desarrollo lo sigue realizando Richard. El motor ha sido usado con éxito en infinidad de juegos y a día de hoy me parece la opción más madura y efectiva de realizar un juego HTML5 con JavaScript.

Phaser usa Pixi.js como motor de renderizado, lo que permite a los juegos usar WebGL o Canvas 2D indistintamente. Además si manejas Pixi verás que algunas partes de la API de Phaser son similares. Los juegos funcionan en cualquier dispositivo que soporte HTML5, desde ordenadores de mesa (Windows/Mac/Linux) hasta televisores y consolas (WiiU, Xbox One, Chromecast,…) pasando por los omnipresentes móviles y tablets, que a día de hoy son las plataformas que prefieren los jugadores para jugar a juegos sencillos, de poca profundidad.

¿Estas listo para probar Phaser? He realizado una lista con, al menos, los elementos de los que me gustaría tratar en la web Phaser.js Hispano. La Gran Guía de Phaser en Español, úsalo como índice para tus consultas. Si tienes alguna duda no dudes en expresarla. ¿Quiéres tratar algún tema en particular? ¿Conocías la librería antes?

La entrada Phaser.js Hispano, aprende a hacer videojuegos en HTML5 aparece primero en Blog - Adrianistan.eu.

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

Jesús Perales

Zte volumen bajo

August 30, 2016 08:35 PM

Zte volumen bajo

Un problema en mi celular ZTE Blade A475 es que no se escucha al conectarlo a el auxiliar de mi auto.

Para solucionarlo es necesario ir al modo ingeniero (Enginner Mode) a el cual se llega ya sea tecleando *#*#3646633*#*#* en la aplicación del teléfono o bajando una aplicación en Google Play.

Zte volumen bajo

Si utilizamos la aplicación para acceder al modo ingeniero debemos seleccionar la opción MTK Settings.

Zte volumen bajo

Vamos a el apartado de Hardware Testing y seleccionamos Audio.

Zte volumen bajo

Ahora seleccionamos la opción Headset Mode

Zte volumen bajo

El campo de Max Vol. 0~160 lo podemos poner con el valor de 104 o 105, cualquiera de los 2 funciona, y presionar SET.

Zte volumen bajo

Listo ya se debería escuchar el celular al conectarlo por auxiliares, esto fue probado en un ZTE Blade A475.

Fuente

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

Adrianistán

La Criptonovela del verano: una historia en tres capítulos (Capítulo 3)

August 30, 2016 01:00 AM

Ya hemos lo que sucedió en el mundo Bitcoin con el tamaño de bloques y también el hard fork en Ethereum causado por la pérdida de fondos en la DAO. Ahora veremos otro robo, con un desenlace totalmente distinto, el caso de Bitfinex.

Capítulo 3: El robo de Bitfinex

Bitfinex es una casa de intercambio, donde la gente puede depositar sus bitcoins y conseguir otra moneda y viceversa. En el caso de Bitfinex el soporte al trading está muy presente.

Bitfinex

El 3 de agosto saltó a noticia, incluso la prensa generalista de hizo eco, había habido un robo en la plataforma. Al poco se aclaró que el problema no era un fallo de seguridad de Bitcoin sino de la propia plataforma de Bitfinex. La cantidad sustraída ascendió a más de 65 millones de dólares al cambio. Ese mismo día la cotización de Bitcoin cayó un 20%. A estas alturas el caso podría recordarnos al de Mt. Gox, pero aquí acaban las similitudes.

CEO de Mt. Gox en los buenos tiemposCEO de Mt. Gox en los buenos tiempos

Bitfinex bloqueó la plataforma y decidió que quitaría el 36% a todos los que tuviesen depositado dinero en la plataforma. No importa que tuviesen dólares, Litecoins, Ethereum, … les afecta a todos. Bitfinex además tuvo una curiosa idea, compensó a sus usuarios con BFX, una moneda especial. Esta moneda representa el dinero sustraído, con valor nominal de 1$. Es decir, si por la quita del 36% perdiste 500$, Bitfinex te recompensa con 500 BFX.

Ante esta curiosa respuesta quedan dos posibilidades:

  • Cuando Bitfinex logre recuperar el dinero sustraído fruto de su actividad recompre los BFX a valor nominal. Esto implicaría que Bitfinex pagaría con sus bolsillos las pérdidas del robo y los usuarios recuperarían su dinero íntegramente.
  • Intercambiar los BFX por otra moneda, aquí uno puede asumir las pérdidas (pues el BFX siempre valdrá menos que un dólar a nivel de mercado, ya que la devolución no es algo garantizado) o comprar todavía más BFX con la esperanza de que suban.

Nada más salir BFX, su valor experimentó un descenso pronunciado, llegando a caer hasta un valor de 0,3 $.

Sin embargo esta solución no ha gustado a muchos usuarios que plantean emprender acciones legales contra la compañía.

A modo de comparación, si recordáis, con Ethereum ante un robo de una cantidad inferior se llegó al hard fork, sin embargo en este caso tal situación no se ha planteado, pues se considera que el fallo no lo tuvo en ningún caso Bitcoin sino Bitfinex.

¿Te parece correcta la solución de Bitfinex ante el robo?

Este es el último capítulo de la serie La Criptonovela del verano: una historia en 3 capítulos. Podéis dejar en los comentarios si os ha gustado o no y por qué.

La entrada La Criptonovela del verano: una historia en tres capítulos (Capítulo 3) aparece primero en Blog - Adrianistan.eu.

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

Una sinfonía en C#

Problemas deshabilitando Hyper-V en Windows 10

August 29, 2016 01:01 PM

La cosa es que necesitaba correr una máquina virtual en VMWare y éste no es compatible con Hyper-V pero yo lo tenía habilitado (porque los emuladores de Visual Studio lo querieren) así que hice lo que había hecho otras veces en el pasado, ir a “funcionalidades de Windows” y deshabilitar todo lo relativo a Hyper-V

 

image

Después de eso Windows pide reiniciar, decimos que sí, claro, pero al volver  iniciar nos dice que no pudo hacer los cambios y Hyper-V sigue ahí…todo mal.

La solución

Finalmente encontré en Stack exchange la solución, una línea de comando que evita que Hyper-V se reactive (que al parecer era el problema):

bcdedit /set {current} hypervisorlaunchtype off

 

Y si queremos habilitarlo de nuevo

 

bcdedit /set {current} hypervisorlaunchtype auto

 

En fin...cosas...nos leemos

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

Poesía Binaria

Cómo crear un plugin para WordPress. Making of de SimTerm: insertar recursos JS/CSS y shortcodes (tercera parte)

August 29, 2016 08:50 AM

simterm
Estoy haciendo un pequeño tutorial de cómo me lo he montado para crear un plugin de WordPress: simterm. El plugin inserta un shortcode que nos permite simular una ventana de terminal (sea el SO que sea) y hacer como que se escriben cosas y el sistema nos da la respuesta. Es perfecto para nuestros tutoriales y si seguís este blog, seguro que lo habéis visto miles de veces.

Esta es la tercera parte, enfocada a recursos y shortcodes. Podéis acceder desde aquí a:

  • Primera parte. Introducción y conceptos básicos de plugins de WordPress y algunas manías personales.
  • Segunda parte. Enfocada a la pantalla de configuración de nuestro plugin.

Vayamos al grano.

Insertar recursos en la web

Cuando queremos insertar archivos JS y CSS dentro de una web hecha en WordPress, como para todo, tenemos dos formas:

  • A pelo, es decir, insertando el código HTML:
    1
     <script type="text/javascript" src="ruta de nuestro script"></script>

    . Aunque esto es muy feo y muy poco recomendable ya que puede romper la estructura del HTML resultante, resultar lento para el usuario y puede que las dependencias no se gestionen correctamente (¿cuántos archivos js dependen de que jQuery se haya cargado antes? y eso de esta forma no está garantizado)

  • Utilizando funciones específicas de WordPress. Esta será la forma recomendada para que nada se rompa. Y la que contaré en este post

Insertar scripts

Aunque hay varios métodos para insertar recursos Javascript y CSS en una web hecha en WordPress, algunas formas muy complicadas. Aunque si no queremos complicarnos la vida podemos usar wp_enqueue_script(). Esta función introduce nuestro script en una cola que se podrá incluir en el <head> o justo antes de que acabe el </body&ft;. Permite además gestionar en cierto modo la versión del script que se utiliza. Eso será bueno ya que si nuestro servidor permite que el usuario guarde archivos en caché local (vamos, que el usuario se queda con los JS y los CSS para no tener que descargarlos cuando está navegando por nuestra web) lo va a utilizar de forma eficiente.

Sin más dilación, la forma en la que tenemos que utilizar esto sería:

1
wp_enqueue_script($identificador, $src, $dependencias, $version, $footer);

Es decir:

  • $dentificador: Será un identificador único de nuestro script, ningún otro script que cargue este wordpress puede llamarse igual. Esto nos ayuda con la gestión de dependencias. Si por ejemplo el Javascript que incluimos es una biblioteca genérica (underscore, angular, plugins de jQuery, etc), podemos utilizar como identificador el nombre de esta biblioteca. Esto será bueno porque si varios plugins utilizan la biblioteca al mismo tiempo sólo se incluirá una vez, evitando conflictos. Por otro lado, si el archivo Javascript es nuestro, o muy específico del plugin podemos utilizar como nombre “nombreplugin-nombrescript” para garantizar que el nombre es único. En mi caso (que pondré más adelante, los identificadores se llaman “simterm-shoryourterms” y “simterm-launcher”.
  • $src: Es la URL del recurso que vamos a incluir. Es decir, el Javascript en cuestión. Esta ruta debería ser absoluta para evitar muchos problemas en el caso en el que el blog no esté en el directorio raíz del dominio. Por ejemplo, podríamos poner aquí: “/wp-content/plugins/simterm/js/simterm.js” perfectamente, y funcionaría en muchos sitios. Pero si nuestro blog lo colocamos en www.dominio.com/blog/ ya no funcionaría correctamente. Para ello podemos utilizar la función plugins_url() de la siguiente forma:
    1
    2
    <?php
    echo plugins_url('js/simterm.js', __FILE__);

    De esta forma, la función cogerá la URL correspondiente al fichero actual del plugin y le añadirá js/simterm.js; solucionando cualquier problema que pueda presentar la ruta en el futuro.

  • $dependencias: Esto será un array con los identificadores de todos los scripts de los que dependa el javascript que estamos encolando. De esta forma, cuando se vaya a añadir definitivamente el script en la página, las dependencias se añadirán antes, incluso las dependencias de las dependencias… de esta forma evitamos este tipo de conflictos.
  • $version: Una cadena de caracteres con la versión del script que vamos a añadir, false (o nada) si queremos coger la versión que tiene WordPress (si la tiene), o null si no queremos añadir versión.
  • $footer: Es un booleano que, si vale false, añadiremos el script en la cabecera, y si vale true, lo añadiremos antes de cerrar body. También depende del momento en el que hagamos la inclusión del script, si ya tenemos la salida iniciada, es recomendable añadirlo en el footer.

Si por el contrario, sólo queremos que WordPress conozca la existencia del script, sin añadrlo atomáticamente y, si algún módulo lo incluye como dependencia se incluya automáticamente, podemos utilizar de la misma manera wp_register_script().

Insertar estilos CSS

Casi casi de la misma forma que insertamos Javascripts podemos insertar estilos, sólo que esta vez no se añaden en el footer, el último argumento de wp_enqueue_style() es $media, que especifica para qué dispositivo, orientación, o tamaño de pantalla está pensado este CSS. Por defecto ‘all’.

Ejemplo en simterm

En el plugin simterm, esto se ha hecho de la siguiente forma:

1
2
3
4
      wp_enqueue_script('simterm-showyourterms', plugins_url('js/show-your-terms.min.js',__FILE__), array(), '20160705', true);
      wp_enqueue_script('simterm-launcher', plugins_url('js/simterm.js',__FILE__), array('simterm-showyourterms'), '20160705', true);
      wp_enqueue_style('simterm-showyourtermscss', plugins_url('css/show-your-terms.min.css', __FILE__), array(), '20160705', 'all');
      wp_enqueue_style('simterm-extracss', plugins_url('css/simterm.css', __FILE__), array(), '20160705', 'all');

Inserto dos JS y dos CSS, para mantener compatibilidad con el script original, inserto el JS y el CSS originales tal cual están en el repositorio (tengo mi propio fork en GitHub, con algunas modificaciones), por otro lado hay un JS y un CSS para adaptar a WordPress estos archivos (son un pequeño cambio, pero me gusta tenerlo todo separado).
Por otro lado, para los números de versión he utilizado la fecha en formato YYYYMMDD (añomesdía), y los scripts los he situado en directorios css/ y js/ dentro del mismo directorio del script.

Creación del shortcode

El funcionamiento del plugin será el siguiente. En medio de un post, escribimos:

[simterm]
$ comando
salida del comando
$ comando 2
Bienvenido al comando 2
> El comando 2 permite al usuario una entrada de texto adicional
El comando 2 proporciona una respuesta.
Fin del comando 2
[/simterm]

El shortcode será simterm. WordPress utiliza este tipo de códigos cortos que nos ayudan a escribir texto predefinido e insertar bloques predefinidos dentro de los posts (tal y como hago, por ejemplo para insertar bloques de código), o como hacen muchas webs para insertar un texto para enviar por Twitter directamente.
El shortcode del ejemplo anterior se traducirá por esto:

comando
salida del comando
comando 2
Bienvenido al comando 2
El comando 2 permite al usuario una entrada de texto adicional
El comando 2 proporciona una respuesta.
Fin del comando 2

Lo primero es decirle a WordPress que vamos a insertar un shortcode. Esto lo hacemos así:

1
2
<?php
    add_shortcode('simterm', array(self::$st, 'simterm_shortcode'));

Donde el segundo argumento será el callback que se ejecutará cada vez que se encuentre este shortcode. El shortcode será simterm. El callback puede ser el nombre de una función como string o un array tipo (clase, función) como en el caso anterior. Esta línea, yo la he incluido en la inicialización del plugin, directamente en aquella función Init() que expliqué en la primera parte, pero perfectamente puede estar a pelo escrito en el PHP principal de tu plugin.

La función del shortcode tendrá una forma parecida a esta:

1
2
3
4
    function simterm_shortcode($atts, $content="")
    {
       return "Lo que queremos poner de vuelta";
    }

Si el shortcode tiene esta forma:

[[code atributo1=valor1 atributo2=valor2]contenido[/code]]

En $atts recibiremos los atributos y en $content recibiremos el contenido. Con esto ya tenemos lo suficiente para generar una salida en consecuencia que devolveremos en el return de la función. En mi caso, yo he decidido cargar aquí los JS y los CSS, para no incluir nada que no se necesite en la página del post. Además, como valor de retorno, he cargado una vista que se encargará de generar el código HTML necesario para representar el terminal. Podéis echarle un vistazo al código en GitHub. Ya que creé una clase aparte para procesar cada línea de entrada, y hay algunas cosas que poco tienen que ver con WordPress.

En este punto, consulto las opciones que tengo almacenadas por el plugin que modificarán el comportamiento.

En la práctica podemos incluir tantos shortcodes como queramos, el sistema de gestión de shortcodes es bastante eficiente y depende más del número de shortcodes que incluyamos en el post en cuestión que del número de shortcodes que podemos introducir. Aunque es muy recomendable que las funciones que procesan estos shortcodes estén lo más optimizadas posible y dependan lo menos posible de recursos externos ya que influirán en el tiempo de carga del post, y eso puede ser malo para nuestros usuarios.

Siguiente parte

Aunque con esto hay para hacer un plugin básico, todavía quedan algunos aspectos interesantes que podemos incluir, como por ejemplo la localización de nuestro plugin, para que los mensajes estén en el idioma del usuario. El post sale el 5 de septiembre.

The post Cómo crear un plugin para WordPress. Making of de SimTerm: insertar recursos JS/CSS y shortcodes (tercera parte) appeared first on Poesía Binaria.

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

Koalite

De lo nuevo y lo viejo

August 29, 2016 05:06 AM

Hace un mes Robert C. Martin (Uncle Bob) publicó un post que, como muchos de los que escribe, generó bastante atención. Lógico, teniendo en cuenta que es el padre de Clean Code y uno de los abanderados del movimientos Software Craftmanship que tantos adeptos tiene. Quizá esa influencia que tiene sobre la opinión de mucha gente merezca dedicar algo de tiempo a analizar lo que dice en su post.

Os recomiendo que leáis el post original antes de continuar. Sólo os llevará un par de minutos y os permitirá contextualizar la discusión. Si sois demasiado perezosos para eso y confiáis en mi resumen (cosa que no deberíais hacer), el post viene a decir los siguiente:

All we are really doing is reinventing the wheel, over, and over again. (…)

Progress in software has followed a logarithmic growth curve. In the early years, progress was stark and dramatic. In later years the progress became much more incremental. Now, progress is virtually non-existent. (…)

New languages aren’t better; they are just shiny. And the search for the golden fleece of a new language, or a new framework, or a new paradigm, or a new process has reached the point of being unprofessional.

Vamos, que está todo el pescado vendido.

Que ya no hay margen para grandes avances en el mundo del desarrollo de software. Que la forma en que desarrollamos software hoy en día es la mejor, nuestras herramientas (él habla concretamente de Eclipse e IntelliJ) son las mejores, y nuestros lenguajes actuales los más adecuados. Intentar encontrar mejores soluciones es un esfuerzo futil que no merece la pena, y una actitud que podemos considerar poco profesional.

No te dejes llevar por las modas

Lo que hay que hacer, según Robert C. Martin, es aprovechar lo que ya tenemos. Conocer unos cuantos lenguajes de los que ya existen, saber sacarle partido a las herramientas que hemos construido y empezar a desarrollar software que resuelva problemas de verdad, no que dé vueltas una y otra vez sobre las mismas cosas.

Es fácil empatizar con el mensaje. Especialmente si eres de los que está más o menos al día en este sector y estás cansado de ver modas que van y vienen, de lenguajes que no aportan nada nuevo y de librerías que desaparecen antes de que te dé tiempo a sacar la segunda versión de tu aplicación. Si además tienes contacto con el caos del desarrollo frontend, te sentirás aún más indentificado.

Yo mismo he defendido en varias ocasiones la importancia de aprender cosas fundamentales por encima de cosas novedosas, o he criticado el uso excesivo de arquitecturas de moda, y estoy de acuerdo en la necesidad de ser productivo y no estar reescribiendo nuestras aplicaciones cada dos meses sólo porque ahora tenemos un lenguaje o librería más molón.

Toda esa parte me parece bien. Me parece más peligrosa la interpretación que puedan hacer algunos, que tienen a Robert C. Martin en un pedestal, de parte del mensaje del post.

Todavía estamos empezando

Por un parte, me parece arrogante pensar que hemos alcanzado el zenit del desarrollo, y más teniendo en cuenta que estamos hablando de una disciplina que no tiene ni un siglo de antigüedad.

En el post original no se da ningún argumento real al respecto. Sí es verdad que Fortran supuso un avance mayor con respecto al Ensamblador de lo que puede suponer (si es que lo supone) TypeScript sobre Javascript, pero eso no quiere decir que no haya avance a nivel global y, sobre todo, creo que se equivoca de foco.

No se trata de comparar C# con Java. O Elixir con Ruby. O xUnit con NUnit. O React con Angular. O Visual Studio con Eclipse. Desde luego, hablar de React como un gran avance en la historia del desarrollo de software no tiene ningún sentido y no es comparable, por ejemplo, a la aparición de LISP, aunque eso no quiere decir que no sea útil, y los conceptos que ha ayudado a popularizar entre muchos de nosotros son útiles.

Pero lo más importante es que hay otras áreas en las que todavía queda mucho por avanzar. No soy futurólogo, pero hay áreas en las que creo que podemos ver mejoras a corto-medio plazo:

Sistemas de tipos y analizadores estáticos cada vez más avanzados que ayuden a detectar más errores en tiempo de compilación, o que permitan implementar soluciones de tipado gradual de forma más cómoda que en la actualidad. Esto está muy relacionado con el, a veces denostado, mundo académico, pero ese trabajo acabará llegando (como lo ha hecho en otra ocasiones) a las herramientas mainstream sin que nos demos cuenta. Entonces diremos, “mira que listo es Eclipse que refactoriza código fácilmente y nos hace ser más productivos”.

Reducción del tiempo necesario para obtener feedback al hacer cambios en las aplicaciones, por ejemplo mediante herramientas que nos permitan recargar código en caliente sin perder el estado. Algo similar a lo que podemos hacer con HTML y CSS en un browser, pero aplicado a todo tipo de código. Hoy en día hay plataformas que lo soportan mejor (como Erlang), y herramientas que llegan muy lejos (como Figwheel), pero todavía no son aptas para todos los públicos y queda muchísimo margen de mejora.

Son dos ejemplos concretos de líneas de investigación, una más teórica y otra de aplicación más directa que pueden contribuir mucho a incrementar la productividad de los programadores. ¿Serían avances revolucionarios? No lo sé. Puede que no, ¿pero por qué renunciar a ellos?

El valor de iterar

Por otro lado, no acabo de comprender esa crítica a iterar sobre los mismos problemas y obtener mejoras (solo) incrementales. Reinventar la rueda es más importante de lo que parece.

De hecho, me resulta especialmente curioso que todo un artesano de software, acostumbrado a hacer katas, es decir, solucionar una y otra vez el mismo problema para perfeccionar la forma de hacerlo, no vea el valor de reinventar la rueda.

No tiene sentido reescribir una y otra vez la misma aplicación que desarrollas profesionalmente sin aportar valor adicional, pero eso no quiere decir que implementar nuevas soluciones a problemas conocidos no aporte ningún valor.

Además del valor intrínseco del aprendizaje que conlleva hacer esas implementaciones, es frecuente que cada solución tenga caraterísticas ligeramente diferentes que la haga más adecuada para cierto tipo de problemas o mas agradable para determinados grupos de usuarios.

Por seguir con los ejemplos del post original, podríamos pensar que desarrollar React existiendo Angular no tiene sentido. Bueno, y que Angular, existiendo Ember tampoco lo tiene. Sin embargo, hay diferencias suficientes entre unos y otros como para que todos puedan convivir y aportar algo al mundo de las librerías y frameworks para desarrollo web.

Con lenguajes de programación pasa exactamente lo mismo. ¿Era necesario inventar C# existiendo Java? Pues hombre, necesario, lo que se dice necesario, a lo mejor no, pero negativo tampoco es. De hecho eso ha provocado que entre uno y otro se acaben retroalimentando, pero manteniendo cada uno sus diferencias. Lo que no tiene sentido (en general) es convertir una aplicación Java a C# por el mero hecho de reescribirla.

Conclusión

La idea de no dejarse llevar por la novedad y actuar de forma responsable y profesional en nuestros desarrollos me parece importante. Ahora que muchos andan corriendo de una tecnología a otra, siguiendo modas cada vez menos duraderas, me parece un mensaje de sensatez.

Sin embargo, desincentivar la innovación diciendo que “ya está todo inventado y no hay espacio para mejora” es un mensaje muy peligroso, y más viniendo de alguien cuya opinión todavía tiene mucho peso entre muchos profesionales de este sector. Es una excusa perfecta para cerrarse en sus lenguajes, arquitecturas, herramientas y metodologías de hoy “porque con ellas ya soy productivo y lo dice Uncle Bob”.

Veamos las cosas con un poco de perspectiva. No nos dejemos llevar por la modas, pero tampoco seamos tan arrogantes como para pensar que ya hemos dado con la mejor solución a todos los problemas existentes.

No hay posts relacionados.

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

Meta-Info

¿Que es?

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

rss subscripción

Sponsors

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

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

Idea: Juanjo Navarro

Diseño: Albin