Departamento de Sistemas organizado en Círculos, Comunidades u Holocracia… ¿De verdad sirve?

La holocracia es una forma de organización de las empresas que consiste en la conformación de círculos o comunidades autogestionables, cada comunidad tiene un propósito, un dominio y un conjunto de responsabilidades bien definidas y está conformado por un conjunto de individuos que pueden asumir uno o mas roles. Estas comunidades, si bien son autogestionables, no son autodirigidas. Son dirigidas por una comunidad mayor, con el objetivo de que los esfuerzos estén orientados hacia la misma misión y visión, pero cada círculo es libre de organizarse de la mejor manera para alcanzar sus objetivos y cumplir sus responsabilidades.

¿Suena bien no? Pero, ¿como nace? ¿cuando es necesario? ¿cómo se implanta?, ¿cómo se puede hacer la transición? ¿se ven resultados inmediatos? Me extendería mucho explicando todo esto, sin embargo, afortunadamente, te tengo dos casos de estudio, el primero (Snapper, empresa de servicio de emisión de tickets en Nueva Zelanda), aplicado en una organización en el primer mundo, y el que te voy a contar, vivido en persona, en un país en vías de desarrollo, bajo un contexto económico social bastante desastroso.

Los inicios

Hace 2 años y medio que el anterior CIO de la empresa organizó el departamento en comunidades, el área conformada por cerca de 40 colaboradores, se dividió en 7 comunidades. La iniciativa fue presentada ante directivos quiénes dieron su aprobación y ante el equipo.

Esta forma de trabajo se fijó bastante rápido tanto en quienes conformaron cada comunidad, y nuestros clientes de igual manera comprendieron rápidamente nuestra nueva forma de organización y competencias. En menos de dos meses se creó la cultura de trabajo bajo los principios en la que esta se fundamenta. Quizás esto se deba a la naturalidad humana de trabajar en equipo desde la época en que o lo hacíamos, o nos devoraban los dinosaurios.

¿Por qué tuvimos que organizarnos de esta manera?

Las estructuras jerárquicas y burocráticas, donde un requerimiento pasa días mientras es canalizado por un jefe y escalado a sus subordinados, son el enemigo de un departamento de TI que busca ser ágil y dar respuesta, no en días sino horas.

Con las comunidades, los cargos pasaron a un segundo plano cuando la nueva estructura organizativa hizo énfasis en roles y las responsabilidades de éstos. Cada comunidad tiene un líder y todos los miembros pueden ser el líder en cierto momento.

Los requerimientos de prestación de servicio se encaminan mucho mas rápido, cada comunidad sabe qué le compete, que no y a quién otro sí; propiciando la gestión correcta del requerimiento; el tiempo de respuesta, dependerá de la agilidad de sus miembros.

Los resultados

La comunicación horizontal permitió llevar el equipo a un nuevo nivel. El tiempo de gestión de requerimientos se redujo considerablemente. Los proyectos inician mas rápido y finalizan con mayor tasa de éxito. El ambiente de trabajo es mas cálido, dinámico y competitivo.

A su vez, se crea y reforza en la persona el sentido de pertenencia, y llega a reconocer la importancia de sus habilidades y competencias, independientemente del rol que tenga dentro de la comunidad, creando consciencia de que su trabajo es apreciado directamente por quiénes envían los requerimientos y por el resto del equipo. En síntesis, es una de las estructuras organizativas que permite reforzar el compromiso.

Manteniendo el orden

De igual manera, toda estructura auto-organizada, adquiere independencia en la toma de decisiones, independencia que debe estar normada, supervisada, mas no controlada. Esta es la responsabilidad de una comunidad de gestión.

Si tienes consultas adicionales, o quisieras que adentremos mas en el tema, me lo puedes hacer saber en los comentarios.

Hoy en día, quizás te interese conocer, que estamos haciendo un experimento de expansión en escala, partiendo de esta estructura. De 40 personas, a más de 200 ¿Será posible? ¿Funcionará? ¿Deberá cambiarse algo, todo o nada?

