6 puntos por GN⁺ 2025-01-01 | 2 comentarios | Compartir por WhatsApp
  • Las propuestas de diseño de sistemas que empiezan con “let’s just” por lo general se vuelven mucho más complejas de lo esperado, y las buenas decisiones de arquitectura dependen en gran medida de reglas prácticas y de entender el contexto
  • Las estructuras de plugins, agregar APIs y las capas de abstracción pueden sonar razonables, pero en la práctica también tienen que hacerse cargo de la compatibilidad de comportamiento, el mantenimiento, la seguridad, el rendimiento y las exigencias del ecosistema
  • El procesamiento asíncrono, el control de acceso y la sincronización de datos parecen temas conocidos, pero en entornos de producto suelen terminar en errores difíciles de reproducir, rediseños del modelo de seguridad y problemas complejos de sincronización
  • El enfoque cross-platform y las salidas nativas (native escape) pueden servir en productos iniciales y simples, pero cuando se separan las funciones de la plataforma y el estado interno, se vuelve difícil mantener la calidad y la consistencia
  • Estos patrones no siempre están mal, pero la mayoría de las veces no hacen falta o tienen alternativas, y en vez de elegir enfoques propensos al fracaso conviene volver a resolver el problema desde los primeros principios (first principles)

Por qué “let’s just” es peligroso

  • Las propuestas que vienen después de “let’s just” terminan, 9 de cada 10 veces, siendo un trabajo mucho más complejo de lo que se imaginó en la sala de reuniones
  • La ingeniería también tiene algo de ciencia social, así que lo que funciona depende en gran medida del contexto
  • Cuando dices que cierto enfoque no funciona, para un ingeniero eso puede sentirse de inmediato como un reto para demostrar un contraejemplo
  • Gran parte de la gestión de ingeniería y de la arquitectura de software es una combinación de reglas prácticas (rule of thumb) obtenidas de la experiencia y lecciones aprendidas con mucho esfuerzo

“Hagámoslo pluginizable”

  • Cuando una sola implementación parece insuficiente, meter una nueva implementación en la misma arquitectura hace pensar que se podrán obtener mejoras o funciones nuevas sin cambiar a quien llama la API
  • Pero como “una API no es un archivo de encabezado ni documentación, sino el comportamiento mismo”, casi no existen plugins que simplemente funcionen
  • El componente de software moderno más cercano a un plugin es un driver de dispositivo
    • En el pasado, los drivers tenían una calidad de funcionamiento tan mala que dejaron de tolerarse, o los sistemas operativos modernos han cambiado hacia construir sus propios drivers
  • Para crear una estructura realmente pluginizable, hay que diseñar al mismo tiempo la implementación base y una segunda implementación, porque solo así existe al menos una prueba de que funciona una vez

“Agreguemos una API”

  • Muchas veces, después de que un producto o una empresa logra cierto éxito, aparece la idea de “tenemos que convertirnos en plataforma y atraer desarrolladores”, y entonces se agrega una API
  • Quien ofrece una API tiene que negociar constantemente entre agregar funciones y mantener la compatibilidad e interoperabilidad, y su libertad de cambio se reduce mucho por el comportamiento y las características de rendimiento ya existentes
  • Que exista una API no significa que alguien necesariamente quiera usarla
    • Muchas APIs nuevas aparecen cuando el producto quiere cierta capacidad pero no le asigna una prioridad interna suficientemente alta
    • El mercado objetivo puede ser pequeño, muy vertical o limitado a un dominio específico, y se espera que socios externos llenen ese hueco por medio de la API
    • Pero esos socios también tienen su propio negocio y sus propios clientes, así que quizá no quieran incorporar otro producto adicional para resolver el problema
  • Convertirse en plataforma es un negocio con una demanda real considerable, y rara vez basta con ofrecer unas cuantas APIs para darles a terceros una base económica sostenible

