NOTICIA
NOTICIA
NOTICIA
NOTICIA
NOTICIA
Tanto entre mis alumnos, como en las conversaciones con otros compañeros del sector, percibo siempre la duda de la necesidad o conveniencia de migrar al Cloud. Y, ciertamente, no es algo sencillo de explicar.
Muchas veces se generan intensos debates sobre si es una moda, una técnica comercial de las multinacionales para “sacarnos los cuartos” o un camino irresistible al que mejor no presentar una excesiva resistencia.
Por ello, en este artículo quiero resumir los orígenes, razones, procesos y características de los diferentes senderos que deberé recorrer para desplegar mis aplicaciones y servicios en la Nube.
El Porqué de migrar a la nube
Tengo muy claro -al iniciar el camino hacia el Cloud- que el principal motor para abordar los costes y esfuerzos debe ser un modelo de negocio claro, donde la adopción de la Nube se signifique como un mecanismo para incrementar la productividad. Es decir: al Cloud se va a ganar dinero.
No es buena idea que aborde el aprovecharme de las posibilidades de una infraestructura a la que tendré acceso, si el coste por su uso no es cubierto por un incremento de beneficios o la optimización de los costes.
La pregunta no es porqué, realmente es cúando.
Debo tener en cuenta que, desplegando mis servicios en estas plataformas, me hago beneficiario de precios que solamente se pueden alcanzar en Economía a Escala. Es decir, cuando se habla de adquirir millones o centenas de millones de servidores, está claro que el precio unitario de compra, mantenimiento y operación está muy por debajo de lo que yo podría conseguir en el mercado general. Y esa contención de los costes, se revierte en precios de consumo del Cloud cada vez más bajos y competitivos.
La alta disponibilidad, la escalabilidad y la resiliencia, son otras ventajas que emergen de estas plataformas mastodónticas, en donde la disponibilidad de recursos es virtualmente infinita (el límite lo pone mi nivel adquisitivo). Cubriendo las necesidades de la práctica totalidad de los casos de uso, al disponer de la capacidad de replicar cualquier servicio, infraestructura o aplicación que quiera publicar en el Cloud, tantas veces que sea necesario para asegurar niveles de acuerdo de servicio superiores al 99,99%, en cualquier zona geográfica del mundo.
Otra característica que solamente me ofrece este tipo de plataformas es que la inversión en adquisición, puesta en marcha y crecimiento de mis servicios, es muy inferior a la que tendría que enfrentar en el caso de querer hacerlo con mi propio “hierro”.
Aun, incluso, cuando a medio/largo plazo los costes de instalación, administración, mantenimiento y actualización tanto del software como del hardware, puedan llegar a ser similares; a corto plazo (menos de dos años), la Nube es imbatible en los costes de operación, inicio nuevos servicios, o abordar el crecimiento (ya sea imprevisto, constante, puntual, o periódico).
Tampoco son baladí las inversiones asociadas para logar un acceso mundial a mis aplicaciones; lo que implica una formidable complejidad técnica y una barrera de entrada, muchas veces insalvable, a nuevos mercados o al crecimiento empresarial. El Cloud, sin embargo, es por naturaleza de ámbito mundial. Siendo, gracias a la redundancia permanente, la plataforma perfecta para publicaciones geo replicadas con acceso vía Web.
Por último, y no por ello menos importante, las plataformas de Nube liberan de la creciente necesidad de formación, experiencia y conocimiento que se requiere para administrar y evolucionar sistemas informáticos tan complejos como los actuales. Los tiempos del administrador para todo, han quedado atrás. Y el coste de sostener una creciente plantilla que debe estar en formación permanente, no siempre es viable económicamente. Por ello, el delegar estas responsabilidades al Cloud, con los diferentes niveles basados en los tres tipos principales de “sabores” (IaaS, PaaS y SaaS), y el ahorro de costes asociados en personal especializado (sea de plantillas o externo), es otra causa de plantearme la migración de los servicios.
Para qué migrar a la nube
Aunque me repita, el objetivo último de adoptar el Cloud computing es el incrementar los beneficios de la empresa a corto y medio plazo, por medio de la optimización de los costes:
- Disponibilidad del servicio. La mayoría de los negocios se apoyan firmemente en servicios publicados en Internet y/o en aplicaciones/herramientas. De hecho, aún demasiado pocos son plenamente conscientes de lo dependientes que somos de las Tecnologías de la Información hasta que falla algún sistema, o deja de estar disponible. Y este es uno de los objetivos más importantes que se buscan al irse a la Nube: la importancia de tener mi “sistema informático” permanentemente disponible; lo cual gana en criticidad según el impacto que genera en el negocio cada vez que se sufre una incidencia. Llegando incluso, a significar el cierre de la empresa, si la interrupción es lo suficientemente prolongada o crítica.
- Simplificar. Todo lo relacionado con la informática va ganando complejidad según la tecnología y la propia industria va incrementado su madurez (aún es muy joven). El hardware, el software y las herramientas que se crean con ello, son cada vez más numerosas y complejas. Llegando a ser inmantenibles, insostenibles y desconocidas. El concepto de KISS, gana en importancia, y hacer más sencillo las gestiones de los recursos TI se convierte en imprescindible. Así desde el propio concepto de Infraestructura como Servicios, hasta el Software como Servicio, el Cloud ofrece una salida para mitigar la complejidad y su crecimiento.
- Seguridad. Esa es otra preocupación con la que se debe bregar desde el entorno empresarial, por las consecuencias legales y de negocio que ocasionan. Estamos inmersos en la metáfora de “El cañón contra el escudo”, en una verdadera guerra armamentística en el ciberespacio. Y dónde los conocimientos necesarios, en renovación constante y permanente sobre seguridad informática, están atesorados por un número muy limitado de profesionales. Rara es la empresa que puede tener un departamento o personal dedicado en exclusiva a proteger sus sistemas de los llamado cyber-ataques. Así, delegando en el Cloud obtendré acuerdos de seguridad del servicio, con una fracción de la inversión que implicaría subcontratar estos trabajos a empresas externas, o formar mi propio personal.
- Pago por uso. Curiosamente el mayor coste de una infraestructura sobre la que publicar mis servicios, nos es tanto la adquisición, mantenimiento y evolución de la misma, si no la amortización de todas las capacidades que no se utilizan y que deben ser adquiridas igualmente. Por ejemplo, capacidades de cálculo (procesadores y placas madre), memoria (RAM), y almacenamiento que adquiero sobre dimensionadas, para poder soportar picos de trabajo o crecimiento previsto, y que no se utilizan durante largos periodos de tiempo. En Cloud se paga por lo que se usa. Si crezco, el coste es mayor porque estoy consumiendo más recursos para generar más negocio, pero la diferencia la marca la capacidad de reducir la escala, consumiendo menos, y dejando de pagar por aquellos recursos que ya no necesito. Siendo esto una operación con un gran impacto en el ahorro de costes de operación.
- Costes laborales. La simplificación de la plataforma sobre la que funcionan las aplicaciones significa que delego en la Nube la adquisición, instalación, administración, mantenimiento y evolución del hardware y el software – dependiendo del nivel de abstracción de los servicios. Lo que significa una importante reducción de los costes laborales, al liberar ciertos perfiles profesionales de estas tareas. Por ejemplo, no necesitaría tener personal de guardia por si una fuente de alimentación falla.
Cuándo lanzarse a la nube
Podría decir que la mejor respuesta es cuanto antes, pero en realidad hay múltiples factores a tomar en cuenta para iniciar el camino hacia el Cloud.
Lo primero que debo de asegurar es que el sistema, infraestructura o aplicaciones que quiero publicar en la Nube, sea un sistema estable. Es decir, es un error pensar que un servicio que sufre errores funciona mal o de forma impredecible, va a estabilizarse por irse al Cloud. No solamente no es así, sino que los problemas se pueden hacer aún más complejos y difíciles de resolver, impactando directamente en la operatividad.
Otra cosa que debo de mitigar al máximo es la resistencia al cambio que toda organización va a presentar. Desde los profesionales que ven peligrar sus funciones, el usuario final que está acostumbrado a hacer las cosas desde dentro de su zona de confort, hasta el directivo que se resiste a que los datos salgan de debajo de su mesa. Mientras esta resistencia no deje de ser un problema bloqueante, el forzar el cambio solamente añade riesgos de fracaso.
Los grandes centros de Cloud atráen el talento y experiencia de los mejores. Hay en marcha una nueva transformación de los puestos de trabajo
El equipo debe estar formado en los procesos de migración, o ser acompañado por consultores con experiencia real y conocimiento profundo del Cloud de destino. El tamaño y número de servicios que ofrecen las Nubes actuales está en continuo incremento, y se necesita “tenerlos por la mano” para poder tomar las decisiones arquitectónicas, de procesos y tecnología sobre las que vamos a construir nuestros servicios.
También las propias circunstancias del negocio me pueden indicar que es el momento del salto. Así podría ser indicio claro el que tenga un bloqueo en el crecimiento (principalmente a causa de los costes de inversión necesarios); o estar por debajo del nivel crítico de disponibilidad y resiliencia en los servicios, que pueda poder en riesgo la viabilidad de la empresa; o que deba abordar complejos y caros procesos de certificación de calidad, seguridad o procesos; o que por fin caiga en cuenta que el sitio más endeble e inseguro para almacenar los datos es debajo de mi mesa.
Aunque, en mi experiencia, casi siempre el pistoletazo de salida proviene de la percepción y conocimiento, por parte del personal técnico, de las ventajas económicas y operativas de la Nube. Transmitiendo a Dirección las ventajas en la relación servicios/costes que ofrece la plataforma.
Cómo hacerlo
Una vez que tenga claro que el Cloud es mi destino, hay que empezar por lo más básico: una valoración del nivel de madurez de nuestra plataforma actual para, en conjunto con negocio y tecnología, definir cuáles serían las aplicaciones y servicios que podríamos desplegar.
La primera clasificación, por cada una de ellas, es el esfuerzo que hay que realizar, y que se podría categorizar así:
- Migración. Muy orientada a IaaS, o máquinas virtuales, en donde despliego los servicios en un entorno tan similar al original, que no tengo que realizar casi ningún cambio. Esta es la forma más sencilla de irme al Cloud, pero también es la que más coste por servicio soporta.
- Transformación. Ya sea como Infraestructura o Plataforma, mis servicios van a requerir ser modificados en mayor o menor medida para ajustarse a las características de la Nube. Un ejemplo es tener que cambiar la forma en que trabajo con los ficheros, al adoptar una cuenta de almacenamiento de Blob en vez de una Carpeta en el Sistema de ficheros. Esto requiere transformación a nivel de código, que será más o menos costosa de acuerdo con la deuda técnica con que me encuentre.
- Reconstrucción. Hay casos en que la transformación exige tantos cambios y tan profundos que puede ser más interesante económicamente y de forma práctica el reconstruir el servicio desde cero o casi. Esto puede suceder si queremos irnos a la versión PaaS o SaaS del Cloud, o aprovecharnos de las capacidades de los servicios serveless, o implantar las arquitecturas de aplicaciones Cloud más correctas (bus de mensajes, cqrs, key Vault, etc.).
- Por último, y no menos importante, decidir no migrar. Aquellas aplicaciones en donde el coste no compense los beneficios de la adopción del Cloud, no deben ser migradas. Como ejemplo típico, es aquella aplicación que funciona sobre Windows XP utilizando drivers hechos a medida y que reproducirlos en un entorno virtual sería difícil y costoso. O aquella aplicación realizada sobre Excel, que su reconstrucción sería inabordable.
El siguiente paso que realizar, una vez definido si el proyecto de migración tiene sentido y es el momento oportuno para abordarlo, es el realizar pilotos de migración. Esta aproximación tiene un coste muy pequeño (solo se paga por lo que se usa) y permite formarse en los conocimientos necesarios para realizar las transformaciones o reconstrucciones que van a aparecer durante la migración. Tengo que tener muy presente que me voy a enfrentar a las diferencias tanto en la Infraestructura, Sistemas, Telecomunicaciones, Desarrollo de software, Seguridad, etc., en comparación con mi plataforma actual. A lo que he de añadir que, cuanto más alto es el nivel de abstracción, más “específicos” son los cambios y de más calado.
Pero si no mido, no podré saber si la plataforma Cloud está bien configurada o mis servicios y aplicaciones funcionan correctamente. Es más, debo definir qué significa “funciona correctamente” o “mejora”, estableciendo el conjunto de métricas y KPI’s que monitorizar, y cuáles son los valores nominales en donde se deben de mantener.
Qué pruebas funcionales, de carga, experiencia de usuario o rendimiento se deben realizar; cuales serán automáticas; cómo se van a reportar; y en que prioridad ejecutar las acciones correctivas. Y cuáles son los valores esperados y aceptables.
Por supuesto hay que definir un marco financiero que limite el gasto a valores sostenibles. Pero evitando caer en la falacia de obtener un presupuesto basado en una estimación de las horas y costes previstos; porque en este tipo de migraciones los riesgos, mutabilidad y volatibilidad de las operaciones fuerzan un rango de incertidumbre demasiado amplío para ser útil.
Por ello, es crítico saber el volumen de inversión que estoy dispuesto a asumir; cuales son los puntos de fallo, retorno y no retorno; y las acciones de refinanciación o mitigación de los costes extraordinarios, si los hubiera. Es decir, realizar una gestión de riesgos económicos.
Por último, hay que tener paciencia. Son operaciones técnicas con ramificaciones e implicaciones en todo el negocio. Por lo cual el dicho de “las prisas nunca son buenas consejeras” hay que aplicarlo a rajatabla, e ir cubriendo todos los pasos de forma confiable para llevar a buen término el piloto (primero), y luego las migraciones a producción.
Desventajas
Sin duda no existe ninguna tecnología que no tenga desventajas; y la Nube no iba a ser diferente.
Una de las mayores resistencias aparece cuando nos damos cuenta de que nos convertimos en un cliente cautivo, en donde tenemos una dependencia bastante alta con el proveedor. Es decir, si nos decidimos por los servicios de Amazon, no es transparente ni sencillo el irnos el día de mañana a Azure, o volverlos a traer a nuestra infraestructura privada.
Han cambiado las reglas del juego. Ahora, cualquier pequeña empresa puede posicionar sus servicios en Cloud con una inversión inicial mínima
Al revés, cuanto más abstracta es nuestra plataforma (PaaS o SaaS) más encadenados estamos al proveedor y a su tecnología. Llevándolo a su límite en servicios como Lambdas o Serveless, o las plataformas de publicación de arquitecturas de microservicios. Añadiendo que el límite de nuestros servicios lo impondrá el límite de lo que puede hacerse con el Cloud elegido.
Y aquí tenemos otra desventaja: de facto en la actualidad vivimos un duopolio com Amazon AWS y Microsoft Azure. Es cierto que existen Google y otras Cloud, pero realmente la voz cantante la lleva AWS con casi el 48% del mercado, seguido por Azure con poco más del 10%, y Google con apenas un 3%.
También, como transmito durante todo el artículo, hay que asumir importantes costes monetarios, pero también en horas/hombre, en esfuerzo, en formación y en transformación de la propia empresa. No es el proceso más crítico y complejo al que se enfrentan las empresas, pero no es un proceso sencillo, transparente y barato.
Aquí habría que incluir el impacto en la paz laboral de la empresa. Cloud genera recelos y rechazo en los perfiles técnicos orientados a la administración de sistemas; siendo la decisión de migrar al Cloud causas de conflictos, resistencias al cambio, o transformaciones en la fuerza laboral.
Conclusión
No hay otro camino, ya sea de forma privada, híbrida o en Cloud pública, las ventajas de adoptar la Nube como plataforma sobre la que construir servicios son irrefutables. Y soy de la opinión de que no tiene vuelta atrás.
Creamos en ello o no, vivimos en un mundo hiperconectado, global y público. En dónde el concepto de ventaja competitiva hace emerger grandes corporaciones y destruye a otras, en ciclos tan cortos que ningún economista hubiera creído posible hace unas pocas décadas.
Y donde la Nube es casi una obligación a causa del cambio en profundidad las reglas del juego que significa el dar acceso universal a servicios del mayor nivel y calidad, anteriormente reservados a las empresas con abultados presupuestos económicos.
Hoy en día, basado en Cloud, montar una Startup o un negocio clásico con unos costes mínimos de TI ya no es una entelequia, es una realidad que se observa en el día a día.
Lo cual me lleva a la conclusión de que la pregunta realmente a contestar es: ¿Cuándo?
También te recomendamos
Google lanza PerfKit ¿Cómo evaluar el rendimiento real de las plataformas en la nube?
15 tipos de compañeros de oficina que todos hemos tenido (y tenemos)
–
La noticia
Porqué, para qué, cuándo y cómo migrar al Cloud computing
fue publicada originalmente en
Genbeta Dev
por
Juan Quijano
.
Estoy seguro de que si te dedicas a programar, conoces a Robert «Uncle» Martin. Su libro Clean Code es uno de los más recomendados en la lista de libros que todo desarrollador debería leer. Martin, con sus cosas buenas y malas, es uno de los desarrolladores más influyentes del panorama ingenieril. Fuerte defensor de TDD, de la cobertura de tests y otras buenas prácticas, y además cuenta con muchas personas que siguen sus enseñanzas a rajatabla.
Recientemente, Bob Martin, ha publicado un nuevo libro llamado Clean Architecture. ¿Pero qué se entiende por arquitectura limpia?
Clean Code
Como comentaba antes, Clean Code es un libro muy recomendable, que desgrana algunas ideas importantes para poder escribir código limpio.
El código limpio es aquel código que está estructurado de forma compresible, que es claro en sus intenciones, fácil de leer, que es fácilmente mantenible y que está testeado. En el libro se van dando algunas ideas para conseguir escribir código limpio, hablando de principios SOLID, de la importancia de dar nombres a variables y clases etc. En GenbetaDev ya hemos hablado del libro y de sus ideas en alguna ocasión
Principios de una arquitectura limpia
Aunque seamos capaces de escribir código limpio, podemos encontrarnos que al crecer nuestro sistema, la arquitectura del mismo sea un lastre. Y es que no es lo mismo escribir código limpio para un proyecto sencillo, que para un proyecto complejo compuesto de varios componentes obligados a cooperar. A veces las arquitecturas son demasiado complejas, nos obligan a repetir código, o nos hacen tener demasiadas dependencias entre componentes, causándonos muchos problemas.
Los conceptos de cohesión y acoplamiento, también pueden aplicarse a nivel de arquitectura.
Si utilizáis programación orientada a objetos, seguro que conocéis los conceptos de cohesión y acoplamiento. Esos conceptos también pueden aplicarse de forma parecida a los componentes de un sistema, ya sean dlls o archivos jar, estos tienen que cooperar unos con otros. Y la manera en la que cooperen, pueden hacer un sistema fracasar. Pero si seguimos una serie de principios para controlar estas dos variables, nuestra arquitectura será más limpia y manejable.
Cohesión
-
The Reuse/Release Equivalence Principle: que nos dice que los componentes deben poder ser desplegados de forma independiente sin afectar a los demás. Las clases, o código que van en ese componente, deben tener una relación, y por tanto deben poderse desplegar de forma conjunta.
-
The common closure principle: se podría decir que hablamos del principio de responsabilidad única (SRP) aplicado a componentes. La idea es agrupar clases que puedan cambiar por la misma razón en un solo componente. Si tenemos que hacer un cambio, y hay que tocar varios componentes, esto supondrá tener que desplegarlos todos, en lugar de sólo uno.
-
The common reuse principle: este principio nos habla de evitar a aquellos que utilizan un componente depender de cosas que no necesitan. Si un componente depende de otro, hay que intentar que sea porque necesita todas las clases que lo componen. Lo contrario nos obligará a trabajar más cuando nos toque hacer el despliegue. De esta manera será más fácil reutilizar componentes.
Conseguir cumplir estos tres principios a la vez es algo bastante difícil, por lo que a veces hay que aceptar compromisos. Por ejemplo es común sacrificar un poco la reusabilidad, para conseguir que los componentes sean fáciles de desplegar.
Acoplamiento
-
The Acyclic Dependencies Principle: si trazamos líneas entre los componentes para representar las dependencias entre ellos, tenemos que intentar que no existan ciclos. Es decir, que el cambio en un componente, no acabe desencadenando en la necesidad de hacer cambios en cadena en los demás componentes, que obliguen a volver a modificar el componente inicial. Cuando eso sucede, es difícil conseguir una versión estable del sistema, ya que hay que hacer multitud de cambios en los distintos componentes hasta que todo vuelve a funcionar.
-
The stable dependencies Principle: todo sistema tiende a cambiar y evolucionar, pero no todos los componentes cambian con la misma frecuencia, ni es igual de fácil modificarlos. Este principio nos dice que un componente que cambia a menudo no debería depender de otro que es difícil modificar, ya que entonces será también difícil de modificar.
-
The stable Abstractions Principle: este principio nos dice que si un componente de nuestro sistema va a cambiar poco ya que es difícil modificarlo, debe estar compuesto mayoritariamente por interfaces y clases abstractas. De esta manera el componente será fácilmente extensible, y no afectará tanto al resto de la arquitectura.
Características de una arquitectura limpia
Además de cumplir los principios anteriormente descritos, una arquitectura limpia se caracteriza por:
-
Independiente de los frameworks. Los frameworks deberían ser herramientas, y no obligarnos a actuar de una determinada manera debido a sus restricciones.
-
Testable. Debemos poder probar nuestras reglas de negocio sin pensar en base de datos, interface gráfica u otros componentes no esenciales de nuestro sistema.
-
Independiente de la UI. Si la UI cambia a menudo esto no puede afectar al resto de nuestro sistema, que tiene que ser independiente.
-
Independiente de la base de datos. Deberíamos poder cambiar de Oracle, a SQL Server, a MongoDB, a Casandra o a cualquier otra base de datos sin que afectara demasiado a nuestro sistema.
-
Independiente de cualquier entidad externa. No deberíamos saber nada de entidades externas, por lo que no deberemos depender de ellas.
Todas estas características, según Bob Martin, se agrupan en el siguiente gráfico:
Partes de una arquitectura limpia
Entidades
Las entidades son las que incluyen las reglas de negocio críticas para el sistema. Estas entidades pueden ser utilizadas por distintos componentes de la arquitectura, por lo que son independientes, y no deben cambiar a consecuencia de otros elementos externos.
Una entidad deberá englobar un concepto crítico para el negocio, y nosotros tendremos que separarlo lo más posible del resto de conceptos. Esa entidad recibirá los datos necesarios, y realizará operaciones sobre ellos para conseguir el objetivo deseado.
Casos de uso
En este caso nos encontramos con las reglas de negocio aplicables a una aplicación concreta. Estos casos de uso siguen un flujo para conseguir que las reglas definidas por las entidades se cumplan. Los casos de uso, solo definen como se comporta nuestro sistema, definiendo los datos de entrada necesarios, y cual será su salida. Los cambios en esta capa no deberían afectar a las entidades, al igual que los cambios en otras capas externas no deberían afectar a los casos de uso.
Es importante que no pensemos en como los datos que genera un caso de uso serán presentados al usuario. No deberemos pensar en HTML, o en SQL. Un caso de uso recibe datos estructurados y devuelve más datos estructurados.
Adaptadores de interfaz
Los datos generados por los casos de uso y las entidades, tienen que transformarse en algo entendible por la siguiente capa que los va a utilizar y de eso se encarga esta capa. Pensando en MVC por ejemplo, los controladores y las vistas, pertenecerían a esta capa, y el modelo, serían los datos que se pasan entre los casos de uso y los controladores para luego poder presentar las vistas.
Lo mismo aplicaría para por ejemplo, presentar información a un servicio externo, ya que en esta capa definiríamos la manera en la que los datos de las capas internas se presenta al exterior.
Frameworks y drivers
En la capa más externa es, como dice Bob Martin, donde van los detalles. Y la base de datos es un detalle, nuestro framework web, es un detalle etc.
Fronteras o límites
Una frontera (o como dicen los aglosajones, boundaries) es una separación que definimos en nuestra arquitectura para dividir componentes y definir dependencias. Estas fronteras tenemos que decidir dónde ponerlas, y cuándo ponerlas. Esta decisión es importante ya que puede condicionar el buen desempeño del proyecto. Una mala decisión sobre los límites puede complicar el desarrollo de nuestra aplicación o su mantenimiento futuro.
Una mala decisión sobre los límites entre componentes puede complicar el desarrollo de nuestra aplicación o su mantenimiento futuro
Por ejemplo, podemos sentirnos tentados de pensar que las reglas de negocio deben poder guardar información directamente en la base de datos. Como ya hemos visto antes, la base de datos es un detalle, así que esto deberíamos evitarlo. En ese punto deberíamos trazar una frontera. Nuestras reglas de negocio, se comunicarían siempre con una interface, sin saber nada sobre la base de datos. La base de datos en cambio, si sabrá cosas sobre las reglas de negocio, ya que tiene que transformar los datos en sentencias SQL que puedan almacenar la información.
Otra ventaja adicional de este enfoque, es que podemos retrasar ciertas decisiones. Podemos empezar a desarrollar todas nuestras reglas de negocio, sin tener en cuenta su persistencia, ya que esa parte se realiza a través de una interface. Primero podemos utilizar objetos en memoria, y según avancemos, ir añadiendo sistemas más sofisticados. Al final podremos elegir entre usar una base de datos relacional, NoSQL, o incluso guardar la información en archivos.
En definitiva, debemos pensar en nuestro sistema, como un sistema de plugins, de forma que los componentes estén aislados y podamos sustituir unos por otros sin demasiados problemas.
Las fronteras de una arquitectura limpia
En el esquema de arquitectura limpia que hemos visto anteriormente, podemos ver dónde se han trazado las fronteras o límites. Entre entidades y casos de uso, hay una frontera. Lo mismo con los adaptadores de interface, o los frameworks y drivers. Las fronteras son importantes, porque añadirlas cuando no las necesitamos pude crearnos muchos problemas, pero no añadirlas cuando las necesitamos pude generar otros tantos (añadirlas después, es siempre es mucho más costoso).
La separación en fronteras es importante, pero mucho más importante es la gestión que hagamos de las dependencias entre estas capas. Para ello siempre hay que seguir la regla de las dependencias.
La regla de las dependencias
Esta regla es muy importante, ya que sin ella, nuestra arquitectura no sería más que un bonito diagrama. Las capas interiores de una arquitectura limpia, no deben saber nada de las capas exteriores. Por ejemplo la capa de entidades, no puede saber de la existencia de los casos de uso, y los casos de uso no deben saber nada de la existencia de los adaptadores de interface. Así las dependencias están controladas y van siempre en un solo sentido.
Estructuras de datos simples
A la hora de traspasar una frontera, deberemos utilizar estructuras de datos simples, evitando utilizar conceptos como DatabaseRows o similares. Pensando en los casos de uso, estos deben recibir estructuras de datos como datos de entradas, y deben devolver estructuras de datos como salida. Como decía antes, no nos interesa que un caso de uso tenga conocimientos sobre HTML o SQL. Lo contrario nos lleva a una falta de independencia, con todo lo que eso conlleva (despliegue, actualización, tests etc.)
Las capas interiores de una arquitectura limpia, no deben saber nada de las capas exteriores
En ocasiones al pasar datos a los casos de uso, podemos pensar que es buena idea utilizar las entidades como datos de entrada o salida. Al fin y al cabo comparten mucha información. Pero esto no deja de ser un error, ya que aunque al principio la información parezca similar, en el futuro los casos de uso y las entidades cambiarán de muy diferentes maneras, obligándonos a tratar con la dependencia que hemos creado.
Fronteras parciales
A veces, por motivos de organización y mantenimiento, nos interesa crear fronteras parciales. Este tipo de fronteras las tenemos que planificar de forma similar a una frontera real, pero en lugar de empaquetarla en un componente aislado, la dejamos que forme parte de otro componente. Así nos ahorramos parte del esfuerzo de crear un componente nuevo, que no estamos seguros de que vaya a necesitarse. Obtenemos algunas de sus ventajas, dejando todo preparado por si es necesario dar ese último paso.
Conclusión
Aunque puede que no sea la parte más importante de un proyecto de software, la arquitectura juega siempre un papel importante. Ignorar esta fase pude traernos muchos problemas en el futuro, por lo que nunca está de más prestarle un poco de atención. Cuando diseñamos una arquitectura hay que tener muchas cosas en cuenta, como la separación de componentes, las dependencias entre ellos y la manera en la que cruzaremos las fronteras entre los mismos.
Como desarrolladores de software, queremos conseguir desarrollar programas que funcionen y que sean útiles para sus usuarios, pero también que sean fácilmente mantenibles y rápidamente extensibles. Y sin duda para esto no viene nada mal tener algunos conceptos de como debe construirse una arquitectura limpia.
Libro | Clean Code
Gráfico | Clean Architecture: A Craftsman’s Guide to Software Structure and Design
Imagen | acavoulacos
También te recomendamos
15 tipos de compañeros de oficina que todos hemos tenido (y tenemos)
Aprender de la arquitectura del mejor software Open Source
Usando MVP e inversión de dependencias para abstraernos del framework en Android
–
La noticia
Principios de una arquitectura limpia: mantenible y testeable
fue publicada originalmente en
Genbeta Dev
por
rubenfa
.
NOTICIA
React se ha convertido en los últimos tiempos en una de las librerías más utilizadas a la hora de afrontar el problema de la comunicación con el DOM. Gracias al trabajo de muchos desarrolladores y divulgadores, existen multitud de recursos tanto gratuitos como de pago que hacen que aprender React sea una tarea relativamente sencilla, así que no nos vamos a centrar tanto en el manejo de propiedades o en la gestión del estado en React, sino más en su uso como solución general dentro de un contexto Agile.
Este artículo no va de porqué React y no Angular 4 o VueJS. Si esperabas un flame al respecto siento decepcionarte. Este artículo se centra en como hacer que una herramienta como React se alinee con nuestra forma de enfocar el desarrollo de software.
La iteración 0
Cada vez que iniciamos un nuevo proyecto debemos crear la estructura del mismo y preparar las herramientas necesarias para ir añadiendo funcionalidad de forma progresiva haciéndola llegar a producción de la forma más rápida y efectiva. Esta construcción incial en la «iteración 0», se conoce como Walking Skeleton y está descrita en detalle en el Growing Object-Oriented Software, Guided by Tests, siendo además de vital importancia para garantizar una correcta evolución del proyecto. Si no estáis familiarizados con el concepto, la idea principal es intentar que la primera historia de usuario que implementemos en el sistema, por muy mínima que sea, actue como una bala trazadora obligándonos a definir todo nuestro sistema, construcción, despliegue y puesta en producción desde el principio. De esta forma, cada vez que terminemos una historia de usuario, esta podrá acabar en producción de una forma sencilla y predecible al haber implementado desde el principio todo el ciclo completo de construcción y despliegue.
En el caso de React y comenzando por la creación del proyecto, podemos generar esta estructura inicial mediante una utilidad que se llama create-react-app
. Con create-react-app
podemos gestionar un proyecto React sin tener que lidiar de forma directa con las complejidades del tooling de nueva generación que envuelve a la mayoría de proyectos JavaScripts actuales. Un pequeño infierno que debes aprender a controlar dominando Babel, NPM, Webpack y algunos otros amigos con los que mantener una relación de amor/odio.
Con create-react-app
tenemos gratis:
- Babel: React, JSX y ES6.
- Chequeo de tipos con Flow.
- Linting con ESLint.
- Webpack: Dev server + soporte para los loaders de CSS e imágenes.
- Testing con Jest.
- Autoprefixer.
- Build script para generación de versiones de producción, con imágenes optimizadas y soporte para Source Maps.
- Offline-first service worker y webapp manifest para Progressive Web Apps.
Si no te gusta tanta magia negra, siempre puedes ejecutar el comando npm run eject
y hacer explícita la configuración utilizada (toda la config se guarda en la raíz de tu proyecto), pudiendo así adaptar tu aplicación a cualquier configuración no soportada inicialmente por create-react-app
.
Por supuesto, a la parte cliente tenemos que añadir las llamadas a nuestro backend que expondrá la funcionalidad deseada como servicio. En cualquier caso, simplemente recordaros que para poder conectar con la parte del servidor sin tener problemas de CORS, podemos utilizar la opción de proxy de nuestro servidor de desarrollo.
Empezando la casa por las historias de usuario
Cualquier funcionalidad en un proyecto Agile nace gracias a su formalización como historia de usuario. Aunque todo esto lo explica Mike Cohn muchísimo mejor que yo, me gustaría centrarme en un aspecto que para mi es clave en su escritura y que cada vez veo a más equipos obviar a la hora de crear una buena historia de usuario: El Definition of Done o DoD para los amigos.
Sin el DoD, no tenemos una forma clara de verificar que las expectativas de la historia de usuario se han satisfecho una vez finalizada. Es la descripción formal, sistematizada y reproducible del incremento de valor aportado y, como tal, tiene que ayudarnos a guiar nuestro desarrollo dirigido por pruebas.
«No se que tengo que testear» es una de la afirmaciones que más sueles escuchar cuando alguien está comenzando a introducirse a XP (ojo que XP no es un sistema operativo obsoleto que aun vaga por el mundo, sino un conjunto de prácticas técnicas sintetizadas por Kent Bech en Extreme Programming Explained).
¿Como comenzar entonces mis primeras pruebas? Pues si seguimos una aproximación de fuera hacia dentro (outside-in TDD), el primer test del que partiremos será un test de aceptación construido a partir de la definición del DoD que nuestro Product Owner ha escrito para nosotros. Si todo esto te suena un poco a chino y quieres saber más acerca de los tests de aceptación o de testing en general, puedes echarle un ojo a Test-Driven Development by Example de Kent Beck o Growing Object-Oriented Software, Guided by Tests de Steve Freeman.
Centrando un poco más el tema, nuestro objetivo es que cada funcionalidad que se defina en mi backlog en forma de historia de usuario tenga su DoD y pueda dar lugar a un test de aceptación que guíe el desarrollo. Para este primer test de aceptación, nosotros no usamos el concepto de historia de usuario «ejecutable» que podemos ver en Cucumber en su definición más BDD y/o ATDD, sino que es el equipo técnico el que escribe estos tests a partir del DoD y los automatiza para que se ejecuten a través del navegador (aunque comenzamos hace un tiempo con PhantomJS, ahora estamos pasando a Chrome headless y desde hace nada siguiendo muy de cerca el trabajo detrás de Chrome Puppeteer).
Si ya conoces bien la comunidad JavaScript, sabrás que existen mil millones de frameworks para cada cosa, y el tema del testing no es una excepción. Desde la base definida por Selenium y WebDriver podemos encontrar una amplísima gama de opciones con la que tendremos que lidiar antes de poder poner a funcionar nuestro primer test de aceptación, así que si las opciones elegidas para este ejemplo no te convencen, no te preocupes, hay mucho donde elegir!!!
Como curiosidad, comentar que nosotros usamos NightWatch para lanzar este tipo de pruebas y que, para evitar la fragilidad de los tests por cambios en el interfaz, los puntos del UI son accionados mediante una abstracción que definimos sobre los componentes siguiendo el patrón Page Object.
Siguiendo nuestro enfoque dirigido por las pruebas de aceptación, deberíamos de tener el test fallando y en rojo y el Page Object correspondiente definido pero sin posibilidad de interaccionar con ningún componente del interfaz. Estamos en el buen camino!! Sigamos pues adelante 🙂
Tests de integración de componentes
Con un test de aceptación en rojo que mantendremos durante el tiempo que tardemos en satisfacer el DoD de la historia de usuario, es hora de comenzar a implementar la funcionalidad deseada mediante la interacción de distintos componentes dentro del interfaz.
Es en este momento momento cuando herramientas como enzyme, gracias al shallow rendering que permite React, nos permitirán ir definiendo como se deben comportar en cuanto a interacción y en cuanto a definición nuestros componentes.
Antes de nada, añadimos las dependencias necesarias a nuestro proyecto, teniendo en cuenta que, si hemos usado create-react-app
tal y como hemos comentado anteriormente, Jest será el framework de test que tendremos como base para la ejecución de los tests.
npm install --save-dev chai enzyme react-test-renderer
Una vez todo instalado, ya podemos crear un test en nuestro proyecto.
Aunque se puede hacer de muchas formas, Jest soporta la definición de directorios __tests__
en los distintos niveles de nuestra estructura de código, de forma que podemos dejar en estos directorios las clases de test y los recursos que utilicen en ellas.
Como ejemplo, podemos ver este test que prueba un componente que lista películas de StarWars haciendo uso de un Page Object:
jest.mock('../Repository');
import React from 'react';
import { mount } from 'enzyme';
import App from '../../App';
import Films from '../Films';
const FILM_TITLES = [
'The Phantom Menace',
'Attack of the Clones',
'Revenge of the Sith',
'A New Hope',
'The Empire Strikes Back',
'Return of the Jedi',
'The Force Awakens'
];
const FILM_EPISODES = FILM_TITLES.map((title, index) => index+1);
const NUMBER_OF_FILMS = FILM_TITLES.length;
describe('Films', () => {
let wrapper;
let films;
beforeEach(() => {
wrapper = mount( );
films = new Films(wrapper);
});
it('should be listed', async () => {
expect(films.obtainFilms()).toHaveLength(NUMBER_OF_FILMS);
});
it('should show name and episode number', async () => {
const filmsTitles = films.obtainFilmsTitles();
expect(filmsTitles).toEqual(FILM_TITLES);
const filmsEpisodes = films.obtainFilmsEpisodes();
expect(filmsEpisodes).toEqual(FILM_EPISODES);
});
it('should be ordered by episode number', async () => {
films.obtainFilmsEpisodes().forEach((episode, index) => {
expect(episode).toEqual(index + 1);
});
});
});
Como podemos ver en la primera linea de código del ejemplo, se hace uso de un doble de test o mock, de forma que los datos no se cargan realmente del origen HTTP, sino que se definen para servir ciertas fixtures dentro de un directorio especial que en Jest se llama «__mocks__».
Así pues, sólo nos quedaría echar un vistazo al Page Object utilizado para el acceso a la estructura de películas:
export default class Films {
constructor(wrapper) {
this.wrapper = wrapper;
}
obtainFilms() {
return this.wrapper.find('.film');
}
obtainFilmsTitles() {
return this.wrapper.find('.film .title').map((film) => film.text());
}
obtainFilmsEpisodes() {
return this.wrapper.find('.film .episode').map((film) => parseInt(film.text(), 10));
}
}
Y, como no, aquí tenemos el componente principal:
import React, { Component } from 'react';
import repository from './Repository';
export default class FilmsPanel extends Component {
constructor(props) {
super(props);
this.state = {
films: []
}
}
componentWillMount() {
repository.retrieveFilms()
.then((response) => {
this.setState({
films: response.results
});
});
}
render() {
return (
<div>
{
this.state.films.map((film) => {
return (
<div className="film" key={film.episode_id}>
<div className="title">{film.title}</div>
<div className="episode">{film.episode_id}</div>
</div>
);
})
}
</div>
);
}
}
Una vez añadido todo el código de test necesario a nuestro proyecto, tendremos que lanzar el comando npm test
para ver como la ejecución de las pruebas se queda en modo «watch», esperando cambios por nuestra parte:
Con este ciclo que hemos abierto, sólo debemos continuar iterando en estas definiciones hasta que todos los requisitos del DoD se hayan satisfecho y el test de aceptación general pase por fin de rojo a verde. Well done!!! 🙂
Conclusión
El framework principal de elección es sólo una parte ínfima del conjunto de decisiones que debemos llegar a tomar para diseñar un proceso de construcción escalable y de calidad. Prácticas como el testing, la integración continua y la correcta definición de historias de usuario tienen un peso intrínseco infinitamente mayor que ser fan y/o gurú de React o de VueJS. Comencemos hoy a interiorizar prácticas independientes de la tecnología empleada y nos convertiremos con el tiempo en verdaderos Agile Developers.
¿Qué practicas estás incorporando a tu ciclo de desarrollo con el fin de mejorarlo día a día?
También te recomendamos
Conociendo la API REST de WordPress
Angular.js módulos y arquitectura
WaterWall™: cómo es la tecnología que limpia los platos de forma vertical
–
La noticia
Creación de aplicaciones React «The Agile Way»
fue publicada originalmente en
Genbeta Dev
por
Ricardo Borillo
.
NOTICIA
Articulo original publicado en el blog de Stratio.
En esta parte nos ponemos el gorro del mítico Pitfall Harry para echarle un vistazo a algunos de los problemas con los que nos hemos cruzado y el impacto que han tenido en nuestro trabajo diario. También incluimos algunos consejos sobre cómo solventar estos problemas.
Lo primero es lo primero: los pipelines de Jenkins son una gran mejora en cuanto a las funcionalidades básicas de Jenkins y nos permiten montar de forma sencilla flujos completos de continuous delivery con atributos con mucha capacidad de reutilización y mantenimiento.
En este artículo vamos a echar un vistazo a algunos de los defectos, escollos y limitaciones de nuestros (geniales) pipelines de Jenkins, estableciendo algunas de las soluciones alternativas para esquivarlos.
Timeout!
Realizar un timeout es lo mejor que podemos hacer cuando una ejecución se cuelga. Si la ejecución dura de media X minutos, X*3 significa, en prácticamente el 100% de los casos, que se ha colgado. A nadie le gusta tener a zombies pululando por casa, así que mejor deshacernos de ellos.
Sin embargo (y esto va a cambiar) los timeouts no pondrán freno al código incluido en los pasos withEnv o withCredentials. Existe un problema, para el que se está buscando actualmente una solución, con una PR de github.
Debido a que el 90% de nuestros métodos se ejecutan incluidos en elementos withX, nos estamos ocupando de este problema, forzándonos a abortar las ejecuciones de forma manual.
Solución alternativa: Espera y cruza los dedos. Se pueden realizar acciones manuales en caso necesario.
NonSerializableException
Jenkins serializa objetos en diferentes puntos para que estén listos a la hora de sobrevivir a reinicios o a fallos en el nodo. Esta es un función muy interesante para afrontar la pérdida temporal del servicio y los reinicios. La serialización en el disco permite remitir el proceso cuando es necesario reiniciar algunas de las acciones.
El plugin de checkpoints probablemente utilizará está serialización por su propio bien. Cada vez que exista un objeto que no sea pueda liberar ni serializar y Jenkins intente serializarlo… ¡BOOM! De repente NonSerializableException.
Saltará NonSerializableException y se detendrá la ejecución ¿Un impacto bastante grande, verdad?
Solución alternativa: Presta atención a cualquier iterador, matcher, jsonsluper o cualquier otra clase que no esté implementando el uso de la interfaz serializable de java. Es difícil deducir con qué clase estás trabajando, porque Groovy puede no tener tipo o incluso las clases internas pueden ser desconocidas (JsonSlurper utiliza un LazyMap de forma interna y no un serializable), hacer una prueba te echará una mano.
La anotación @NonCPS es útil para superar este problema, puesto que no se realizará una serialización en el método con anotación. No es una solución al 100 % porque no puedes invocar pasos de pipeline dentro de dichas soluciones.
Pruebas
Necesitamos hacer pruebas para asegurarnos de que la función implementada está escrita de forma correcta. Podemos tratar los casos concretos y no saltará ningún NonSerializableException. Sin embargo, y por mucho que nos pese, no hay ningún arnés de pruebas para los pipelines complejos.
Sin pruebas no hay diversión. Para asegurarnos de que nuestro código es estable, es obligatorio probarlo.
Solución alternativa: Hay que hacer las pruebas de forma manual usando la consola de script de Jenkins, trabajos auxiliares o volviendo a ejecutar trabajos. Otra opción es limitar el margen de error posible y dejar que la ejecución continúe.
Manazas
Las bibliotecas de pipeline las escriben personas y como no hay forma de montar el pipeline de manera local, un código incorrecto podría acabar en la herramienta SCM. El código mal escrito supondrá problemas a la hora de analizarlo, por lo que las ejecuciones afectadas no continuarán.
Solución alternativa: Cómete tus propios marrones. PRs para cada función con su propio pipeline. Hacer análisis estáticos de código y revisar el código te ayudarán.
Pérdida de conexión con el nodo
¿Te acuerdas del error NonSerializableException? Se suponía que era para permitir a jenkins sobrevivir a un reinicio o a reconexiones del nodo, pero surge un problema cuando el agente está en la nube. Dichos agentes tendrán un nombre variable (normalmente con una encriptación autogenerada) que lo identifique de forma única. Esto hace que un trabajo no pueda cambiar a otro agente, incluso si el primero ya no esté en activo.
Nuestro entorno está compilado sobre un enjambre de docker, por lo que es algo que pasa bastante a menudo.
Solución alternativa: Acéptalo o prueba con un cambio en el plugin del docker. En Cloudbees han resuelto este problema en su Jenkins Operations Center.
Evaluación final
Como código, los pipelines están muy bien (¿acaso no lo he dicho ya?). Nos permiten implementar estructuras completas como, por ejemplo, un mapa <String, GString> donde cada GString está compuesto por varias GStrings bastante descuidadas (¿alguien ha dicho Inception?), donde cada una a su vez tiene otra variable bastante descuidada (o lo que es lo mismo, otra GString). Esta estructura, que probablemente viene de un problema CPS, nos lleva a la peor forma de evaluación de GString. Los Gstrings son objetos con dos matrices: strings y valores. Estas matrices se combinan para una llamada o para invocar toString, lo que resulta en un objeto eat String (?).
Probablemente sea el problema más difícil al que nos hemos enfrentado y casi hace que tengamos que interrumpir nuestro proyecto. Las estructuras de datos que necesitábamos sufrieron mucho por el tema de los descuidos y otros GStrings.
Solución alternativa: La primera idea sería hacer un NonCPS en el código afectado: ¡FALSO! El string resultante también era incorrecto, cortado en el primer elemento GString (de la matriz de los strings).
Finalmente acabamos analizando un objeto con clase GStringImpl y volviendo a poner en su lugar correcto las matrices de strings y valores. Esto se conoce como el famoso método gStringyHackifier.
Estos son algunos de los problemas más importantes con los que hemos tenido que lidiar. Los compartimos con vosotros a modo de referencia por si os encontráis con situaciones parecidas y os sirven a la hora de trabajar con pipelines.
Javier Delgado es evangelista no oficial del uso de Jenkins para tareas continuas (inspection, testing, delivery), apasionado de la automatización y orador en diferentes conferencias sobre estas materias. Ingeniero informático y fiel seguidor del aprendizaje continuo, actualmente trabaja como ingeniero DevOps en Stratio, compañía de big data española-americana pionera en ofrecer a grandes empresas una transformación digital completa en torno a sus datos a través de un único producto.
También te recomendamos
WaterWall™: cómo es la tecnología que limpia los platos de forma vertical
Continuous Delivery en profundidad: pipelines
GitHub libera Janky, su entorno de integración continua que combina Jenkins con Hubot
–
La noticia
Continuous Delivery en profundidad: problemas y soluciones alternativas comunes de los pipelines de Jenkins
fue publicada originalmente en
Genbeta Dev
por
Javier Delgado Garrido
.
NOTICIA
A la hora de integrar mapas en una aplicación móvil tenemos varias alternativas a nuestro alcance. Actualmente, las opciones más usadas, sobretodo en el desarrollo móvil, son la API de Google Maps, el SDK de Mapbox y el framework MapKit de Apple. Así que, si estás pensando en incluir mapas en tu aplicación, conviene hacer la mejor elección desde un principio.
Tras trabajar con todas estas opciones durante un tiempo, sin duda, considero que la mejor alternativa es tirar por la solución que nos ofrece Mapbox, por su simplicidad y flexibilidad. En este artículo vamos a explicar por qué Mapbox, además de ver cómo implementar algunas de las funcionalidades más potentes analizando un par de sencillos ejemplos.
¿Qué tiene Mapbox que no tienen los demás?
-
Todo es 100% personalizable. Desde cualquier color hasta mostrar/ocultar capas en el mapa. Hay una serie de estilos disponibles por defecto (Dark, Light, etc.) pero también tienes la posibilidad de diseñar/crear tus propios estilos por completo a través de la herramienta Mapbox Studio. Recientemente se lanzó Cartogram, que te genera un estilo automáticamente a partir de una imagen. Los estilos se integran en las aplicaciones añadiendo una sola línea de código. Como puedes imaginar, todo ello te permite generar mapas acordes con el branding de tu app y así ofrecer una mejor experiencia a tus usuarios.
-
Open source. Todo el código está abierto y basado en estándares abiertos. Mapbox dispone de más de 500 repositorios en Github. Esto te permite ver las funcionalidades que están en desarrollo, reportar cualquier tipo de problema que puedas tener o incluso contribuir mandando PRs. Mapbox es una plataforma hecha por desarrolladores para desarrolladores.
-
No importa para qué plataforma desarrolles porque hay SDKs disponibles para prácticamente todas. Entre las cuales están Android, iOS, Web, Qt, Unity y MacOS. Además, todas las funcionalidades están accesibles desde cada uno de ellos, ya que comparten una misma base.
-
In-app. Todo ocurre en tu app. No hay necesidad de tener que saltar a otra aplicación para nada (Mapbox no tiene apps para usuarios así que no tiene interés en competir con sus desarrolladores). Esto es especialmente útil si estás desarrollando una app de navegación, ya que, a diferencia de otros SDKs, puedes proveer una experiencia de navegación completa, sin perder a tus usuarios en ningún momento. Otro ejemplo es la posibilidad de guardar mapas offline sin salir de tu app.
-
El core está basado en mapas vectoriales implementados en C++, de forma que únicamente se mandan los datos necesarios al dispositivo y se interpretan en tiempo real, lo que se traduce en mapas muy rápidos y en visualizaciones mucho más ligeras.
-
Tanto el SDK de Android como el de iOS tienen una API similar a la de Google Maps y MapKit respectivamente. Por lo que todo el conocimiento que ya tuvieras te seguirá siendo útil y además migrar a Mapbox no te costará nada. Para hacer el cambio basta con hacer un Reemplazar todos a través del IDE y listo.
Talk is cheap. Show me the code
Para empezar a usar los servicios de Mapbox en tus aplicaciones tan sólo necesitas el típico token de acceso, que se consigue fácilmente tras darse de alta (usar Mapbox es gratis para tus primeros 50,000 usuarios activos). Hay guías rápidas de instalación, tanto para Android como para iOS. Tras completar la guía de la plataforma para la que estés desarrollando, ya estarás listo para empezar a programar.
A continuación, mostraremos cómo trabajar con dos de las funcionalidades más potentes del SDK, Data Driven Styling, Offline y 3D Extrusions. Los ejemplos están escritos en Java para Android. Aún así, como ya se ha mencionado antes, se pueden implementar en cualquiera de las otras plataformas disponibles (y Kotlin, claro).
En primer lugar, tenemos que configurar el token de acceso:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mapbox access token is configured here. This needs to be called either in your application object or in the same activity which contains the mapview.
// Line must go before the layout XML files loaded
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_style_zoom_dependent_fill_color);
// ...
}
A continuación, ya podemos incluir un mapa de la siguiente forma:
private MapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_style_zoom_dependent_fill_color);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
// ...
}
// Add required Lifecycle methods
activity_style_zoom_dependent_fill_color.xml:
Para garantizar un correcto manejo entre el ciclo de vida de OpenGL y el de Android, MapView define su propio ciclo de vida. Es por ello, que tenemos que sobreescribir los métodos del ciclo de vida de la Activity de la siguiente forma:
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
Los métodos que tenemos que sobre escribir para que todo funcione correctamente son los siguientes (Mapbox provee implementación para todos ellos):
onCreate();
onStart();
onResume();
onPause();
onStop();
onSaveInstanceState();
onLowMemory();
onDestroy();
Por último, una vez declarado y asignado el MapView, hay que llamar a MapView#getMapAsync para crear un objeto MapboxMap, necesario para interactuar con el mapa (como ves, muy parecido a Google Maps API en Android):
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this, getString(R.string.access_token));
setContentView(R.layout.activity_style_zoom_dependent_fill_color);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
// Interact with the map using mapboxMap here
// Customize map with markers, polylines, etc.
}
});
Data Driven Styling
- Cambiar el color del agua en función del zoom:
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(final MapboxMap mapboxMap) {
FillLayer layer = mapboxMap.getLayerAs("water");
if (layer == null) {
return;
}
// Set a zoom function to update the color of the water
layer.setProperties(fillColor(Function.zoom(exponential(
Stop.stop(1f, fillColor(Color.GREEN)),
Stop.stop(8.5f, fillColor(Color.BLUE)),
Stop.stop(10f, fillColor(Color.RED)),
Stop.stop(18f, fillColor(Color.YELLOW))
))));
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40.73581, -73.99155), 12), 12000);
}
});
Offline
- Descargar un mapa offline:
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(final MapboxMap mapboxMap) {
String minZoom = map.getStyleUrl();
double minZoom = map.getCameraPosition().zoom;
double maxZoom = map.getMaxZoom();
float pixelRatio = this.getResources().getDisplayMetrics().density;
OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition(styleURL, bounds, minZoom, maxZoom, pixelRatio);
byte[] metadata = name.getBytes(CHARSET);
offlineManager.createOfflineRegion(definition, metadata, new OfflineManager.CreateOfflineRegionCallback() {
@Override
public void onCreate(OfflineRegion offlineRegion) {
offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE);
}
@Override
public void onError(String error) {
}
});
}
});
3D Extrusions (Building plugin)
- Usando mapbox-android-plugin-building, mostrar edificios en 3D es tan sencillo como:
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull final MapboxMap map) {
BuildingPlugin buildingPlugin = new BuildingPlugin(mapView, mapboxMap);
buildingPlugin.setVisibility(true);
}
});
Conclusión
Como has podido ver, Mapbox trae muchas funcionalidades que no nos ofrecen otros frameworks. Y esto tan solo es una pequeña muestra de lo que podemos hacer, ya que aparte del SDK de mapas, tenemos disponibles el Mapbox Services SDK (APIs de Geocoding, Map Matching, Directions, etc.), el Navigation SDK o los Mapbox Plugins.
Y tú, ¿conocías Mapbox? ¿Cúales son tus casos de uso al trabajar con mapas? Te animo a que le eches un vistazo a la última versión (Android/iOS) y nos digas qué te parece. En próximos artículos, hablaremos de cómo implementar otras funcionalides y trabajar con el resto de SDKs. Mientras tanto, si tienes cualquier duda, la sección de comentarios es tuya.
Documentación Mapbox Android SDK, Mapbox iOS SDK, Github
También te recomendamos
Amazon prepara una API para ofrecer mapas en las aplicaciones móviles de Android
Publicada la versión 3.2 del SDK de Android
WaterWall™: cómo es la tecnología que limpia los platos de forma vertical
–
La noticia
Mapbox: el SDK de mapas abierto
fue publicada originalmente en
Genbeta Dev
por
Pablo Guardiola
.