Les cuento en la medida que vaya ocurriendo…

 

 

 

Acerca del Mobilegeddon y la forma en que Google cambió la búsquedas generales, móviles y locales

Lo único constante con el marketing es el cambio

Con esa frase inicia una de las ponencias a las que asistí en Orgill el año pasado. En el 2015, ocurrió una serie de eventos en la Web denominado por varios nombres pero quizás el mas común es el Mobilegeddon. Se habló específicamente de cómo Google muestra ahora los resultados móviles y locales. Sin embargo, he querido enriquecer este post añadiendo información importante sobre otros cambios realizados en el motor de búsqueda que considero forman parte de ese armagedón web.

El de 21 de Abril del 2015 Google cambió la forma en qué los resultados de las búsquedas se mostraban en los dispositivos móviles. Lanzó un nuevo algoritmo de rankeo que dejó varias páginas fuera por no estar preparadas para su navegación móvil o no ser lo suficientemente responsive. Sin embargo, ser responsive es sólo uno de los tantos criterios que el algoritmo evalúa. Otras características como relevancia, localización, idioma, entre otros, son características también evaluadas.

Ocupando en el 2017 el 77% de share en los motores de búsqueda empleados, y considerando que cerca del 60% de las búsquedas se realizan ahora desde un dispositivo móvil, que tu sitio quede fuera del ranking no es gracioso para algunos (más estadísticas, acá).

Muchas preguntas salieron a la luz por parte de los afectados cuyos resultados ya no aparecían en el ranking de Google. Para eso, Google preparó en su blog un FAQ a modo de explicar con detenimiento de qué van estos nuevos cambios. Una de las aclaratorias que realiza es que el ranking solo varía en dispositivos móviles pero en equipos de escritorio y tabletas, se mantiene. También indica que no excluye del ranking portales que no sean mobile responsive, pero deben tener contenido relevante para su visibilidad (acá escribí algo al respecto de esto último).

La siguiente herramienta de Google permite validar que tan mobile responsive es un sitio Web.


Las búsquedas en Google son gobernadas por sofisticados algoritmos como el Panda, liberado en el 2011 y su última versión a a la fecha 18 de Julio de 2015. Este algoritmo tras su lanzamiento en el 2011 eliminó en sus resultados cerca del 12% de sitios indexados. El algoritmo busca entre varias cosas, mejorar el indexado de sitios de calidad, sacando así de sus resultados sitios pocos relevantes o con contenido de mala calidad. Dentro de esta categoría entran aquellos que usurpan información de otros sitios.

En combinación con el algormitmo Penguin, actualizado en Septiembre del 2016, el cual busca eliminar de los resultados sitios spam o de contenido robado, hacen que la web sea cada vez mas segura, eficiente y relevante.

Por su parte, el RankBrain, también liberado en el 2015, emplea minería de datos para ofrecer resultados a los usuarios de sitios que puede que posean la información que están buscando a pesar que las palabras o frases empleadas no hagan referencia directa al resultado. Según Google, 15% de los resultados exitosos provienen de esta inteligencia articifial.

El 3 de Agosto del 2015 también cambió internacionalmente la forma en que Google recomienda los lugares mas próximos o relacionados a la búsqueda realizada. Se pasó de una vista casi plana de 7 lugares a una de solo 3 lugares, denominado “3-pack”, acompañado de la vista en un mapa de Google Maps. Con eso Google sacó al 60% de los resultados sobre los cuales el usuario presta atención de manera inmediata.


Todos estos cambios tuvieron lugar en un lapso menor de 12 meses. Continuamente los buscadores realizan cambios o mejoras en sus portales, algoritmos, infraestructura, pero rara vez ocurre uno de tal magnitud que cambia las reglas de juego de tal forma.