“Agreguemos otra abstracción”

  • La frase de Butler Lampson, “todos los problemas de la informática pueden resolverse con otro nivel de indirección”, contiene una verdad real
  • Los fracasos suelen aparecer de dos formas
    • Una abstracción introducida demasiado temprano se queda en la arquitectura como sobreabstracción sin un plan real de uso
    • Una abstracción agregada después puede volver muy complejos el mantenimiento, la seguridad y la optimización de rendimiento
  • Windows NT tuvo muchas sobreabstracciones incluidas desde el principio que en la práctica no se usaron
  • En la evolución de Mac OS hubo casos en que una abstracción que al principio parecía rara resultó útil dos versiones después, y la diferencia estaba en que sí había un plan
  • Si una abstracción añadida a posteriori solo se usa en parte del código, termina habiendo mucho código que no usa esa nueva abstracción, lo que aumenta la carga de mantenimiento

“Hagámoslo asíncrono”

  • Buena parte de los primeros 25 años de la informática se dedicó a entender e implementar el comportamiento asíncrono
  • En los posgrados de los años 80 se pasaba mucho tiempo con temas como los filósofos comensales, productor-consumidor y el barbero dormilón
  • Hoy muchos ingenieros tratan los problemas asíncronos de forma bastante abstraída gracias a las reglas de la capa de datos y a los frameworks web
  • Si se administra la asincronía directamente fuera del framework o de la capa de datos, al principio puede parecer que funciona bien, pero un año después pueden aparecer errores difíciles de reproducir
  • Solo queda esperar que esos errores no impliquen corrupción de datos

“Luego le agregamos control de acceso”

  • La ubicación del control de acceso fue objeto de debates teóricos, pero los sistemas actuales viven en un entorno mucho más complejo porque están bajo ataque constante
  • Todo el mundo sabe que la seguridad es necesaria desde el comienzo, pero por la velocidad de salida al mercado casi no existen sistemas que diseñen por completo desde el inicio el control de acceso y el modelo de seguridad
  • Si no se parte de la perspectiva del cliente y del atacante, es difícil crear un diseño de control de acceso adecuado para el producto
  • Agregar el control de acceso después puede fracasar, o llevar a una situación en la que más adelante haya que reescribir el producto
  • Y esa reescritura no suele ser una buena experiencia para nadie, incluidos los clientes

“Sincronicemos los datos”

  • En entornos con varios dispositivos, aplicaciones SaaS y almacenes de datos, la propuesta de “simplemente sincronicemos los datos” aparece con frecuencia
  • Como enfatizaba Ray Ozzie, pionero de client/server y de la sincronización de datos, la sincronización es un problema difícil
  • En informática, un problema difícil suele significar uno muy delicado, lleno de desafíos que solo se aprenden con experiencia
  • Incluso en almacenes de datos con semántica completa y transacciones, la sincronización es difícil, y cuando entran blobs, datos no estructurados y transformaciones de datos, la dificultad crece de forma abrupta
  • Basar una solución en la sincronización de datos casi nunca es lo que uno quiere, y por eso existen empresas de miles de millones de dólares dedicadas solo a resolver sincronización

“Hagámoslo cross-platform”

  • El debate sobre lo cross-platform se repite desde hace mucho tiempo, y siempre hay alguien que dice que su código funciona muy bien o pone como ejemplo a Unity y los videojuegos
  • Cuando dices que vas a hacer algo cross-platform, en realidad estás prometiendo algo muy parecido a construir uno de estos tres: un sistema operativo, un proveedor de nube o un navegador
  • Lo cross-platform funciona bien en dos casos
    • Cuando la plataforma es nueva y simple, por ejemplo cuando la nube está al nivel de cómputo y almacenamiento simple
    • Cuando la aplicación o el producto es nuevo y simple
  • Esas condiciones se rompen cuando empiezas a separarte de la plataforma base o a crear funciones que se expresan de forma completamente distinta en cada plataforma objetivo
  • A Microsoft se le hizo difícil crear Office para Mac y Office para Windows con el mismo código, así que bifurcó el código de Office en 1998 y nunca volvió atrás
  • Microsoft originalmente existía como un negocio de crear aplicaciones cross-platform, pero eso funcionaba en una época en que la documentación de APIs del sistema operativo era de unas 100 páginas y cada sistema operativo derivaba de CP/M
  • Artículo relacionado: Divergent Thoughts on Cross Platform

