Cuando el mismo ícono significa dos cosas distintas, y por qué la solución no fue solo cambiar una etiqueta
Una revisión de diseño marcó esto, y es un buen ejemplo de un bug que solo existe porque dos funcionalidades crecieron en partes distintas de la app sin que nunca se las comparara una junto a la otra.
En Deep Cut Atlas, una pantalla de Descubrir o Historial tiene un botón de “No interesa”. Ícono de pulgar hacia abajo, estilo rojo destructivo. Al tocarlo, el lanzamiento queda registrado como descartado. No va a volver a aparecer. Esa es una decisión real y permanente, y el ícono y el color comunican ese peso correctamente.
La pestaña Lista tiene un botón casi idéntico en apariencia en su hoja de detalle de álbum. Mismo ícono de pulgar hacia abajo. Mismo estilo rojo destructivo. Está etiquetado como “Ignore.” Solo que tocarlo no descarta nada. Solo saca el álbum de la lista de reproducción actual. El álbum sigue en la biblioteca del usuario. No pasa nada permanente.
Entonces alguien que aprendió en Descubrir que “pulgar hacia abajo significa nunca volver a mostrarme esto” asumiría razonablemente lo mismo en Lista, y se equivocaría. El lenguaje visual hacía una promesa que el código no cumplía.
La solución en sí fue chica: cambiar la etiqueta a “Remove from Playlist,” cambiar el ícono a minus.circle (no a un tacho de basura, ya que no se está borrando nada, solo se quita de una lista), y reservar el pulgar hacia abajo exclusivamente para las dos pantallas donde en verdad es permanente.
Lo que hizo que esto fuera más que un cambio de cadena de cinco minutos fue el método detrás del botón. Se llamaba ignore(), con una propiedad llamada ignoreError. Una vez que la etiqueta visible cambia a “Remove from Playlist,” un método que se sigue llamando ignore() se convierte en su propia trampa pequeña: la próxima persona que lea este código ve un botón que dice una cosa y una función que dice otra, y tiene que detenerse a confirmar que son la misma acción. Entonces el método pasó a llamarse removeFromPlaylist() y la propiedad pasó a llamarse removeError. Ese nombre tampoco fue arbitrario. El view model padre ya tenía un método con ese nombre exacto para la misma operación subyacente, una capa más abajo, así que el renombre se alineó con una convención de nombres que ya existía en vez de inventar una nueva.
El hábito más chico que vale la pena nombrar: antes de dar por definitivo un cambio de cadena en la interfaz, mirar la pantalla renderizada, no solo la línea de código fuente. Una revisión de diseño puede decir “estas dos cosas están nombradas de forma distinta,” pero hace falta una captura de pantalla real para notar que la solución a punto de lanzarse simplemente movería la confusión a otro lugar.
Lecturas relacionadas
Unificando "Dismissed" vs "Not Interested," y la fila de Settings que repetía su propio encabezado de sección
Cuatro nombres para un mismo concepto, y el descubrimiento de que la solución obvia habría introducido una nueva inconsistencia un nivel más arriba, más la única repetición que es una función de seguridad, no un error.
Una decisión de UX que hice mal la primera vez
La acción de agregar a lista de reproducción calzaba con su gesto hermano en la misma tarjeta, y peleaba con el resto de la app. Elegir el punto de referencia equivocado para «consistente.»
La configuración que funcionaba perfecto y se sentía completamente rota
Un filtro por defecto que solo se aplicaba al reabrir la app, porque un TabView mantiene vivos los view models y el estado sembrado en la construcción queda congelado. La solución eliminó un concepto.