Los lineamientos y demás consideraciones del área de SEO, son actualizados con frecuencia en la medida en que quienes dominan la búsqueda de resultados realizan cambios en su plataforma. Es por ello que no hay que dejar a un lado las optimizaciones y herramientas que podamos emplear en nuestros sitios con el objetivo de competir por esa posición dentro de los resultados de búsqueda.

Compartí un Post con mis compañeros de trabajo, y quedé como el malo

 

Y no es la primera vez que ocurre. Mi papá siempre dice que nací para llevarle la contraria al mundo, y cuando dice mundo se refiere a él y a sus absurdas aseveraciones o normas sin fundamento.

De manera natural en casa se fué formando en mí esa necesidad de no aceptar las cosas tal cual son o que tratan de imponer sin una explicación objetiva, o al menos una evaluación crítica. “Eres demasiado terco”, “Es lo que tu dices y yá”, “Eres demasiado necio”, “Eres demasiado imbécil”, “Te encanta el caos”, entre otras frases de ‘defensa’ cuando no logran mi aceptación… al que le importe mi aceptación.

Este post describe un fenómeno que me encanta. El autor llama una nueva tendencia de desarrollo de software basado en la ‘moda’. Yo lo traduzco como desarrollo basado en emociones. En general, los desarrollos basados en emociones son aquellos cuando tomas X tecnología nueva porque has visto muchos posts en twitter o blogs referente a ella, la mencionan en conferencias, o Facebook o Netflix estan haciendo uso de ellas, y entonces decides emplearla para tu siguiente proyecto en el trabajo o startup, solo por eso, porque es lo nuevo y cool.

Chévere, pero luego ocurre lo siguiente:

  • La tecnología no es sencilla de entender porque es todo un paradigma nuevo, tu proyecto se retrasa, se retrasan las entregas, y se frustra el equipo.
  • Estas en medio del proyecto y ya existe una nueva versión que depreca cerca del 80% de lo que ya has hecho pero era un cambio necesario para madurar el nuevo framework del que todos hablan. Toca hacer todo de nuevo.
  • Diseñaste toda una solución basado en premisas y documentación y la hora de implementar las promesas de funcionalidades, velocidad y estabilidad que tanto presumían en realidad no están ahí.

Personalmente me encanta siempre probar nuevas cosas, de manera crítica, y comparando contra lo que ya conozco. En el trabajo he introducido tecnologías de integración que hoy sustentan gran parte de la automatización de la cadena de valor del negocio. Y cuando lo hice, fue porque previo a eso ya había probado otras alternativas, y empleando un análisis de características. Otro compañero de equipo probó varias soluciones para el desarrollo de aplicaciones móviles antes de elegir el enfoque que la nueva generación ha heredado. Pero esto solo lo saben mi antiguo jefe, compañeros de trabajo y yo.

Hoy por hoy, de mi grupo inicial de trabajo quedamos solo tres, y hay cerca de 30 personas mas jóvenes, igual de emocionados y enérgicos en probar nuevas cosas.

Recientemente se eligió emplear dos tecnologías emergentes para dos nuevos desarrollos, se han hecho mesas de trabajo alrededor y se ha empleado mucho tiempo realizando pruebas y prototipos. Todo muy bien salvo por eso último, mucho tiempo empleando pruebas y prototipos y cuando pregunté cuál es la opción B contra la que van a comparar sobre qué van a decidir usar obtuve esto: “Bueno, creemos que no hará falta una opción B”

Wrong, really Wrong

Compartí entonces el artículo que les menciono al inicio con el siguiente mensaje en el asunto del correo “Leamos de manera crítica y revisemos nuestras recientes decisiones”.

A la mañana siguiente: “Por qué eres así?”, “Estas creando caos”, “Solo porque no fue tu idea…”.

Recibí muchas acusaciones que solo confirmaban que los acusadores no habían leído el artículo por completo. El mismo, al final, detalla varias estrategias para que los desarrollos basados en emociones salgan exitosos y saber bien que esperar antes de realizar un plan de trabajo y propuesta de producto.

