Lecciones aprendidas en el desarrollo de grandes aplicaciones, un estudio de caso de Hawaiian Airlines

 

 

 

  • Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX
  • Implemente rápidamente. Implementar inteligentemente

  • Índice
    1. Principios humildes
      1. Salto de vuelo
      2. Objetivos de viaje
      3. Gráfico de precios
    2. La zona de pruebas frontal
      1. Plantillas dinámicas alimentadas por datos estáticos
      2. Lanzar código por encima de la valla
      3. Aprendizajes de la zona de pruebas
    3. CSS y menos
      1. Mezclas vs. Extender
      2. OOCSS y BEM
      3. Aprendizajes CSS
    4. angularjs
      1. Componentes de interfaz de usuario personalizados
      2. Rendimiento de AngularJS
      3. Aprendizajes de AngularJS
    5. Controles de formulario personalizados

    Únase hoy a Cory Shaw mientras reflexiona sobre algunos de los errores que él y su equipo cometieron, las herramientas que utilizaron, los flujos de trabajo y las pautas que siguieron, e incluso algunas de las herramientas personalizadas que crearon mientras trabajaban en el nuevo sitio web de Hawaiian Airlines. Todo mientras se hace crecer un equipo de desarrollo de UI de una a más de diez personas para realizar el trabajo. Fue una montaña rusa como ninguna otra, pero prevalecieron y construyeron lo que él cree que es una de las mejores experiencias de reserva de aerolíneas en la web. Este artículo y la información contenida en él se han compartido con el permiso explícito y la generosidad de Hawaiian Airlines.

     

    Después de pasar más de dos años haciéndolo, simplemente presionamos el botón "Enviar" en el nuevo sitio web de Hawaiian Airlines . Ha sido el proyecto más grande de mi carrera y he trabajado con el equipo más talentoso con el que he trabajado. Todo se reconstruyó desde cero: hardware, funciones, API de back-end, front-end y UX y diseño. Fue una montaña rusa como ninguna otra , pero hemos prevalecido y construido lo que creo que es una de las mejores experiencias de reserva de aerolíneas en la web. ¡Sí, humilde, lo sé!

    Únase a mí mientras reflexiono sobre algunos de los errores que cometimos , las herramientas que utilizamos, los flujos de trabajo y las pautas que seguimos, e incluso algunas de las herramientas personalizadas que creamos, todo mientras hacemos crecer un equipo de desarrollo de UI de uno (un servidor) a más. diez personas para hacer el trabajo.

    Divulgación completa: nuestra empresa, User Kind , es proveedor de Hawaiian Airlines y todas las opiniones expresadas aquí son mías. Este artículo y la información contenida en él se han compartido con el permiso explícito y la generosidad de Hawaiian Airlines.

    Principios humildes

    Cuando me incorporé a este proyecto como desarrollador de UI, Hawaiian Airlines ya había contratado a otra agencia para repensar la UX y el diseño del sitio web existente de 10 años. Esa agencia entregó un documento de estructura alámbrica de más de 500 páginas , un puñado de hermosas maquetas de Photoshop anotadas y una guía de estilo de interfaz de usuario. Ver estos entregables inmediatamente me entusiasmó con el proyecto y algunos de los divertidos desafíos de desarrollo de la interfaz de usuario que se avecinaban.

    Salto de vuelo

    Objetivos de viaje

    Gráfico de precios

    La zona de pruebas frontal

    Cuando comencé, un gran equipo de back-end de aproximadamente 40 desarrolladores estaba intensificando la reconstrucción de todas sus API de servicios. Sabiendo que había un tsunami de trabajo de interfaz de usuario por hacer, que aún no había API de back-end para que las consumiera el front-end y que había una fecha límite estricta, nos pusimos a trabajar.

    Debido a que la pila de back-end aún se estaba definiendo y construyendo detrás de una red privada, comenzamos con un entorno limitado de front-end liviano para comenzar a construir componentes de interfaz de usuario.

    Así es como se veía la pila de herramientas y el flujo de trabajo:

    Plantillas dinámicas alimentadas por datos estáticos

    Mientras trabajábamos en el entorno sandbox, utilizamos AngularJS para crear plantillas dinámicas basadas en un JSON estático, que eventualmente sería reemplazado por puntos finales en vivo una vez que entregáramos el código. A veces, la gente de back-end nos enviaba un archivo JSON generado a partir de datos de vuelo reales, y otras veces simplemente lo definimos nosotros mismos si los datos aún no existían.

     

    El uso de datos JSON estáticos funcionó bien por un tiempo, pero una vez que comenzamos a construir algunos de los componentes de la interfaz de usuario más complejos, rápidamente nos encontramos con un problema: múltiples estados de datos .

    Tomemos como ejemplo los resultados de los vuelos. Tiene resultados de vuelos de ida, de ida y vuelta y de varias ciudades, cada uno con hasta cuatro escalas, vuelos nocturnos y múltiples aerolíneas. ¡Incluso puedes viajar en el tiempo si vuelas a través de las zonas horarias adecuadas en el momento adecuado!

    Dados los archivos JSON de mil líneas, ajustar manualmente el JSON para probar otros estados era una tarea ardua y propensa a errores humanos.

    Necesitábamos una mejor manera de crear y probar todos estos estados diferentes en el entorno de pruebas. Entonces, Nathan se propuso resolver este problema y se le ocurrió lo que llamamos el "inspector de datos":

    Armados con el inspector de datos, pudimos preparar el código de interfaz para que estuviera listo para producción cuando lo entregamos para conectarlo a los datos en vivo. Como beneficio adicional, los diseñadores y propietarios de productos podrían usar esta herramienta en el sitio web de demostración de Heroku para asegurarse de que todo se vea según lo previsto en todos los estados.

    Lanzar código por encima de la valla

    Alerta de spoiler: ¡Nunca hagas esto!

    Cuando llegó el momento de integrar el código front-end con los servicios back-end, tuvimos que entregárselo a las personas que lo estaban integrando en un entorno totalmente diferente (.NET) con herramientas completamente diferentes (Visual Studio y Team). Foundation Server), escondido de forma segura detrás de una red privada en Hawaii.

    Si bien esto funcionó bien al principio, rápidamente se convirtió en una pesadilla. La gente de productos solicitaría cambios en la interfaz de usuario; Haríamos esos cambios en la zona de pruebas y luego los devolveríamos. Los cambios de código tendrían que fusionarse manualmente porque teníamos Git por un lado y Team Foundation Server por el otro. Con diferentes estructuras de archivos y carpetas, estos dos repositorios no funcionaban bien juntos.

    Rápidamente pusimos fin a esto y trabajamos con el equipo de TI para obtener acceso al paraíso amurallado. Sin embargo, este proceso nos hizo retroceder meses de productividad, ya que cambiamos a una pila de desarrollo completamente diferente, obtuvimos acceso a VPN, aprendimos un conjunto de herramientas diferente y configuramos nuestras máquinas virtuales para que coincidieran con lo que estaba usando el equipo de back-end.

    A partir de entonces, hemos trabajado directamente con los equipos de back-end para crear e integrar el código de la interfaz de usuario, utilizando el proceso scrum en sprints de dos semanas, y las cosas han ido mucho mejor desde entonces.

     

    A corto plazo, el sandbox nos dio una gran ventaja. Pudimos utilizar un montón de herramientas y flujos de trabajo modernos con los que todos estábamos familiarizados. Nos hizo realmente eficientes. Dadas las circunstancias, podría haber sido el movimiento correcto, pero esperamos demasiado para arrancar el vendaje y saltar la valla una vez que estuvo listo.

    Aprendizajes de la zona de pruebas

    • Si utiliza Git, elija cuidadosamente un modelo de ramificación desde el primer día y asegúrese de que se ajuste a su equipo, proyecto y flujo de trabajo.
    • Si su estrategia de ramificación de Git se realiza correctamente, entonces revertir o seleccionar características a lo largo de la línea de tiempo de su proyecto debería ser una tarea fácil y económica.
    • Si no es posible construir la interfaz de una aplicación con datos y puntos finales reales, entonces encuentre una manera de hacerlo posible. (Los puntos finales simulados habrían sido mejores).
    • Evite a toda costa que varios equipos trabajen en múltiples entornos, incluso si eso causa retrasos desde el principio.
    • Establezca sus herramientas, flujos de trabajo y entorno desde el principio y asegúrese de que todos los miembros del equipo los utilicen.
    • Si hubiéramos adoptado un enfoque más progresista, nos habría dado una gran ventaja a largo plazo y habríamos evitado por completo la crisis a mitad del proyecto.

    CSS y menos

    Al comienzo de este proyecto, adoptamos la metodología de mantener el HTML liviano, con muy pocas clases de CSS y usar LESS :extenden gran medida, era el camino a seguir.

    Es bueno porque cuando tu diseño cambie en el futuro, tu HTML no estará lleno de muchas clases de CSS y no deberías tener que tocarlo. Simplemente actualice sus estilos MENOS y cambie sus :extendestilos.

    La mayoría de los elementos en HTML no tenían clase o tenían una única clase definitoria:

    section h1Title/h1 pSome Text/p/section

    Luego, en nuestro MENOS, tendríamos estilos como este:

    .my-section { h1:extend(.header-uppercase-1){}; p:extend(.bodycopy-sans-3){};}

    El resultado neto de este método es una gran cantidad de selectores en la salida CSS. Después de un año de codificación, nuestra salida CSS se volvió difícil de manejar, con miles de líneas de esto:

    .ha-modal .help-template h2,.ha-modal .help-template h3,.ha-modal .help-template h3:first-child,.ha-help.collapsable-block h4,.tooltip-block h4,.traveler-lg .name,address h4,.ha-cms-teaser-sidebar .heading,[ha-calendar] .ha-calendar-month,.ha-modal#locationModal .destinations-container .standard-location .heading,[ha-alert] .alert .alert-content .alert-content-primary,[ha-avatar] .avatar .name,[ha-avatar] .avatar.small .name,[ha-tooltip] .ha-tooltip h4,[ha-global-alert] .global-alert .alert-content .alert-content-primary,[ha-promo-tile-other-small] .promo-tile.tile-small .headline,[ha-promo-tile-other-large] .promo-tile .headline,[ha-child-nav-tile] .child-nav-tile .page-title,.navtray-content-inner--stackedlistwrap .stackedlist-li-title,.lte-ie7 .navtray-content-inner--stackedlistwrap .stackedlist-li-title,.ha-flight-hop .departure-city,.ha-flight-hop .arrival-city,.ha-receipt .trip,.ha-my-trip-itinerary .trip-header span.segment-city,.ha-my-trip-itinerary .segment .check-in .status,.ha-my-trip-itinerary .segment .check-in .status:before,.ha-my-trip-itinerary .segment .check-in .status.green:before,.ha-my-trip-itinerary .segment .check-in .status.red:before,.ha-my-trip-itinerary .segment .check-in .status.yellow:before,.ha-flight-status .flight-info .flight-number,.ha-flight-status .flight-info .flight-route,.ha-print-confirmation .reservation-code-title,.ha-my-trips-itinerary-details .trip-header span.segment-city,.ha-my-trips-eticket-receipt .trip-header span.segment-city,.ha-my-trips-itinerary-details .segment .segment-header .col,.ha-my-trips-eticket-receipt .segment .segment-header .col,.ha-my-trips-itinerary-details .segment .leg .leg-details .status,.ha-my-trips-eticket-receipt .segment .leg .leg-details .status,.ha-my-trips-itinerary-details .segment .leg .leg-details .status:before,.ha-my-trips-eticket-receipt .segment .leg .leg-details .status:before,.ha-my-trips-itinerary-details .left-heading .trip-locations,.ha-my-trips-eticket-receipt .left-heading .trip-locations,.ha-book-flight-results .segment .selected-flight-info,.select-class-wrapper a,.ha-book-flight-results .discount-applied .credit-applied { font-style: normal; font-size: 0.9375em; font-family: "helvetica-neue", "HelveticaNeueLT Std", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: bold; text-transform: none; line-height: 1.4; letter-spacing: 0.02em;}

    Dato curioso: ¿Sabías que Internet Explorer 9 y versiones anteriores dejarán de procesar un archivo CSS determinado una vez que alcance los 4095 selectores? El uso intensivo de :extendnos puso muy por encima de ese límite desde el principio. Descubrir por qué el sitio web parecía totalmente desordenado en Internet Explorer 8 y 9 requirió un poco de depuración e investigación. Terminamos usando una tarea Gulp para dividir los archivos CSS de versiones antiguas del navegador.

     

    Esto terminó siendo realmente malo. Infló nuestro CSS con una salida que dificultaba la depuración de estilos en el inspector.

    Mezclas vs. Extender

    Cuando nuestra salida CSS comenzó a superar los 100 KB de tamaño, surgió una pregunta. ¿ Qué generaría una hoja de estilo más pequeña: más estilos (usando @mixin) o más selectores (usando :extend)?

    Dejaré que Jake me explique:

    “Después de probarlo, descubrimos que, a pesar de :extendgenerar significativamente menos CSS, la compresión Gzip de los estilos mixin redundantes en realidad podría traducirse en un tamaño de archivo similar, si no más pequeño. Lo que pone esta idea en la cima es que la transición a mixins haría que el CSS del inspector DOM fuera mucho más legible. Ya no tendríamos 200 selectores no relacionados atenuados para los que h1intenta depurar (lo que puede hacer que el inspector se retrase y reduzca la legibilidad). Hicimos una pequeña prueba de Gzip comparando una hoja de estilo mixin-ed a pequeña escala con una :extendhoja de estilo -ed, y la versión mixin realmente salió victoriosa”.

    Entonces, hicimos una gran revisión para cambiar todos :extendlos s a @mixins. (Cubrimos el 80% con un guión sencillo y el resto a mano). Recetas de cocteles

    Así, esto…

    .my-section { h1:extend(.header-uppercase-1){}; p:extend(.bodycopy-sans-3){};}

    … se convirtió en esto:

     

    .my-section { h1 {.header-uppercase-1} p {.bodycopy-sans-3}}

    Este descubrimiento fue una mejora, pero el CSS inflado podría haberse evitado por completo si hubiéramos adoptado un marco completamente diferente...

    OOCSS y BEM

    Mirando todo esto en retrospectiva, nuestro CSS se habría reducido de tamaño y nuestra productividad de desarrollo habría aumentado si hubiéramos establecido un patrón con más clases definitorias en el marcado ( OOCSS y/o BEM ).

    Estas son las ventajas de OOCSS y BEM:

    • Las hojas de estilo son más pequeñas, planas y más fáciles de mantener.
    • La resolución de problemas y el desarrollo de estilos son más eficientes:
      • Los mapas fuente pueden indicarle dónde encontrar el código fuente MENOS.
      • Modificar estilos en el navegador (para experimentar) es más fácil porque aparecerán como estilos diferentes.
      • El DOM le dirá cuál es la clase personalizada versus cuáles son las clases globales.
      • Puede dividir más fácilmente hojas de estilo específicas para servir solo lo que una página o sección necesita (en lugar de descargar muchas clases a las que la página no hace referencia).

    Y aquí están las desventajas de OOCSS y BEM:

    • El HTML es más manejable y tiene muchas clases de CSS.
    • Tendrá menos flexibilidad para realizar cambios solo de CSS en el futuro.
    • Cuando cambie el diseño, probablemente necesitará modificar las clases HTML.

    En retrospectiva, OOCSS y BEM claramente habrían sido marcos ideales para abordar un proyecto de este tamaño.

    Aprendizajes CSS

    • Acuerde un enfoque general en todo el equipo o adopte un enfoque estilo OOCSS, como BEM.
    • Utilice un linter como el complemento LESS Lint Grunt de Jacob Gable para mantener su LESS y CSS alineados con sus patrones.
    • Evite el uso :extendde s tanto como sea posible en un proyecto grande. La forma en que funciona es inteligente, pero el resultado es confuso y difícil de depurar.
    • Utilice clases que sean planas y reutilizables en todo el proyecto y analice continuamente las clases existentes al crear otras nuevas.

    angularjs

    Cuando me incorporé a este proyecto, tenía mucha experiencia con jQuery, jQuery Mobile y JavaScript básico, pero no había tocado AngularJS ni marcos de JavaScript similares. El cambio de paradigma a AngularJS fue una lucha para mí al principio; pero, como muchos otros han experimentado, una vez superada la curva de aprendizaje, me enamoré.

    Componentes de interfaz de usuario personalizados

    Lo que hace que AngularJS sea una gran solución para un gran proyecto como el sitio web de Hawaiian Airlines es la cantidad de flexibilidad que le brinda para crear componentes de interfaz de usuario personalizados.

    Toda esa flexibilidad significa que hay muchas formas de despellejar al gato AngularJS. Al principio, lo modificamos de manera que nuestro código fuera difícil de probar y de reutilizar en diferentes contextos. Tendríamos una directiva que dependía de alguna variable de alcance principal, y cuando eso no existiera, la directiva fallaría. Aprendimos bastante rápido que si no tienes un alcance aislado en tu directiva, estás buscando problemas.

     

    A lo largo del proyecto, aprendimos a pensar en las directivas de AngularJS más como componentes web autónomos con una API.

    Las directivas de AngularJS deberían ser muy egocéntricas. No deberían saber ni preocuparse por el mundo en el que viven, siempre y cuando se satisfagan sus necesidades básicas, tal como las define una API en forma de atributos de elementos:

    custom-component-thing type="type1" data="{object}" default-airport-code="HNL" excluded-airport-codes="['OGG', 'DEN']" show-partner-airlines="true" on-departure-airport-select="select(departureAirportCode)" on-return-airport-select="select(returnAirportCode)"/custom-component-thing

    En el ejemplo anterior, los datos que alimenta a esta directiva a través de los atributos le indican cómo comportarse y exponen una forma de extraer datos de ella, pero aíslan completamente su funcionamiento interno y la plantilla que se representa en el DOM.

    Rendimiento de AngularJS

    Si bien AngularJS vincula mágicamente todos los datos definidos de $scopedos maneras, esta magia no es gratuita. Para cada elemento de $scope, se crea un oyente que detecta cambios en él. Cuando se detectan cambios, se revisa y actualiza en todos los demás lugares donde se utiliza. Cada vez que AngularJS recorre todos los elementos de $scope, lo llamamos ciclo de resumen. Cuantas más cosas tengas atadas $scope, más difícil será trabajar y más lento se volverá tu ciclo de digestión.

    En una aplicación tan grande como los resultados de vuelos de Hawaiian Airline, comenzamos a notar un rendimiento lento en tabletas y computadoras de escritorio lentas . Tras investigar, nos dimos cuenta de que la página tenía más de 5000 observadores y que el ciclo de resumen tardaba varios cientos de milisegundos.

    Con un nuevo problema y conocimiento del rendimiento de AngularJS, Nathan y Scott crearon y crearon una herramienta útil para monitorear el rendimiento de AngularJS , y la abrieron.

    Esta herramienta terminó siendo clave para solucionar problemas y controlar el rendimiento de AngularJS en todo el sitio web. Compruébelo: puede ver los datos de rendimiento de AngularJS en el sitio web en vivo agregándolos ?performance=truea la URL de cualquier página.

    Junto con la herramienta de rendimiento, utilizamos la directiva AngularJSbind-once para garantizar que tengamos observadores solo en los datos que necesitaban cambiar.

    Como resultado, redujimos nuestros observadores de más de 5000 a menos de 500 y vimos un buen aumento en la capacidad de respuesta en tabletas y dispositivos lentos.

    Aprendizajes de AngularJS

    • Con un gran poder viene una gran responsabilidad. Asegúrese de comprender el funcionamiento interno del marco elegido para aprovecharlo para el bien y no para el mal.
    • AngularJS me ha enseñado una forma completamente diferente de pensar acerca de la construcción de una interfaz de usuario, como dividir los componentes hasta su esencia reutilizable y evitar por completo la manipulación de DOM a través de jQuery.
    • Piense en las directivas como componentes web que exponen una API en ellas y mantenga su alcance aislado del mundo exterior para evitar errores y dolores de cabeza.

    Controles de formulario personalizados

    La reserva de viajes online consiste básicamente en un complejo conjunto de formularios. Entonces, diseñar hermosos controles de formulario personalizados parecía obvio y todos (incluido yo) estábamos entusiasmados con ello.

     

    Mirando hacia atrás, si tuviera que elegir la cosa más dolorosa que hicimos en este proyecto, serían los controles de formulario personalizados.

    Puede que no te des cuenta, pero esos controles de formulario que vienen listos para usar en tu navegador hacen mucho trabajo pesado:

    • Garantizan que las personas con problemas de accesibilidad puedan seguir utilizándolos.
    • Realizan un seguimiento de focuslos estados .bluractiveinactive
    • Permiten al usuario recorrer todos los campos utilizando la tecla "Tab".
    • Descubren cómo y dónde colocar los menús desplegables según la posición de desplazamiento de la página.
    • Permiten al usuario escribir hasta varias letras para saltar a un elemento en un menú desplegable.
    • Se desplazan automáticamente por los elementos del menú desplegable para obtener listas largas.

    Cuando decidimos implementar nuestros propios controles de formulario, asumimos la carga de reinventar la rueda y cumplir con todos los requisitos anteriores.

    Terminamos con una solución que usa AngularJS para ocultar el HTML nativo de menús desplegables seleccionados, casillas de verificación y botones de opción, y los reemplaza con marcas alternativas sobre las cuales teníamos control total sobre el estilo.

    Si bien este enfoque nos dio control a nivel de TOC sobre cada píxel, terminó causando todo tipo de errores oscuros y problemas de accesibilidad en situaciones complejas, que pasamos incontables horas parchando.

    Al final, decidimos descartar estos controles de formulario personalizados en favor de sus contrapartes nativas. Nos dimos cuenta de que, si bien no podíamos lograr la perfección de píxeles de una solución personalizada pura, podíamos lograr el 99% del camino simplemente usando imágenes de fondo y pseudoselectores en el HTML de entrada nativo. En el caso de

     






    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Lecciones aprendidas en el desarrollo de grandes aplicaciones, un estudio de caso de Hawaiian Airlines

    Lecciones aprendidas en el desarrollo de grandes aplicaciones, un estudio de caso de Hawaiian Airlines

    Patrones de diseño de interfaces inteligentes, vídeo de 10h + formación UX Implemente rápidamente. Implementar inteligentemente Índice

    programar

    es

    https://aprendeprogramando.es/static/images/programar-lecciones-aprendidas-en-el-desarrollo-de-grandes-aplicaciones-876-0.jpg

    2024-05-20

     

    Lecciones aprendidas en el desarrollo de grandes aplicaciones, un estudio de caso de Hawaiian Airlines
    Lecciones aprendidas en el desarrollo de grandes aplicaciones, un estudio de caso de Hawaiian Airlines

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20