- El principio de que “el código se lee más de lo que se escribe” parte de priorizar a quien le dará mantenimiento por encima de quien lo escribió, y se expande hacia un modelo de toma de decisiones que considera también a usuarios, operaciones y negocio
- El valor del código no depende de su sofisticación en sí, sino de si cumple el objetivo del usuario; es importante mostrarlo temprano y con frecuencia a los usuarios e incorporar su feedback
- “Ejecutar” código en producción incluye despliegue, actualizaciones, observación, auditoría, monitoreo, corrección y retiro; el costo operativo a largo plazo puede superar por mucho las incomodidades durante el desarrollo
- KISS deja de ser solo simplificar código y se extiende como un principio operativo: reducir partes móviles, entender los modos de falla y hacer que el sistema funcione incluso cuando falle
- Presupuestos, marketing, fechas límite, stakeholders, inversionistas y fuerzas políticas intervienen en las decisiones, por lo que hay que reconocer que complacer a los usuarios y generar ingresos no siempre coinciden
Expansión del modelo de prioridades
- La frase “el código se lee más de lo que se escribe” significa que quien escribe el código por primera vez no debe ignorar el costo de quienes lo leerán y modificarán en el futuro
- Este principio sirve como base para invertir en mantenibilidad, como simplicidad, pruebas y documentación
- En forma resumida, puede verse como el modelo
maintainer > author
El usuario va antes que el desarrollador
- El código es un medio para un fin, y el software debe prestar servicio a algún usuario
- Por muy bien escrito que esté el código o por muy sofisticada que sea la tecnología, su valor disminuye si no cumple su objetivo ni ofrece una buena experiencia de usuario
- La prioridad se expande a
user > maintainer > author; si no se distinguen los roles de desarrollo, queda comouser > dev - En vez de solo adivinar qué quieren los usuarios o preguntarles, es mejor poner el programa frente a ellos temprano y con frecuencia e incorporar lo aprendido a partir de su feedback
Ejecutar también incluye operar en producción
- “Ejecutar” no es simplemente encender un programa, sino todo el proceso de operarlo en producción
- Despliegue
- Actualización
- Observación
- Auditoría
- Monitoreo
- Corrección
- Retiro
- Dan McKinley, en Choose Boring Technology, sostiene que el costo a largo plazo de mantener un sistema funcionando de forma estable casi siempre es mucho mayor que las incomodidades durante su construcción
- Al incorporar esta perspectiva, el modelo queda como
user > ops > dev - Mucho software nunca llega a una escala significativa en producción y se construye sobre supuestos no validados
- Cuando se opera código en producción, KISS deja de ser solo una cuestión de código y se convierte en reducir partes móviles y entender los modos de falla
- Lo importante es desplegar algo y garantizar que siga funcionando incluso cuando falle
El negocio es un eje aparte
- Desarrollar pensando en los usuarios puede llevarte lejos, pero asumir que “el software valioso para los usuarios también es valioso para la organización” es una abstracción simplificada
- Desde la perspectiva del desarrollador, es fácil dividir el mundo entre crear buen software y que el negocio lo convierta en dinero, pero tarde o temprano el proceso de trabajo debe incluir una perspectiva de negocio
- Esta separación suele funcionar en software de consumo y software empresarial
- El modelo se expande a
biz > user > ops > dev - El presupuesto es el ejemplo más claro: como los recursos para satisfacer las necesidades de los usuarios no son infinitos, hay que medir costos y beneficios
- Marketing, fechas límite, stakeholders, inversionistas, intereses personales y política también influyen en la toma de decisiones
- Una decisión que parece correcta si solo se considera el software, el equipo y los usuarios puede no serlo al considerar a toda la organización
- A veces hay que hacer lo que genera ingresos antes que lo que complace al usuario
Olores de las organizaciones de desarrollo vistos con el modelo
-
Código inmantenible:
author > maintainer- El código ingenioso pero perezoso se convierte en espagueti y “bosques encantados”
- Incluye problemas como optimización prematura o módulos que solo una persona específica puede tocar
-
Software inutilizable:
dev > user- Surge en equipos que no aprenden de los usuarios o que priorizan la tecnología
- Ejemplos: programas sobrediseñados, “modernizaciones” que empeoran la experiencia de usuario y apps web que rompen funciones del navegador
-
“En mi máquina funciona”:
dev > ops- Software que no fue diseñado pensando en operaciones
- Incluye complejidad excesiva, como usar bases de datos sofisticadas para cargas de datos pequeñas, o que un equipo pequeño opere un ecosistema de microservicios
- También aplica al software donde la persona que se despierta a medianoche cuando hay una caída no es la misma que lo diseñó
-
“Lo correcto”:
dev > biz- Casos en los que el código se trata como un fin en sí mismo
- Ejemplos: artesanos pretenciosos, músicos del Titanic y Lisp Hackers
-
Desarrollo guiado por el CV:
dev > *- Software que se crea cuando no hay nada en juego y los desarrolladores pueden hacer lo que quieran
-
Software imaginario:
biz > user > ops > dev- Software que se construyó, pero que casi nunca —o nunca— llega a producción
- Charity Majors lo llama living a lie
- El software sin usuarios también entra en la categoría de software imaginario: no resuelve un problema, resuelve el problema equivocado o resuelve un problema que nadie tuvo jamás
- También incluye los casos en que alguien golpea todo con una tecnología inflada hasta que aparece algo que parece un caso de uso difuso
-
“Capitalismo tardío”
- Software financiado por venture capital que no tiene modelo de negocio, o que desarrolla un modelo de negocio basado en explotar a los usuarios después de crecer hasta convertirse en monopolio
La tensión entre usuario y negocio
biz > usertiene consecuencias difíciles de aceptar- La forma en que aprendíamos software consistía en resolver problemas de usuarios finales, y uno de los últimos consejos de The Pragmatic Programmer se resume en el objetivo de no solo entregar código, sino deleitar al usuario
- A medida que el software se volvió omnipresente, mantener esta suposición se hace cada vez más difícil
- Mucho software no se preocupa por los usuarios, los manipula o los convierte en producto
- Este problema no se limita a las redes sociales
- Al reservar una habitación, pedir comida o hacer clic en el botón de inicio de Windows también aparecen pop-ups que intentan captar la atención del usuario
- En Google Search, se describe como recibir resultados que son un montón de basura
- La discrepancia entre lo que muchos creían que era hacer algo bueno y lo que una parte considerable de la industria considera rentable explica la incomodidad de muchos profesionales del software
- No podemos volver a un pasado en el que se ignoraban las realidades económicas, pero necesitamos una postura ética más fuerte para no perjudicar a los usuarios
- Los usuarios no siempre pueden ir antes que el negocio, pero el negocio tampoco debe ir primero de forma incondicional
user > ops > devbiz > ops > devbiz ≹ user
1 comentarios
Opiniones de Hacker News
Algunos usuarios no usan un sistema porque les guste, sino porque su empresa lo compró.
En una situación así, por definición, el negocio está por encima del usuario, y los desarrolladores terminan ajustándose a las exigencias de los mandos medios del cliente más que a las de los usuarios reales. Si no lo hacen, no consiguen el contrato. Al final, los usuarios quedan atados a funciones entregadas a medias mientras el equipo de desarrollo está ocupado creando nuevas funciones que le gusten a algún mando medio.
Suena un poco cínico, pero como ingeniero ayuda saber si, en el fondo, estás en ese tipo de empresa. Por ejemplo, un retailer en línea es muy sensible a sus usuarios, al punto de tener versiones distintas del sitio por país porque a los alemanes les gusta X y a los estadounidenses Y. Un cambio pequeño puede hacer una gran diferencia en las ventas.
En cambio, algunas empresas son poco sensibles a la usabilidad porque quien compra el producto no es el usuario real.
Para ganar contratos teníamos que cumplir con los checklists del cliente, pero también nos preocupábamos por la experiencia de usuario. Una buena experiencia de usuario casi nunca era un requisito estricto del cliente.
El software de la competencia era muy doloroso de usar, así que queríamos diferenciarnos por ese lado; eso facilitó la capacitación, dejó más satisfechos a los usuarios y, cuando podían, incluso recomendaban a sus jefes que compraran más de nuestro producto.
Al final, el 80% venía del orgullo y la empatía de decir “nuestro software no es horrible”, pero a largo plazo también nos convenía porque construía marca.
Adoptamos una estrategia de crecimiento impulsado por el producto, no teníamos vendedores, y el equipo de producto estaba totalmente enfocado en la experiencia de usuario. El problema era que no les vendíamos a los usuarios. Quienes compraban el software eran otras personas dentro de la organización del usuario, y ni siquiera habían usado el producto directamente.
Era un enfoque condenado al fracaso. Necesitábamos vendedores que entendieran qué pasaba por la cabeza de los compradores, les explicaran los beneficios y entrenaran a los usuarios para explicar esos beneficios a otras personas dentro de su organización. Había que cerrar la brecha entre usuarios y compradores.
Así que el problema pasa por decidir a qué usuarios priorizar, y encontrar un equilibrio entre priorizar la experiencia de esa minoría que influye sobre el resto de los usuarios y mantener el producto lo bastante usable para que los demás usuarios puedan proporcionar datos significativos a la gerencia.
Lo único que importaba era la opinión del alcalde, el administrador municipal y el concejo. Si los reportes se veían bien y el precio era adecuado, renovaban.
Recuerdo reuniones en campo donde la gente que lo usaba todos los días nos decía en la cara lo terrible que era. Aun así, sin excepción, ese cliente renovaba con la promesa de corregir algunos bugs específicos y un aumento mínimo de precio.
Hoy aprendí el símbolo ≹. Dicen que “indica una relación en la que ninguno de los dos objetos comparados es mayor o menor que el otro, pero tampoco necesariamente se puede decir que sean iguales. Una distinción sutil importante en ámbitos donde existen formas de comparación que no son estrictamente numéricas” (https://www.mathematics-monster.com/symbols/Neither-Greater-...)
Me parece más claro escribir |z_1| = |z_2|, es decir, que los dos números complejos tienen el mismo valor absoluto.
Dice que “en conclusión, el símbolo ≹ cumple un papel importante al proporcionar un punto intermedio entre los operadores relacionales tradicionales”, pero como estudiante de doctorado en matemáticas nunca lo vi. Me cuesta creer que cumpla un papel importante.
Los juegos son un superconjunto de los números surreales, y los números surreales son un superconjunto de los reales; se obtienen relajando la definición de los surreales de modo que se pierde la propiedad de orden total.
Así aparecen números raros que pueden ser “confundidos” con otros números, o que son “difusos”. El ejemplo más simple es * (star), que no es ni mayor ni menor que 0, así que se confunde con 0. Es como una nube difusa alrededor de 0, y se escribe 0║*.
Los switches, que son juegos más complejos, pueden confundirse con intervalos de números más grandes y se consideran “calientes”. Si construyes números con switches, puedes crear juegos calientes más interesantes.
Los eventos generados en un solo dispositivo siempre tienen un orden completo. Pero si se generan eventos en dos dispositivos sin conexión, no se puede decir cuál ocurrió primero, y entre ambos eventos existe una relación ≹. Dicho de otra forma, se consideran eventos concurrentes.
Así pueden surgir los órdenes “d > b > a” y “d > c > a”, pero “c ≹ b”.
Definir una forma determinista de resolver empates en casos así es gran parte del problema que resuelven los CRDT.
¿Cómo es eso posible?
Para muchos de nosotros, el costo de ejecutar el código mil millones de veces puede ser más barato que unos minutos del tiempo de un desarrollador.
Si gasto 200 dólares al mes en servidores en AWS, puedo ejecutar gran parte del código de mi API web incluso 100 mil millones de veces.
Por eso, optimizar para lectores humanos siempre es mejor, y solo habría que hacer otras optimizaciones cuando se demuestre que es tan lento que resulta económicamente difícil de sostener.
El artículo termina con estas expresiones:
user > ops > dev
biz > ops > dev
biz ≹ user
La conclusión parece más bien que el código existe para los usuarios finales y para el negocio. La última expresión, ≹, expresa de forma prolija que las necesidades de los usuarios finales y las del negocio no son iguales, pero que ambas son igualmente importantes para la existencia del código.
Los usuarios pagan el costo de formas menos obvias, como facturas de electricidad más altas, menor vida útil[0], oportunidades perdidas, mayor frustración y actualizaciones de hardware más frecuentes.
Además, la mayoría de los usuarios no tienen el salario ni la calidad de vida de un desarrollador, así que el daño se siente varias veces mayor.
[0] Hacer perder el tiempo a otros reduce los QALY.
Dice que incluye operarlo en producción: despliegue, actualización, observación, auditoría, monitoreo, corrección, retiro, etc.
Si devolvemos la consecuencia del título al autor, no sería “el código se lee más de lo que se usa”, sino algo más cercano a el código ilegible no se ejecuta por mucho tiempo.
Dicho eso, soy un administrador de sistemas experimentado que intenta moverse lateralmente hacia el desarrollo y, en ese sentido, soy un completo principiante.
Más precisamente, sería algo más cercano a “el código ilegible no permanece modificable por mucho tiempo”.
Si no estamos hablando de ofuscación intencional, la mayor parte del código puede ser leído por alguien dispuesto a esforzarse, y si hace falta también hay formateadores de código.
Hay una consecuencia que sumaría aquí. Entre cada una de las siguientes etapas, la cantidad de usos aumenta exponencialmente.
En muchos lenguajes, la proporción en cada etapa es de aproximadamente 1000 veces, así que por cada diseñador de lenguaje podría haber 1000 personas diseñando y publicando módulos, 1 millón de desarrolladores y 1000 millones de usuarios. Las cifras pueden variar mucho según el caso concreto, pero el orden de magnitud aproximado sirve para una discusión cualitativa.
El punto clave es que una pequeñísima pereza en la primera o segunda etapa se multiplica de forma dramática aguas abajo. Un hack sucio hecho en la etapa 1 para ahorrar 1 minuto por “comodidad propia” puede desperdiciar literalmente millones de horas valiosas de la vida de otras personas: haciéndolas esperar por software lento, frustrándolas con fallos, o haciéndolas esperar porque el desarrollo de funciones se retrasa en las etapas 2 y 3.
Mantener el nivel de calidad necesario en las dos primeras etapas requiere una enorme autodisciplina y ética personal. Por el contrario, cada vez que escucho a alguien defender posturas injustificables sobre el diseño de un lenguaje central o de una biblioteca estándar, me entristece profundamente.
A menudo se oyen cosas como “¡Está bien si conoces toda la historia de cómo apareció esta arista filosa! No es un problema si te mantienes alerta para siempre. No es inseguro, ni riesgoso para la seguridad, ni lento, ni problemático si no lo usas mal”, porque sé que esas cosas harán tropezar a desarrolladores durante décadas y harán más lento el software de millones o miles de millones de personas.
Parece que el autor tomó una regla empírica bastante buena e intentó convertirla en una teoría de todo.
Se ve prolija y sensata, pero si se quitan las formulaciones forzadas, se acerca más a volver a masticar obviedades ampliamente conocidas.
Por eso la expresión puede sonar torpe.
Y aunque sean “obviedades ampliamente conocidas”, este artículo las entrelaza especialmente bien y de forma coherente, por lo que sirve como referencia útil.
Para alguien, todo esto puede ser nuevo, y aunque para mí no haya sido más que una confirmación de mis sesgos, fue una perspectiva interesante.
El encuadre del autor puede malinterpretarse de demasiadas maneras como para ser una abreviatura útil. No puede haber una jerarquía absoluta entre esos términos.
Para empezar, “dev” aquí no es una sola persona, sino un conjunto de personas con distintas especialidades y niveles de experiencia en organizaciones de producto, ingeniería y diseño de varias organizaciones.
“ops” tampoco es una sola cosa, y no significa solo operaciones de ingeniería. También puede incluir operaciones de negocio, soporte al cliente, etc.
“biz” tampoco es una sola cosa. Están branding, marketing, ventas, legal, además de la dirección ejecutiva, el directorio, los reguladores, los prestamistas, los inversionistas, etc.
Todas esas personas influyen en qué código se escribe, cómo se escribe y cuándo y cómo se despliega a los usuarios. Todas tienen que resolver el mismo problema.
Muchas personas dentro de una organización suelen existir para hacer que todos entiendan y vean el mismo problema, y trabajen hacia el mismo objetivo.
Pero esa comprensión evoluciona constantemente, y hay demoras en propagarla por toda la organización. Por eso también hay demoras en que todos trabajen hacia el mismo objetivo, incluso mientras el propio objetivo va cambiando.
Por último, “user” tampoco es una sola cosa, y ningún grupo de usuarios es estático. Hay diversos grupos de usuarios, y su comportamiento puede no ser estable a largo plazo.
Así que ayuda entender y reconocer cómo cambian todas las variables alrededor, y desde ese contexto interpretar un mundo imperfecto y roto. De lo contrario, es fácil caer en la idea de que todos los demás son pésimos y todo está roto, así que dan ganas de reconstruirlo todo desde cero.
Me alegra ver que se discutan temas cercanos a la ética.
En la frase del texto: “creo que hay un desajuste entre lo que pensábamos que era hacer algo bueno y lo que una parte importante de la industria considera rentable, y que esa es la razón por la que crece la incomodidad de muchos profesionales del software”, incomodidad es una expresión bastante suave. Quedan muchas cosas sin decir.
Quisiera agregar algunas preguntas. ¿Qué pasa cuando el usuario no es el cliente, es decir, quien paga? ¿Tiene el negocio obligaciones éticas con todos los usuarios, incluidos los que no pagan? ¿Qué pasa si un cliente de pago quiere usar tu negocio de una forma que genere efectos negativos aguas abajo para los usuarios?
Por ejemplo, ¿qué pasa si una plataforma facilita el fraude más que las alternativas existentes, facilita la difusión de desinformación o facilita moldear las opiniones de los usuarios de una manera destructiva a largo plazo, pero atractiva y generadora de hábitos? Todo eso ha demostrado ser, durante ciertos períodos, un modelo de negocio exitoso.
Si estas dinámicas son reales, ¿debería un negocio perseguir esos modelos explotadores? Si lo hace, ¿puede hacerlo de manera más responsable? ¿Puede una versión más ética del negocio mitigar las peores tendencias de sus competidores, o termina siendo parte del problema?
La conclusión central es clara. Hay ciertos tipos de problemas que son más grandes e importantes que un modelo de negocio. Hay problemas que pueden formularse como: “qué normas y reglas hacen falta para que las empresas operen dentro de cierto rango de sentido común”.
Por último, quiero dejar algo claro. Un negocio transmite inherentemente una serie de valores, y eso es inevitable. Incluso adoptar solo la postura de “lo popular gana” es, en sí misma, una elección con profundas implicaciones de valores. Los politólogos e historiadores conocen desde hace mucho el problema de la tiranía de la mayoría. Sea cual sea tu filosofía política, es algo para pensar.
No sé cuál es el “mejor” sistema ético, pero sí sé que algunas éticas son mejores que otras. Y espero que sigamos refinando nuestra ética, en lugar de dejarla sin examinar.
Puedes elegir qué problemas y ámbitos se ajustan a tu ética. Este artículo trata sobre cómo construir sistemas y cómo priorizar el trabajo.
En realidad, los negocios no existen; son constructos imaginarios que creamos para organizar recursos y trabajar juntos.
El negocio no es lo más importante por encima de todo. Hay muchos usuarios y a veces sus intereses chocan. No se puede estar en todas partes ni ser todo para todos, así que hay que priorizar. Puede parecer que buscar usuarios más rentables o alineados con una estrategia de largo plazo es “bueno para el negocio”, pero en realidad el objetivo es servir a los usuarios. Solo que con algunos pasos intermedios más.
Si la política interna se enreda al punto de tomar decisiones solo por el beneficio del negocio, sin preguntarse cómo eso se traduce en la felicidad de los usuarios, la organización se volvió tóxica. Ya no debería existir. Puede tambalearse un tiempo en estado zombi, pero está en declive y toda la gente buena se irá.
Se podría decir que las emociones también son solo constructos creados para explicar reacciones ante situaciones, pero que no estén hechas de átomos no significa que no sean “reales”.
Los negocios existen en la medida en que son un factor principal que determina la vida de la mayoría de las personas. Dan forma a ciudades, medios, leyes, política y política exterior, e influyen mucho en casi todo lo importante. Sean reales o no, tienen un impacto tangible a nuestro alrededor.
Fuera del open source, queda bastante claro que quien paga decide cómo se construye algo. Aunque esa decisión sea mala para esa entidad, mala para los usuarios y mala para el público en general o para el ambiente. Claro que existen la industria y la regulación gubernamental, pero en general la empresa tiene el poder de decisión.
Lamentablemente, los negocios existen para servir a sus dueños. En la mayoría de los casos, sobre todo en empresas grandes que no son microempresas de menos de 5 personas, los dueños quieren dinero, así que todas las personas de la empresa existen para hacerles ganar más dinero a los dueños. La felicidad de otras personas, incluso la de los usuarios, es totalmente irrelevante salvo cuando se correlaciona con los ingresos.
Otro incentivo universal dentro de una empresa es la autopreservación. Por eso, además de ganar dinero, quienes toman decisiones consideran la seguridad de sus propios puestos.
Los empleados no se van. La empresa logra mantenerlos lo suficientemente satisfechos. Es sorprendentemente fácil hacer que la gente siga trabajando para una organización malvada o sin rostro pagándoles bien y haciéndolos sentir parte de una “comunidad”. Si miras las oficinas de FAANG, puedes ver una lista detallada de estos trucos de RR. HH.
Estoy de acuerdo en que esas empresas son tóxicas y no deberían existir, pero en la práctica así es como funcionan. No es una señal de decadencia, sino la forma de un negocio maduro y saludable que puede durar décadas. Cambian los ejecutivos, los productos y los dueños, pero el negocio permanece.
Pero la importancia es subjetiva. Si es código personal para tu propio disfrute, el negocio no importa. Si quieres convertirlo en tu principal fuente de ingresos, el negocio es lo más importante. Porque si el software no logra servir a nadie, por mucho que les guste a los usuarios, no se convertirá en ingresos reales.
Sin un modelo de negocio, incluso un software excelente, querido por los usuarios, distribuible y mantenible puede terminar apagándose.
Al principio era escéptico, pero me gusta este modelo mental.
Claro que no hay que seguirlo a ciegas. Hay excepciones donde dev > biz, como el caso de OpenAI, y también excepciones donde dev > ops. En una startup temprana hay que moverse rápido, así que, especialmente por razones de negocio, puede darse dev > ops.