Me decepcionó horrible los juicios levantados contra mi intención de ayudar, pero me reconfortó que algunos si leyeron por completo el post y los vi estableciendo nuevas tareas que se desprenden de esas estrategias dentro de la programación del proyecto.

Mi mantra como desarrollador, evangelizador de tecnologías y gerente de proyectos de software es muy sencilla: no hay que reinventar la rueda, ya todo esta hecho, solo hay que descubrirlo, probarlo y usarlo.

Cómo configurar la conexión a SQLServer mediante JDBC (NetBeans, Java 8, SQLServer Express 2016, Windows 10…)

Nunca antes, luego de haber aprendido cómo conectarme a distintas bases de datos mediante JDBC, me había costado tanto una como lo fue con SQLServer (casi 15 minutos). Gracias a Google, Stack Overflow y conocimiento previo salió medianamente rápido, pero vamos, que a esta gente le gusta complicar a veces las cosas.

Archivo de propiedades de conexión (config.properties)

Ya sabemos que es de muy mala educación, y prohibido además, hard-codear valores o atributos que pueden cambiar en el tiempo de una computadora, una red, etc… a otra; entre ellos las propiedades de conexión a una base de datos. Es por eso, que lo ideal es colocarlo en un archivo de propiedades como los que estamos acostumbrados a hacer:

#Ubicado en src\res\config.properties
db.url=jdbc:sqlserver://servidor\\SQLEXPRESS;databaseName=nombre_bd;integratedSecurity=true
db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
db.user=usuario
db.password=clave

Respecto a los valores db.url y db.driver, recordemos que cada manejador de base datos  (o DBMS, como quieran llamarlo) tiene su forma de establecer estos valores, los que les indico funcionan con SQLServer Express 2016; acá mucha mas información respecto a cómo formar la url.

Y una clase en Java sencilla que lo lea:

package th.control.db;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

/**
 *
 * @author jescobar
 */
public final class DBConnection {
 static InputStream inputStream;
 static Connection conn;
 
 public static void connect() throws Exception {
 inputStream = Class.forName("th.control.db.DBConnection").getClassLoader().getResourceAsStream("config.properties");
 
 Properties prop = new Properties();
 
 prop.load(inputStream);
 
 
 Class.forName(prop.getProperty("db.driver"));
 conn = DriverManager.getConnection(
 prop.getProperty("db.url"), 
 prop.getProperty("db.user"), 
 prop.getProperty("db.password"));
 
 System.out.println("Me conecté!!!");
 }
}

Todo bien, compila al pelo, pero al ejecutar un indeseado java.lang.NullPointerException te aparece en la línea donde intentas cargar el archivo de propiedades mediante el método prop.load(inputStream).

run:
Exception in thread "main" java.lang.NullPointerException
 at java.util.Properties$LineReader.readLine(Properties.java:434)
 at java.util.Properties.load0(Properties.java:353)
 at java.util.Properties.load(Properties.java:341)
 at th.control.db.DBConnection.connect(DBConnection.java:26)

El punto es que ni NetBeans ni Eclipse te van a decir dónde colocar el archivo para que sea leído, debes especificar en cada IDE que rutas incluir en el classpath. En NetBeans una solución sencilla es moverlo al directorio src.

#Ubicado en src
db.url=jdbc:sqlserver://servidor\\SQLEXPRESS;databaseName=nombre_bd;integratedSecurity=true
db.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
db.user=usuario
db.password=clave

Ahora tu problema va a ser otro…

Colocando donde es el Driver de conexión

Yo estoy partiendo de que ya te habías descargado el driver JDBC de Microsoft, bien sea el sqljdbc41.jar o el sqljdbc42.jar (clic acá si no lo has hecho) para conectarte con su BD, creaste un directorio lib en el proyecto, y ahí lo metiste. Pero al tratar de ejecutar, recibes otro mensaje de que no vas…

run:
Exception in thread "main" java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
 at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:264)
 at th.control.db.DBConnection.connect(DBConnection.java:29)

