Cálculo de valores en CSS3

En estos últimos tiempos la evolución y el trabajo que se está realizando en las nuevas tecnologías de CSS3 y HTML5 es asombroso.

Hoy descrubrí la función calc de CSS3 que esta soportada en los mas grandes browsers (o sea Firefox y Chrome… y tambien las ultimas versiones de IE)

Si bien gran parte de lo que se puede hacer también se hubiera podido hacer con LESS, para quellos que no queremos utilizar LESS o por algun motivo no lo creemos conveniente para algun proyecto o somos rehacios a mezclar LESS con javascript o simplemente no queremos, es una interesante y util alternativa.

Un ejemplo muy simple, imaginemos que tenemos una página cuyo backgroudn se extiende de lado a lado de la pantalla pero el contenido de la pagina debe estar limitado a 960 pixeles, Por ejemplo algo como la siguiente imagen en la cual estoy trabajando.

Ejemplo página centrada

Suelo crear un una estructura y un css de la siguiente manera

<!DOCTYPE html>
<html>
<head>
    <title>Contenido centrado</title>
    <style>
        .container { background-color: #eee;}
        .content { width: 500px;  margin: 0 auto; }
    </style>
</head>
<body>
<div class="container">
    <div class="content">
        Aca escribo el contenido que quiero limitar a un ancho fijo y que este centrado en la pagina
    </div>
</div>
</body>
</html>

Si bien esto no tiene nada de malo, y creo que la mayoría de los sitios terminan haciendo algo similar a esto, el tener dos divs es algo que hace ruido, o al menos a mi me hace ruido.

El problema es que uno de los divs no tiene ningun motivo más de ser, mas que ayudar al layout. Por una limitación de que no podía hacer las cosas de otra manera, terminaba agregando un div extra sin sentido alguno.

Esto me hace recordar mucho a utilizar las tablas para realizar el layout de las paginas. Si bien el tag div no tiene un significado semántico, dudo que este bien el ver páginas que tienen tags divs por miles de lugares. Desde mi punto de vista el sobre-uso de los divs no es mejor que el abuso que en un tiempo se le daba al tag Table.

Pero esa era la única forma que yo conocía de poder tener un contenido complejo centrado en un área que debía tener un fondo que abarcara un área mayor.

Hasta que descubrí calc(), el cual me permite realizar cuentas en CSS y poder así definir los tamaños dinámicamente y que conseguir de esta manera el mismo resultado.

La versión CSS3 de este mismo html, al menos hasta mi entendimiento actual, sería:

<!DOCTYPE html>
<html>
<head>
    <title>Contenido centrado</title>
    <style>
        .content {  
            padding-left: calc(50% - 500px / 2); 
            padding-right: calc(50% - 500px / 2);
            background-color: #eee; 
        }
    </style>
</head>
<body>
<div class="content">
    Aca escribo el contenido que quiero limitar a un ancho fijo y que este centrado en la pagina
</div>
</body>
</html>

En esta última versión, no hay un tag div extra lo cual me deja un poquito más feliz.

Obviamente los div seguirán siendo útiles. Pero esperemos que con esta y otras funciones cada vez tengamos que depender menos de ellos para layout y podamos usarlo para lo que realmente fue creado, que es agrupar contenido.

Ahora solo espero que var() se estandarice un poco más y sea implementado en varios exploradores y ahi si será divertido ver lo que se podrá lograr !

Grails Searchable con No-ORM y varios datasource

Estamos trabajando en un proyecto que tiene algunas peculiaridades, la más interesante de ellas es que convivimos con un modelo en hibernate considerando una estructura de tablas legacy (para lo que definimos un datasource adicional personalizado). El modelo del proyecto es más o menos así:

  • datasource directo a mongodb donde guardaremos todo nuestro modelo basado en documentos
  • datasource_Legacy donde tendremos las tablas antiguas del modelo ORM en una base de datos convencional – en nuestro caso SQL Server.

Nos encontramos, entonces, con la necesidad de hacer búsquedas dinámicas y flexibles. Tenemos experiencia con Searchable (que al día de hoy tiene poco mantenimiento sobre todo porque Lucene, la tecnología en la que se sostiene, es un proyecto ahora abandonado) así que optamos por eso como primera solución. A la larga, sabemos, tendremos que movernos a ElasticSearch o Solr.

En esta ocasión nos sorprendió encontrarnos con un error horrible de searchable cada vez que iniciábamos:

java.lang.IllegalArgumentException: No entities listed to be indexed, have you defined your entities correctly?

Bien, la respuesta fue simple. Configurar los los beans de Spring para que soporten el datasource personalizado adicional que teníamos. Resulta que automáticamente el plugin no recorre todos los datasource configurados. Basándonos en este post, la cosa sigue así.

(more…)

Locales no encontrados en Debian recién instalado

Estoy cansado de que cada vez que instalo Debian o algun otro Flavor, al querer instalar algunos paquetes, o hace runa actualización me salga el siguiente mensaje:

Can't set locale; make sure $LC_* and $LANG are correct!
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = "en_US:en",
	LC_ALL = (unset),
	LC_TIME = "es_AR.UTF-8",
	LC_MONETARY = "es_AR.UTF-8",
	LC_ADDRESS = "es_AR.UTF-8",
	LC_TELEPHONE = "es_AR.UTF-8",
	LC_NAME = "es_AR.UTF-8",
	LC_MEASUREMENT = "es_AR.UTF-8",
	LC_IDENTIFICATION = "es_AR.UTF-8",
	LC_NUMERIC = "es_AR.UTF-8",
	LC_PAPER = "es_AR.UTF-8",
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_ALL to default locale: No such file or directory

Por lo tanto investigué un poco y llegué a una solución que al menos a mi me ha funcionado siempre. Lo que tengo que hacer es ejecutar el comando: sudo dpkg-reconfigure locales

Luego cuando me pregunta seleccionar los locales que me dan error arriba. En este caso sería es_AR.UTF-8 (los que estaban antes seleccionados, dejarlos seleccionados)

Eso sería todo.

Espero la proxima vez que me suceda recordar este post y no perder media hora o más intentando encontrar la respuesta a un problema ya muchas veces resuelto.

BarcampBA 2013

El sábado pasado me pasé por el BarcampBA. Se que era un día hermoso como para estar al aire libre y todo eso, pero el BarcampBA es un lindo evento y me gusta lo que significa: da una charla de lo que sea. En el fondo, lo se, las charlas suelen ser sobre cuestiones tecnológicas. Pero no hay problema si uno quiere charlar sobre el crecimiento de rosas verdes en la antártida (si es que eso realmente existe), la propuesta es hacer un espacio abierto donde cada uno cuente lo que tenga ganas de contar.

En mi caso además de encontrarme con viejos conocidos y amigos, pasé por algunas charlas que me gustaría rememorar por aquí, a saber:

  • Intro Python: fue una charla que estaba por encima de su capacidad, así que decidí esquivarla
  • Bitcoin y otras Alcoins: acá también intenté ir, pero estaba repleta de gente. Quizás @sheinsha nos pase el material, ¿no? porque tuvo buena repercusión el asunto
  • Hacking Fisico Arduino y Accesibilidad: donde Maxi nos contó lo que había logrado con Arduino en escasos 6 meses y lo mucho que podría hacerse si uno le pone un poco de ganas.
  • Robots Humanoides: Acá me encontré con una investigadora (Marcela?) que nos contó sobre la historia de los robots hogareños, pasando por androides (de verdad, no los celulares) y como han ido evolucionando. Una “robota” que baila, otra que charla, el Asimo de Honda (con sus difrentes versiones), terminando con una terrible aberración de la naturaleza que cuesta 1 millón de dólares y me hizo recordar a los robots de Pacific Rim, Kuratas.
  • Raspberry PI: Acá llegué un poco tarde y tuve que ver la charla desde afuera, pero estuvo linda. Diego (es el nombre que me acuerdo) y <complete aquí> contaron lo que habían logrado con esta plataforma haciendo unos robotitos divinos 😛
  • Deep Web 101: fue la que hubiera querido ir, pero me perdí (era en un cuarto piso y no estaba muy bien señalizado) así que voy a pedir más información a ver qué fue lo que estuvieron charlando.
  • Como hacer un canal de Youtube y no morir en el intento: acá es donde terminé yendo, aunque no quería, me vino bien escuchar algunas experiencia de Nicolás con Suprapixel a la hora de hacerse fama en las redes sociales como Yotube.

Ya después de esto (que no fue mucho, el año pasado la hice bastante más intensiva) estaba agotado y me mandé a casa a descansar un cacho. Pero no por eso quiero dejar de hacer un rápido resumen:

  • Las charlas estuvieron todas bien. La gracia precisamente está en que la gente que las da, solo quiere contar lo que han estado haciendo. Nada más y nada menos. Es divertido porque no hay un orden crítico o una cuestión de prioridades.
  • Me enteré que había ciertas salas que se usaban como “SocialCamp” que vendría a ser contenidos relacionados con inclusión, compromiso empresarial, etc. Creo que va un poco en contra de la filosofía de “charlar de lo que te gusta” pero entiendo que hay gente que tiene particular interés en ver este tipo de charlas así que me parece bien darles un espacio.
  • Creo que hubo mucha gente. Demasiada. Las salas casi todas estaban sobrepobladas. Eso es una pena. Quizás habría que encontrar un lugar que tenga salas más grandes. (Alguna universidad?)
  • Me causó un poco de gracia ver que aquellos oradores humildes, que habían elegido salas pequeñas terminaban teniéndolas repletas (pero maaal) y aquellos que por ahí la temática era de mayor concurrencia, estuvieran vacías.
    • ¿Por qué es eso? – me pregunté – me imagino que los que asistimos a esos eventos queremos, precisamente, ver charlas sobre cosas que usualmente no veríamos en otro tipo de eventos. Ahí es donde está la gracia.

Hacía mucho que no escribía algo en el blog, pero este evento me parece que requería un mención por este canal. Además, nos quedará en la historia. Me gustaría el año pasado dar alguna charla, así que ya me tengo que poner a pensar qué. 🙂

pd: Muy linda la herramienta Kronos de flyering, le falta, pero es una linda iniciativa.

Novedades Julio 2013

Sínteticamente, los interesante desafíos en que andamos trabajando:

– La instalación del portal de minijuegos que estamos haciendo –www.tonojogo.com– mientras buscamos técnicas para optimizar el uso de ancho de banda y del servidor usando ASP.NET MVC4, signalR, BundleTransformer, así como CoffeeScript para la vista y un núcleo hecho en .NET 4.5 con SimpleMembership, MongoRespository y bases de datos SQL Server y MongoDB.

– Un nuevo sistema empresarial en el que venimos trabajando hace tiempo y que esperamos tenga la versatilidad de ser funcional para empresas de diversos rubrosy esta vez con el último milestone de Grails (2.3.0.M2), MongoDB y AngularJS.

…to be continued

APIs de Logging para C#

El jueves veíamos que al traer Quartz con NuGet también traía una librería llamada Common.Logging, descubrimos después que sigue una estructura similar a la que trae su homónimo en Java, commons-logging.
Tal vez los que estuvieran viendo cosas en Java ahora, les suene slf4j que sería como una evolución de commons-logging.
¿Qué ventaja tienen? commons, slf4j, etc son APIs que nos permiten construir código abstrayéndonos de quién sea nuestro logger por detrás así no obligamos a quien corra nuestra aplicación (o framework) en usar alguno y no otro.
En la historia, commons recorría el class-loader de la VM buscando la “mejor opción”, cosa que después dio lugar a slf4j que usa otro método de “scan” más veloz y menos conflictivo con librerías externas.
Por lo pronto, en búsqueda de agilidad, poco me importó usar commons en C#, creí que sería como en Java que se daría cuenta cuál es el mejor logger. Después de alguans pruebas, me di cuenta que si no la configurábamos y le decíamos que estábamos usando log4net lo que terminaría pasando es que todos los logs que recibiera no los trataría, sencillamente porque no sabría cómo.
¿Cuál fue mi problema? Quartz loggeaba a través de commons y, como no estaba configurada no podía ver su logging. Sin duda que esto podría pasar con otros frameworks.
Nota: Esto no estaba pasando con nhibernate, que usa directamnete log4net.
En resumen, siempre que esté dentro de sus posibilidades, tiendan a usar una API de implementación de logging que nos dará un código más flexible y no complicaría (para nada) nuestra forma de codificar. Después de todo, los framework de logging están basados en log4net (o log4j) que es en lo que estamos acostumbrados.

Consolidar estadísticas de varios dominios de una misma empresa

Aunque algunos ya lo saben, queríamos contarles que 3f ha pasado por un intenso proceso de nuevas experiencias lanzando en el último año dos ediciones de un producto al mercado, aliándose con publishers, publicando en stores y otro tantos desafíos que están a punto de ver la luz como un producto concreto para pequeñas organizaciones y un juego de estrategia con integración con Facebook.
Entre todo este conjunto de vertiginosas novedades, una de las cosas que logramos fue unificar las estadísticas de acceso a nuestros sitios Web. Todos los sitios que pertenecen a lo que nosotros disfrutamos en llamar: Universo 3f.
Imaginen un ejemplo fácil.
1. alguien entra al blog de 3f
2. después a la página de 3f
3. después a al página de Reversion
4. después nuevamente al blog
Desde GA (acrónimo de Google Analytics) estos son diferentes identificadores por medio de los cuales se puede determinar que el usuario estuvo O (1), P (2) , Q (3) segundos en cada página. Una baja cantidad de segundos habla de una baja permanencia y eso se traduce en alguien que entró a nuestra página y no le pareció interesante o fue una equivocación.
De hecho, hay una métrica que básicamente dice si nuestros usuarios estuvieron (o no) en el sitio un tiempo aceptable para leer o cayeron de carambola por error y no estuvieron interesados. Imaginen que el tiempo de cada una de las partes es siempre menor al total…
Ahora bien, sólo lo dicho no nos sirve a nosotros para entender a nuestros “usuarios”. En concreto, toda la gente que navega por nuestro universo no está yendo a otras páginas pero lo que nos interesa saber es desde dónde llegó y dónde estuvo más tiempo. Y también nos interesa saber el tiempo total que estuvo navegándolas.
Para eso, lo que hay que hacer es seguir los lineamientos que se explican aquí:
https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingSite
https://developers.google.com/analytics/resources/concepts/gaConceptsDomains
 
Y en el supuesto caso de que uno quiera filtrar dónde estuvieron los usuarios, se puede aplicar un filtro con el “domainName” al que realmente han accedido. De hecho, podemos llegar a ver por dónde entran y por dónde se van (cosa que antes no podíamos).
 
En nuestro caso: 3f-blog, 3f-site, reversion-blog, reversion-site, 3f-interactive
 
Si alguien sabe de alguna otra buena manera, nos dice… Por ahora, esto es lo mejor que se nos ocurrió.

 

Mi reflexión sobre Herencia Múltiple en Java 8

Este artículo lo envíe como una conversación interna en la empresa, pero me parece interesante compartir mi opinión al respecto. Esta reflexión mia nació luego de leer:

http://blog.loxal.net/2013/05/java-8-default-interface.html

Hace poco dije en un email que java me parecía un lenguaje que estaba quedando obsoleto.

Que carecía de muchas de las herramientas de le gustes más modernos e incluso de muchos implementados sobre su misma vm.

Esto es otro paso que me parece confirmar mi parecer. Herencia múltiple es un infierno que ya conocimos con C++ y ahora tendremos en la nueva versión de java.

Realmente es necesaria? Reconozco que dos o tres veces en la vida he deseado usarla…. pero alguna vez la use cuando disponía de ella?

Las pocas veces que la necesite en el mundo de java fue para poder reutilizar un comportamiento entre muchas clases no relacionadas por herencia, lo cual no se si es un buen argumento para la utilización de herencia múltiple.

Lenguajes más modernos utilizan mixins para ese motivo, que es una especie de herencia múltiple debo admitir, pero bastante diluida. Por que java no podía ir por ese camino?

Supongo igual que la herencia múltiple ayudará a spring, aspectj y otros frameworks además de lenguajes basados en la vm a optimizar sus implementaciones ya que se me ocurre que se podrían evitar varias magias y proxies con esta característica.

Pero espero no ver mucho de eso en la base de código de usuario.

Crossroad vs Sammy

Vamos a comparar dos plugins de javascript para manejar páginas web y crear lo que se conoce como single web aplication.

sammy-vs-crossroads

 

Para el caso de Crossroads

  • No ofrece un sistema en el cual le agregamos las rutas de nuestra aplicación.
  • Tiene un método llamado addRoutes, al cual le pasamos una regular expression, y de acuerdo a ciertas reglas, ejecuta una función que le pasemos.
  • Su mayor desventaja es que tenemos es que no se asocia automáticamente al cambio de la url, sino que lo hacemos manualmente. En ese lugar, tenemos que usar la función parse de crossroads.
  • Se usa window.history.pushState, que guarda en el location la dirección que deseamos sin recargar la página, pero es una característica de html5, y no está soportado en ie9.

Sobre Sammy

  • se monta sobre el hash del location, y se queda escuchando solo el cambio del hash.
  • Maneja solo el pushState, y en el caso de internet explorer ofrece una alternativa.
  • Para ejecutarlo dentro del sammy debemos definir los get con las variantes del hash que nos interesen (puede manejarse como si fuese una url y poner ‘/’ para separar secciones), y la función a ejecutar en cada caso.
  • Una vez definido, le damos run, en donde le podemos definir a partir de que hash arranca la aplicación

Conclusión: Sammy parece ser menos rebuscado y más usable. Crossroads está orientado a un tipo de proyecto que aún no hemos tenido que hacer. 😉

Oracle Java (JDK 7) en Debian 6 (squeeze)

Estamos reconfigurando nuestros servidores en vísperas de los nuevos lanzamientos que tenemos agendados para el 2013. Así que ahora tocó la hora de reconfigurar un servidor Debian con la última versión del JDK de Oracle.

¿Por qué usar la de Oracle? a pesar que muchos critican a Oracle por su constante adquisición de empresas (y Sun no es la excepción de ahí la crecida comunidad generando nuevos proyectos fuera de ese contexto como MariaDB) en nuestro caso los diferentes equipos de desarrollo están usando siempre la última versión del JDK de Oracle, entonces, preferimos mantenernos con esta versión para evitarnos inconvenientes. Consistencia es una de las cualidades que preferimos.

¿Cómo instalar en Debian? He de confesar que una vez que uno entiende cómo hacerlo, el procedimiento es bastante sencillo. Si quieren una versión super archi resumida del asunto, pueden seguir los pasos descriptos aquí.

Primero que nada, descargar la última versión del JDK – http://www.oracle.com/technetwork/java/javase/downloads/index.html. En mi caso jdk-7u11-linux-i586.tar.gz.

Seguir los siguientes pasos en la línea de comandos.

# Descomprimirlo (estamos ubicados en el directorio donde pusimos la descarga)
tar -xvf jdk-7u11-linux-i586.tar.gz
# Crear directorio para todas las versiones de java
mkdir /usr/local/java
# Mover el directorio descomrpimido
mv jdk1.7.0_11 /usr/local/java
# Configurar Debian para que sepa donde pusimos Java
update-alternatives --install /usr/bin/java java /usr/local/java/jdk1.7.0_11/bin/java 1065
update-alternatives --install /usr/bin/javac javac /usr/local/java/jdk1.7.0_11/bin/javac 1065
update-alternatives --install /usr/bin/jar jar /usr/local/java/jdk1.7.0_11/bin/jar 1065
update-alternatives --install /usr/bin/javaws javaws /usr/local/java/jdk1.7.0_11/bin/javaws 1065
# Configuramos el default de java
update-alternatives --config java
# Si solo tenemos uno, el mensaje sería:
# -> There is only one alternative in link group java: /usr/local/java/jdk1.7.0_11/bin/java

¿Cómo verificamos la instalación? Fácil

java -version

Deberíamos ver

java version "1.7.0_11"
Java(TM) SE Runtime Environment (build 1.7.0_11-b21)
Java HotSpot(TM) Server VM (build 23.6-b04, mixed mode)

Y si queremos lujo, podríamos configurar los bash, agregando en el /etc/bash.bashrc

$ vi /etc/bash.bashrc
export JAVA_HOME=/usr/local/java/jdk1.7.0_11
export PATH=$PATH:$JAVA_HOME/bin

Y para que quede todo bien, configuramos usando

source /etc/bash.bashrc
source ~/.bashrc

Con eso estamos… 😉