“Si hace falta, dejemos una salida nativa”

  • Como lo cross-platform solo funciona bien durante poco tiempo, los frameworks y las abstracciones de API suelen ofrecer una salida nativa (native escape)
  • La idea es que, a medida que la plataforma evoluciona, se pueda invocar directamente una función de la plataforma nativa que el framework todavía no expone
  • Pero el framework o la API que ofrece la abstracción mantiene estado interno o cachés
  • Si se llama directamente a la plataforma nativa, se modifican estructuras de datos y estados que el framework no conoce
  • Algunos frameworks ofrecen mecanismos para intercambiar datos o estado entre el código de escape y el framework, pero eso se parece más a reintroducir arquitecturas tipo malloc/free en la era de la administración automática de memoria

Se puede elegir, pero no debería ser la opción por defecto

  • Esto no significa que siempre haya que responder “no” a estos enfoques
  • En ciertos contextos, estas formas de trabajo pueden funcionar
  • Pero en la mayoría de los casos, estos patrones no hacen falta o existe una mejor manera
  • En vez de empezar por patrones de software con alta probabilidad de fallar, hay que resolver el problema desde los primeros principios

2 comentarios

 
ndrgrd 2025-01-02

En el caso de los plugins, lo más importante es diseñar la interfaz filtrando al máximo solo las acciones esenciales.
Si solo tomas la estructura general del código actual para crear la interfaz, inevitablemente se convierte en una interfaz innecesaria atada a esa implementación; y lamentablemente, eso sucede más de lo que debería...

 
GN⁺ 2025-01-01
Opiniones de Hacker News
  • El problema con ideas como esta está menos en la idea en sí y más en el enfoque tipo “solo hagámoslo” o en las expectativas que la preceden.
    Por ejemplo, si se ve una API como “solo una función más” del producto, en plan “solo agreguemos una API”, creo que tendría una tasa de éxito parecida a “solo agreguemos una UI”.
    Para crear una buena UI hay que ser cuidadoso y exhaustivo, y también se necesitan especialistas en esa área.
    No hay razón para que otra interfaz del producto sea distinta; más que si es una mala o buena idea, lo central es que no es algo que se deba hacer “así nomás”.

    • En un trabajo anterior teníamos una regla.
      La única persona que podía decir “solo” era el desarrollador realmente responsable de hacerlo funcionar; si otro desarrollador lo decía, se entendía que se estaba ofreciendo para encargarse de esa tarea.
      Era una regla que nos funcionaba bien.
    • Exacto. Al agregar una API, no existe el “solo”.
      Hacer bien una API implica mucho diseño y complejidad.
      Si no está bien diseñada, el cliente puede tener que hacer varias llamadas donde debería bastar una, o la API puede ser confusa y terminar llamándose mal o no poder usarse en absoluto.
      También se necesitan autenticación y autorización, así que hay que configurar OAuth2 o, como mínimo, contar con generación, almacenamiento y validación seguros de tokens de API.
      Los datos también deben manejarse de forma segura, y si el rendimiento es malo, la base de datos puede quedar aplastada por la carga.
      Si se agrega caché, aparece la complejidad adicional de la invalidación de caché y de servidores o procesos para soportarla.
      Sin límites de velocidad, un cliente descuidado puede martillar la API, y si la documentación es pobre, en la práctica no sirve.
      Según el caso, incluso hay que ofrecer SDK para varios lenguajes; y sin buenos mensajes de error, un usuario primerizo no sabrá por qué falló su llamada.
    • La mayoría de los consejos profesionales se parecen a los consejos amorosos.
      Generalizan lo que a alguien le salió mal, pero casi nunca se aplican tal cual salvo que seas la misma persona en una situación muy parecida.
      Los consejos que son consistentemente correctos, como “piensa con cuidado, intenta hacer lo correcto y revisa los resultados”, son tan generales que casi se vuelven inútiles.
      Con ese tipo de frases no se venden muy bien ni entradas de blog ni libros.
    • Siento que el trabajo de preventa existe casi por completo por la palabra “solo”.
      Porque hay que asegurarse de que el cliente no se asuste cuando uno empieza a sacar del agua el resto del iceberg.
    • Exacto. El texto habría estado mucho mejor planteado como “qué se necesita realmente para hacer que una idea de sistema funcione ‘así nomás’”.
      Así no sería un tema de posible/imposible, sino de las formas en que algo tiene éxito o fracasa.
      Cuando conoces los detalles necesarios, se vuelve difícil decir “solo” sin saber siquiera qué es lo que no sabes.
      Eso sí, sobre las DSL estoy casi 100% de acuerdo.
      Suelen ser una complejización innecesaria y con pretensión de ser simpática, y quien esté calificado para crear una debería ser alguien que ya haya creado un lenguaje de programación exitoso y lo haya actualizado hasta una segunda edición o un segundo lenguaje incorporando sus errores, pero aun así se haya equivocado en muchas cosas.
  • (1) Los DSL a veces funcionan muy bien. Ver https://www.jooq.org/
    (2) Elastic Load Balancer es un bucle de control que reacciona a la carga de trabajo, y ese tipo de tecnología ya está generalizada
    (3) En la mayoría de las industrias, el subaprovisionamiento está muy extendido. Ver https://erikbern.com/2018/03/27/waiting-time-load-factor-and... y https://www.amazon.com/Goal-Process-Ongoing-Improvement/dp/0...
    (4) La detección de anomalías no es intrínsecamente un problema de sistemas distribuidos como los otros puntos, pero alguien que ya se haya quemado fuerte puede sentir que la necesita
    También es un campo intelectualmente difícil
    El primer algoritmo que me pareció más o menos inteligente fue https://scikit-learn.org/1.5/modules/outlier_detection.html#..., y a veces funciona como por milagro
    Cuando lo apliqué a texto con embeddings basados en CNN que usaba en 2018, encajó bien, pero con SBERT no tuve nada de suerte

    • Escribí dos DSL, uno junto con mi equipo, y diría que ambos fueron exitosos
      Resolvieron el problema y nadie se quejó
      Creo que el factor más importante fue que ambos eran pequeños
      Eran muy parecidos y reutilizaban código
      Uno era para escribir reglas que validaban formularios enormes, y el otro para escribir reglas de decisión según las respuestas del formulario
      Un buen DSL permite hacer algo a quien antes no podía hacerlo
      Un DSL creado para ahorrar tiempo tiene muchas menos probabilidades de ser útil, porque es muy posible que en realidad no ahorre tiempo
      En ambos casos había que llevar al programa comportamiento complejo del dominio
      Así que hay que enseñarle el dominio al programador, juntar al programador con un experto del dominio, o enseñarle programación al experto del dominio
      Si hay mucho trabajo, es atractivo darle poder al experto del dominio
      El programador puede hacer otras cosas y el ciclo de feedback se acorta
      Si el dominio es profundo, probablemente no quieras mandar al programador a estudiar para aprenderlo; si el dominio es superficial, quizá pueda encargarse alguien más barato
      Los DSL implican una gran carga cognitiva
      Pero si la alternativa es aprender un lenguaje de programación completo, se vuelven más razonables
      Un DSL para ahorrar tiempo es el caso en que alguien que ya sabe escribir código quiere escribir menos código, pero el ahorro es pequeño y en general no vale mucho la pena
      Luego, cuando un programador quiere cambiar algo, en vez de leer código intuitivo tiene que aprender o recordar todo este DSL
      Como regla práctica más simple: un DSL para programadores tiene menos probabilidades de ser una buena idea que un DSL para no programadores
    • jOOQ es un desastre y no se lo recomiendo a nadie
      Escribo consultas SQL, las pruebo en herramientas como DataGrip y luego paso horas averiguando cómo convertirlas a ese DSL
      Si usas funciones SQL “exóticas”, como expresiones JSON, el problema empeora
      Depurar se vuelve un flujo de “imprimir el SQL generado, copiarlo en algo como DataGrip, ajustar la consulta y luego encontrar cómo volver a encajar eso en el DSL”
      Es una pérdida de tiempo enorme
      El principal argumento de venta de jOOQ son las consultas type-safe, pero perdió importancia cuando IntelliJ empezó a validar el SQL en strings dentro del código contra datos reales
      El flujo de editar SQL directamente y probarlo de inmediato contra la base de datos simplemente es mejor
      jOOQ refuerza el argumento del post original sobre los DSL
    • Salvo cosas como las expresiones regulares, nunca he visto un buen DSL, e incluso ahí escuché que mucha gente se queja del lenguaje en sí
      Ejemplos populares de DSL que podrían considerarse malos o casi fracasos son HCL, E4X, XUL y el lenguaje de formateo de strings de Common Lisp
      HCL es el lenguaje de configuración de Terraform, y era evidente que desde el inicio no contemplaba el problema muy común de aprovisionar equipos similares según la cantidad de variables
      Los intentos posteriores de agregar esa funcionalidad también fueron torpes y no resolvieron el problema por completo
      E4X era un DSL de JavaScript para trabajar con XML; en casos simples permitía expresar el trabajo con XML de forma más concisa, pero enseguida podía volverse difícil de leer, como una pared de signos de puntuación
      Al igual que LINQ de Microsoft, tampoco le daba al autor ninguna pista sobre la complejidad computacional del código interno
      Al final, el código que usaba este DSL a menudo se reescribía de una forma menos concisa, pero más fácil de analizar
      XUL era un lenguaje de UI para extensiones del chrome del navegador Firefox, y estaba bien para crear extensiones de Firefox
      Pero Firefox también quería venderlo como tecnología base para aplicaciones internas de empresas, y en ese ámbito se quedaba muy corto
      Para hacer cosas simples hacía falta usar muchos trucos y rodeos
      El lenguaje de formateo de strings de Common Lisp es parecido: está bien para problemas pequeños, pero no escala
      Algunos problemas de formateo requieren soluciones muy raras o directamente no tienen respuesta, y detesto ver código que llama recursivamente a format
      En general, el problema más común de este enfoque es que es una solución improvisada y no escala bien
      Pronto te topas con problemas que no puedes resolver correctamente, y los programas grandes escritos en DSL suelen ser una pesadilla de manejar
    • Cada vez que veo odio hacia los DSL me desconcierta, hasta que caigo en que lo que la gente critica no son los DSL en general, sino los DSL que hay que escribir desde cero
      Si montas un DSL sobre Lisp, solo tienes que escribir la lógica del dominio, no el lenguaje base
      La mayor parte del trabajo ya está hecha, y el lenguaje es útil desde el primer día
      Si lo haces como un DSL alojado sobre Lisp, puede usarse de verdad; no entiendo por qué alguien insistiría en crear un lenguaje nuevo desde cero y verlo marchitarse
    • Los DSL funcionan bien cuando hay un IDE con autocompletado y un ciclo de feedback rápido o inmediato
  • Todos estos elementos tienen muchos casos de éxito
    Es difícil usar la palabra “casi” como escapatoria
    Esto simplemente parece pesimismo y cinismo cansado
    Entiendo ese sentimiento y también lo he sentido, y a veces es difícil hacer que un ingeniero entusiasta abandone una mala idea
    Pero este tono me parece dañino

    • Me parece que es solo una forma atractiva, digamos tipo clickbait, de decir: “estas cosas son más difíciles de lo que parecen de construir correctamente o desplegar de forma efectiva”
    • Detrás de muchos de esos casos de “éxito” hay un equipo de ingenieros curtido en batalla que se encarga de todos los fracasos de la idea
      Bucles de control que se disparan hacia infinito o hacia límites máximos/mínimos, cachés que no se recuperan de fallas distribuidas, estado corrompido durante migraciones en vivo, ráfagas que causan sobrecarga en los momentos menos convenientes, falsas alertas de detección de anomalías que te avisan de feriados en todo el mundo, y cosas por el estilo
      Debajo de todas esas ideas hay una maraña de complejidad que casi todo el mundo subestima
    • En general estoy de acuerdo
      Esta es una lista de ideas de sistemas que son más difíciles de lo que uno piensa al principio, y hay que abordarlas en serio, no tomarlas a la ligera
      Suena vagamente parecido a “se ven bien, pero casi nunca funcionan”, pero en los detalles es completamente distinto
      Si las tratas como problemas difíciles e inviertes en consecuencia, que funcionen bien es un resultado perfectamente alcanzable
      Si son una función agregada a posteriori o se asume ingenuamente que son fáciles, suelen salir mal
    • No lo leo como “pesimismo y cinismo cansado”
      Lo leo como algo sobre ingenieros obsesionados con la optimización prematura aunque no haya beneficio para el negocio
      Es algo realmente muy extendido en la industria: diseñar y construir una nave espacial de autoescalado redundante es divertido, aunque preparar respaldos que puedan desplegarse en unas horas y sobreaprovisionar servidores al 200% podría costar menos de una décima parte
      A veces estas ideas tienen sentido, pero solo después de que se vuelven necesarias
      No son algo que debas diseñar por adelantado en la etapa inicial de un producto
      Muy pocos productos necesitan realmente la escala, disponibilidad y complejidad que estas implementaciones buscan resolver
    • Creo que Steven no está diciendo que estas cosas sean imposibles, sino que son difíciles y que fallan de formas inusualmente problemáticas
  • Parece que aquí mucha gente intenta encontrar una función de juicio sutil para separar las excepciones, pero en realidad es sencillo
    Estas ideas son excelentes cuando las hago yo, y nunca funcionan como se pretendía cuando las hizo el idiota que me precedió

    • Exactamente, parece ser eso
      Y a veces ese idiota que me precedió soy yo mismo hace unos meses
  • Me gustaría agregar aquí el diseño guiado por el dominio
    Intentar alinear la aplicación con la estructura del negocio y, con eso, fijar el diseño del negocio es una receta para el desastre
    Si el negocio es pequeño o está estancado, quizá no notes el problema
    Pero si el negocio tiene éxito o crece, pronto te arrepentirás de haber intentado crear dominios con nombres horriblemente descriptivos, atados a prácticas de trabajo ya obsoletas
    En cambio, es mucho más flexible diseñar alrededor de capas funcionales, como se ha hecho de manera probada durante décadas, y poner la lógica de negocio tanto como sea posible en configuración, filas de base de datos y flujos de trabajo de usuario

    • Te vas a arrepentir de ambas opciones
      Mencionaste como trampas del diseño guiado por el dominio el lenguaje obsoleto y la baja reutilización de código y sistemas para nuevos intentos, pero a la inversa, un diseño altamente abstracto que pone toda la lógica de negocio en configuración, flujos de trabajo, etc., solo es flexible cuando toda la organización entiende bastante bien esa abstracción, la configuración y sus innumerables combinaciones
      Esa combinatoria explota rápidamente en forma de laberinto y crea comportamientos desconocidos e inesperados de los que la gente termina dependiendo
      El onboarding de nuevos desarrolladores y el costo de reemplazar equipos de desarrollo también se vuelven difíciles de sostener
      La organización termina hablando dos idiomas distintos
      La mayoría de las solicitudes de funcionalidades que parecen simples, si rompen la abstracción, se convierten en un rediseño enorme del sistema, o bien en “hackeemos esta abstracción para que por ahora parezca un cambio más seguro y pequeño”
      Lo primero siempre es muy difícil, incluso con ingenieros sobresalientes que entienden por completo el comportamiento de todo el sistema y la base de código, además de buenas prácticas y procesos de ingeniería, y puede llevar meses o años
      Lo segundo ocurre con más frecuencia, y por eso los proyectos “altamente abstractos, en capas funcionales, basados en configuración y con lógica de negocio emergente” al principio parecen perfectos y flexibles, pero al final se convierten en “qué diablos es esto”
      Una vez implementado el sistema, esa lógica de negocio emergente se convierte en el idioma que todos hablan
      Cuando la organización habla dos o tres idiomas totalmente irreconciliables, es muy doloroso, y si no hay varias personas que puedan traducir con fluidez entre ellos hacia arriba, hacia abajo y hacia los lados, terminas sintiendo que habría sido mejor representar el dominio de forma más cercana
    • “Haz que los estados imposibles sean irrepresentables” también entra aquí
      Si diseñas un estado de modo que sea imposible representarlo con tipos, debes poder estar seguro de que, durante la vida útil de ese diseño, ese estado realmente será un estado imposible
  • No entiendo bien el punto sobre los bucles de control que reaccionan a la carga
    Son un componente básico y fundamental de muchísimos sistemas
    Los reguladores centrífugos de las máquinas de vapor del siglo XIX o de los tocadiscos Victrola del siglo XX también son bucles de control que reaccionan a la carga
    Toda la electrónica es una red de bucles de control que reaccionan a la carga, y lo mismo ocurre con las transmisiones automáticas de los autos

    • El problema común es agregar un bucle de control sin entender lo suficiente la señal, o agregarlo sin considerar otros bucles de control
      El uso de CPU es un ejemplo interesante
      Por ejemplo, puedes ver una situación en la que un balanceador de carga entre regiones pelea contra el rechazo de carga dentro del proceso
      Porque la señal del balanceador de carga no refleja el rechazo de carga, o lo refleja de forma incorrecta
      Otro problema es cuando un bucle de control que intenta optimizar resultados locales del servicio perjudica el resultado global
      En general, creo que es mejor tener pocos bucles de control ubicados en puntos de alto impacto
    • No está del todo claro, pero podría referirse en particular a la carga de CPU
      La carga de CPU tiene varios problemas, como se explica en https://arxiv.org/abs/2312.10172
  • Estos problemas tienen un patrón en común
    Todos son preocupaciones transversales que agregan restricciones al modelo de programación de procesamiento secuencial de datos con el que los programadores están familiarizados
    Cada vez que se agrega una restricción, aumenta lo que todos los desarrolladores posteriores deben tener presente mientras sigan desarrollando en ese sistema
    Es fácil caer en una situación en la que el sistema queda excesivamente restringido y no se puede avanzar sin relajar algunas restricciones
    Aunque no sea imposible, se vuelve más lento
    Porque cada vez el desarrollador debe considerar cómo una nueva función interactúa con las API, la seguridad, la sincronización, la latencia, otras plataformas y el código nativo que ya se prometió soportar
    Por eso también es posible soportar todas estas propiedades
    Por ejemplo, si se toma la sincronización transparente de datos como la propuesta de valor central de la plataforma, todo el desarrollo posterior priorizará soportarla y hará evolucionar el conjunto de funciones posibles dentro de esas restricciones
    Puede que ese conjunto de funciones no sea exactamente lo que el usuario quiere, pero ese es el alcance que soporta
    El producto se ve atractivo para los clientes que ponen esa propiedad como el principal criterio de compra

  • He trabajado en proyectos que usaban varios DSL, caché P2P y paralelismo híbrido, y todos funcionaron
    Además, fueron realmente divertidos de construir
    Salvo una excepción, fueron buenas inversiones
    La caché P2P no hacía falta, así que al final no se recuperó mucho de esa inversión
    Por lo tanto, decir que estas cosas casi nunca funcionan es claramente incorrecto
    Son complejas, pero esa complejidad aporta capacidades difíciles de obtener de otra manera
    La lección del ejemplo de la caché P2P es asegurarse primero de si esa capacidad realmente es necesaria

  • Se lee un poco extraño, porque he implementado con éxito bastantes de estas ideas

    • O realmente sabes muy bien lo que estás haciendo, o realmente no tienes la menor idea
  • “Simplemente sincronicemos los datos” es, para mí, la razón por la que existen los días difíciles
    He visto demasiados sistemas a los que se les agregaron colas, procesamiento de eventos y demás pensando en algo como “escala de Internet”, cuando su alcance natural real está muy por debajo de ese umbral
    Estos equipos son ingenuos o, en el peor de los casos, se aprovechan de directivos que no entienden de ingeniería para conseguir dinero y jugar con estos problemas por diversión

    • Yo leí “simplemente sincronicemos los datos” como esperar ingenuamente que, leyendo de un lado y escribiendo del otro, no se separen dos fuentes de verdad
      Para hacerlo bien, las colas y el procesamiento de eventos son indispensables