Y es que tienes que decirle a NetBeans donde estas colocando tus librerías externas. Algo así logras presionando sobre el botón “Add JAR/Folder” y especificando la ruta que visualizas en la imagen.

002

Y con lo anterior, al tratar de ejecutar… Cambiamos de problema! Uno mas de no sabemos cuantos mas… Pero lo que si sabemos, que como todo, es que en algún momento ya no habrán.

Ahora la librería que colocamos nos está diciendo que no logra conectarse con el servidor SQLServer…

run:
Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: No se pudo realizar la conexión TCP/IP al host localhost, puerto 1433. Error: "Connection refused: connect. Verifique las propiedades de conexión, compruebe que hay una instancia de SQL Server ejecutándose en el host y aceptando las conexiones TCP/IP en el puerto y compruebe que no hay ningún firewall bloqueando las conexiones TCP en el puerto.".
 at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:191)
 at com.microsoft.sqlserver.jdbc.SQLServerException.ConvertConnectExceptionToSQLServerException(SQLServerException.java:242)
 at com.microsoft.sqlserver.jdbc.SocketFinder.findSocket(IOBuffer.java:2369)
 at com.microsoft.sqlserver.jdbc.TDSChannel.open(IOBuffer.java:551)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1963)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1628)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1459)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:773)
 at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
 at java.sql.DriverManager.getConnection(DriverManager.java:664)
 at java.sql.DriverManager.getConnection(DriverManager.java:247)
 at th.control.db.DBConnection.connect(DBConnection.java:30)

Acomodando las cosas para que SQLServer escuche

No tiene sentido que si usas el Microsoft SQL Server Management Studio, y ahí puedes hacer lo que te plazca (creates, updates, inserts, tanto de datos como esquemas, bases de datos, etc…) si tratas de conectarte desde otra aplicación, estén las puertas cerradas. Para abrirlas hay que hacer lo siguiente:

En una línea de comandos (cmd), o desde el comando ejecutar (Tecla Win + R), ejecuta los siguiente:

 C:\Windows\SysWOW64\SQLServerManager13.msc

Se te abrirá una ventana como la siguiente (yo ni sabía que existía). Es el SQL Server Configuration Manager.

001

Y tal como muestra la imagen siguiente, habilita las comunicación TCP/IP dentro de Protocolos de SQLEXPRESS.

003

El SQL Server Configuration Manager te va a decir que necesitas reiniciar el servicio para que los cambios tomen efecto, la siguiente imagen te indica cómo hacerlo.

004

Le damos play a la clase y…. Otra excepción… Lo bueno es que esta nos dice explícitamente que hacer!

run:
Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: No se pudo realizar la conexión con el host localhost, instancia con nombre sqlexpress. Error: "java.net.SocketTimeoutException: Receive timed out". Verifique los nombres del servidor y de instancia, compruebe que no hay ningún firewall bloqueando el tráfico UDP al puerto 1434. Para SQL Server 2005 o posterior, verifique que el servicio SQL Server Browser se está ejecutando en el host.
 at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:191)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.getInstancePort(SQLServerConnection.java:5247)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.primaryPermissionCheck(SQLServerConnection.java:1871)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1608)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1459)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:773)
 at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
 at java.sql.DriverManager.getConnection(DriverManager.java:664)
 at java.sql.DriverManager.getConnection(DriverManager.java:247)
 at th.control.db.DBConnection.connect(DBConnection.java:30)

Nos dice que verifiquemos que un fulano servicio llamado SQL Server Browser debe estar iniciado. Y si revisamos la última imagen, hay algo ahí llamado igual. No hace falta imagen para esto sino sentido común: Clic derecho -> Iniciar… Play de nuevo!

run:
feb 05, 2017 9:59:38 AM com.microsoft.sqlserver.jdbc.AuthenticationJNI <clinit>
ADVERTENCIA: Failed to load the sqljdbc_auth.dll cause : no sqljdbc_auth in java.library.path
Exception in thread "main" com.microsoft.sqlserver.jdbc.SQLServerException: Este controlador no está configurado para la autenticación integrada. ClientConnectionId:056b6f27-b750-4a8d-bda7-188d11f2aae9
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:2400)
 at com.microsoft.sqlserver.jdbc.AuthenticationJNI.<init>(AuthenticationJNI.java:68)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.logon(SQLServerConnection.java:3132)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.access$100(SQLServerConnection.java:43)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection$LogonCommand.doExecute(SQLServerConnection.java:3123)
 at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7505)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2445)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1981)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:1628)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1459)
 at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:773)
 at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1168)
 at java.sql.DriverManager.getConnection(DriverManager.java:664)
 at java.sql.DriverManager.getConnection(DriverManager.java:247)
 at th.control.db.DBConnection.connect(DBConnection.java:30)

Ok, esto sigue descontrolado! Y ahora qué?

Bueno, resulta que Microsoft permite dos maneras de conectarnos con su base de datos, y eso se lo decimos en el archivo de configuración. El parámetro integratedSecurity (integratedSecurity=true) indica si se usan las credenciales de Windows para conectarnos o si por el contrario, debemos especificar un usuario o contraseña (integratedSecurity=false), tal cual estamos haciendo. En otras palabras, SQLServer se esta pasando por el forro nuestro usuario y clave porque está usando nuestras credenciales de Windows para iniciar sesión…

Hay dos soluciones para esto… La que puedes inferir en el párrafo anterior (coloca en false el valor de integratedSecurity), o la otra, localizar el bendito sqljdbc_auth.dll y pegarlo en la carpeta System32 de Windows. Ambas funcionan, y el fulano .dll está en el mismo archivo donde bajaste los drivers JDBC de SQL Server hace unos parrafos mas arriba.

Cuando ejecutes de nuevo tu clase, este será el mensaje que obtendrás:

run:
Me conecté!!!

Saludos!

Éxito de Visibilidad Web de acuerdo a Web.com

Cómo les comenté en el reciente post, tuve la oportunidad de asistir a un seminario dictado por la gente (en realidad no recuerdo el nombre del expositor, sorry) de Web.com, empresa la cual según Wikipedia, tiene mas de 3 millones de clientes a quienes ofrece asesoría de posicionamiento Web, entre otros servicios.

Visibilidad o posicionamiento Web, en pocas palabras, es hacer que los buscadores coloquen tu portal dentro de los primeros resultados ante una búsqueda. Existe una rama de la informática dedicada a esto y muchos factores influyen en el mejoramiento del ranking de tu portal.

En la sesión explicaron un conjunto de premisas que pueden llevar a mejorar la visibilidad Web de tu negocio si las cumples. El target principal eran pequeños y medianos comerciantes; Durante la sesión, pocos tenían ya un portal Web, la mayoría estaban interesados en tener uno.

Algunas de estas premisas parecen triviales, otras no tanto. A continuación las menciono dando mi aporte crítico de cada una:

  1. Información de contacto de rápido acceso. Sin navegar mucho por el portal, el cliente debe ser capaz de identificar teléfonos de contacto, dirección y horas de trabajo. Hacer esto permite que los buscadores Web que ofrecen esta información en sus resultados de búsquedas indexen con mas rapidez el portal. Muchos portales lo ofrecen al pie de página (ej. https://airandspace.si.edu/), otros requieren entrar en una ficha de horario o contacto. En mi opinión la posición ideal es que esté dentro del área principal de visualización. Si tienes sucursales, una sección de Tiendas o Stores es ideal (ej. http://www.epa.biz/ve/tiendas/).
  2. El contenido no debe estar amontonado. Nada molesta mas que mucha información mal presentada, el exceso puede frustrar al visitante y también al motor de indexado de los buscadores. El espaciado es importante y el contenido debe ser de fácil lectura, claro y conciso. El contenido es el Rey… Repetirse siempre lo último.
  3. El contenido debe ser relevante. No tiene sentido hablar de noticias locales en el portal de tu súper mercado. Tiene mas sentido presentar recetas o información sobre festivales gastronómicos. Un ejemplo de alguien que lo esta haciendo mal… http://www.kromimarket.com. Playlists musicales en el área de noticias?!  Alguien que lo hace bien… http://www.ecomarket.com.ve. De nuevo, el contenido es el Rey.
  4. Tu portal debe ser ‘responsive’. Es decir, debe visualizarse bien en cualquier dispositivo o tamaño de pantalla. Por ejemplo, abre este blog que estas leyendo en un smartphone, luego en una tablet y luego en una PC. La forma de presentación se adapta para una mejor visualización. Google te mostrará portales que se ven bien en smartphones si la búsqueda la realizas desde uno.
  5. Tu portal debe estar optimizado. Flash, videos incrustados, imágenes de alta resolución, a todo esto NO. Un portal optimizado solo contiene texto, un arte hecho a base de CCS y HTML5 e imágenes optimizadas para la Web. El 72% de los usuarios acceden a la Web desde su móvil para realizar búsquedas; por lo que este punto y el anterior son importantes para ahorrarles datos y visualizar de manera rápida lo que a través de tu portal quieres ofrecer.
  6. La experiencia del usuario es importante. Imágenes de fondo que se deslizan, presentación presentada en tarjetas o secciones que se expanden al posicionarse sobre ellas, todas estas interacciones, bien usadas, llaman la atención y tienen un propósito.
  7. Buena organización. Tópicos, categorías, departamentos. La organización del portal debe guiar al visitante quien es un cliente potencial.
  8. Si quieres visibilidad mas rápida, paga por ello. Contrata servicios de publicidad Pay per Clic.

Si quieres saber mas de visibilidad Web, una rápida búsqueda del término ‘SEO’ en Google en conjunto con otras palabras (curso, tutorial, entre otros), te llevarán a contenido mas específico, y hasta diplomados y cursos universitarios de ello.

 

 

Problemas de desempeño mas comunes en Java… Y en cuáles he caído desarrollando en plataformas móviles: El N+1

Recientemente me hice con un entretenido e-book de AppDynamics donde se presentan un conjunto de 1o problemas con los cuales estoy seguro todos nos hemos enfrentado cuando estamos realizando estas maravillosas y extensas aplicaciones en Java que nos toma meses construir y las mismas una vez que las ‘inauguramos’ empiezan a caer, colgarse y molestar a nuestros usuarios.

¡Javier, esto es muy lento! Dime de una vez si me regreso a mi formulario en papel…

Mi mayor experiencia en Java empezó refactorizando una aplicación de ventas que se ejecuta sobre la máquina virtual de Java de IBM (J9) en la plataforma Windows Mobile. Para aquella entonces, los dispositivos basados en procesadores de 600 Mhz y apenas 256 MB de Ram de los AS400 que empleábamos daban la batalla en durabilidad para las manos pesadas y descuidos a los que estaban sometidos por la fuerza de venta; sin embargo, debido a sus limitados recursos, el código tenía que ser mas que eficiente en uso de memoria y el tiempo de respuesta de la aplicación era crítico para perder o ganar una venta.

Posterior a eso, la era de Android. Equipos doble núcleo, gigas de memoria, ¡mucho poder! Pero en un mercado emergente y socialmente peligroso como en el cual se desenvuelve nuestra fuerza de ventas, el vendedor no puede andar si quiera con un Galaxy S5 sin estar expuesto a un asalto y tampoco es viable para la empresa equipar a mas de 900 ‘asesores comerciales’ con un smartphone cada mes por situaciones como estas.

La aplicación debe ser rápida y ejecutarse en cualquier ‘aparatico’ que no pase de 70USD

Muchos de los problemas de desempeño a veces los solucionamos empleando sentido común, pero no descarto también golpes de suerte probando eso o aquello conseguido en Internet.

El e-book que les comparto distribuye en cuatro categorías los problemas de desempeño en desarrollos basados en Java: base de datos, memoria, concurrencia, y ‘descuido’. Este último no se llama así como tal, pero lo he tropicalizado. Los mismos están medidos por la magnitud del impacto que pueden causar en el desempeño de la aplicación, muestra patrones que permiten identificarlos y lineamentos para resolverlos. Son muchos como para estar en un solo post así que habrá mas de una publicación de este tema en este blog.

Problema ‘Muerte por 1000 Cortes’. El problema N+1 de Base de datos

Confieso que el nombre me llamó la atención y lo que leí en Wikipedia me dejó un mal sabor del café que me tomaba mientras les redactaba esto.

Ocurre cuando nuestra aplicación se vuelve lenta por el uso excesivo de la base de datos a través de accesos individuales. Es mas común en procesos transaccionales y tiene lugar cuando utilizas un número elevado de consultas cuando lo mismo lo puedes hacer con solo dos.

Por ejemplo, el vendedor con su dispositivo puede atender alrededor de 60 clientes al mes que tiene asignado. Un vendedor puede tomar en promedio al día cerca de 10 pedidos de unas 25 líneas a clientes distintos. En un mes puede hacer en promedio 5.000 líneas de pedido; y en total, los 900 vendedores de la empresa pueden hacer 4.500.000 líneas al mes.

Obtener las ventas realizadas a un cliente entonces, durante toda su vida pudiese hacerse ‘de mal manera’ así:

select id_pedido from pedido where id_cliente = $el_cliente

select * from pedido_detalle where id_pedido = 1

select * from pedido_detalle where id_pedido = 2

...

select * from pedido_detalle where id_pedido = n

La solución a este problema es sencilla, de hecho, seguramente la mayoría de quienes lean esto preguntarán ¿por qué no se hace así?:

select id_pedido from pedido where id_cliente = $el_cliente

select * from pedido_detalle where id_pedido in (1, 2, ..., n)

¿Cómo identifico que esto está sucediendo?

  • La aplicación responde lentamente obteniendo información.
  • Si cuentas el número de consultas que haces a la base de datos y lo comparas con el número de ítems del negocio siendo procesados, encontrarás una relación cercana de 1 a 1.

¿Qué me pasó a mi?

Cuando desarrollas para plataformas móviles, siempre debes tener en cuenta también algo: memoria.

Hice que la aplicación que carga lentamente los pedidos muestre un mensaje de “Espere por favor”para que el usuario’pierda un poco menos’ la paciencia mientras se analizaba el problema. El problema N+1 estaba en el código obteniendo todos los pedidos con una consulta a la base de datos pero instanciando las líneas de cada pedido con una consulta a la vez. Se solucionó la lentitud con una sola consulta, Join de pedidos y detalle de pedidos, la respuesta era inmediata pero mas temprano que tarde un java.lang.OutOfMemoryError aparecía de vez en cuando.

Esto no lo entendía puesto que la forma anterior debería ocasionar el mismo problema. Esto no era así porque en otra sección del código, luego de recuperar el pedido deseado, los detalles no utilizados eran descartados (se liberaba memoria) pero vueltos a cargar al volver a la pantalla anterior (lentitud de nuevo… pero funciona).

Cuando trabajas con poca memoria se debe analizar el impacto de la solución. La selección de únicamente los id del pedido que se necesitaban para instanciar los detalles y la consulta de únicamente las columnas necesarias para la instanciación de los detalles solucionó el problema. Eso, y por supuesto, no descartar las líneas de los demás salvo cuando se cambie de cliente.

El problema recién descrito parece ser trivial, pero no se asombren de si de vez en cuando pecan de hacerlo porque fue la solución rápida, la máquina donde se ejecuta tiene el poder para eso, o simplemente llevamos días sin dormir y el trabajo tenía que terminarse como fuese.

En un próximo post seguimos con dos problemas mas de desempeño relacionados con bases de datos  y Java.