¿Qué tipos de software son mucho más complejos de desarrollar de lo que las personas (que no son ingenieros de software) se dan cuenta?

Casi todo es más complejo de lo que crees que será. Los humanos tienen una capacidad tremenda para pensar en diferentes niveles de abstracción simultáneamente. Como resultado, no se dan cuenta de las complejidades cuando entras en el meollo. ¡Incluso los programadores piensan en abstracciones sin darse cuenta! Por ejemplo, habitualmente decimos que “el Módulo A habla con el Módulo B”. O “El programa A interactúa con el programa B”. ¡Pero los módulos y programas son abstracciones! Todo se ejecuta en la CPU. No hay módulos Pensar en los módulos / programas como entidades independientes hace que sea más fácil analizar el comportamiento de un sistema informático, y entrar en una abstracción de nivel inferior de analizar cómo reacciona la CPU a veces puede ofuscar la verdad. Del mismo modo, cuando los no programadores hablan de cosas, hablan en abstracciones sin darse cuenta.

En los problemas de Big Data, por ejemplo, los no ingenieros (e incluso algunos ingenieros) piensan en una aplicación distribuida como una sola aplicación. Esto puede ocultar mucha complejidad. Par de ejemplos

Hace unos años, estaba construyendo un motor de predicción en Gigaspaces. Obtendríamos un conjunto de datos que distribuimos en la cuadrícula, y teníamos un código que aplicaba un modelo de predicción en cada segmento de datos. De vez en cuando, obtendríamos datos realmente malos, y la ejecución arrojaría muchos errores. El problema era que en ese momento, Gigaspaces no tenía un contador distribuido confiable. Entonces, a pesar de que cada trabajador sabía que estaba recibiendo muchos errores, no podía detener el trabajo porque no podía asumir que todos los demás trabajadores estaban obteniendo errores. Entonces, uno de los analistas de negocios dijo: “Bueno, ¿por qué no te detienes cuando ves que el 10% de los registros tienen el mismo error?”. Verá, tiene sentido para él porque pasa por toda la aplicación como un programa que se ejecuta en un solo nodo, y contar errores es trivial en una aplicación de un solo nodo. Tuve que hacer una analogía usando una fábrica hipotética que tiene cientos de trabajadores, y la usé para demostrar cómo la fábrica se paralizaría si hiciéramos lo que él quería que hiciéramos usando una solución ingenua. También le mostré cómo sería una solución real y cómo no es tan simple como él cree que es.

El segundo ejemplo es: con frecuencia me dicen “¿Por qué no lo pones en una transacción de la base de datos?” Gente … las transacciones de la base de datos tienen un solo proceso. No hay transacción de base de datos en una aplicación distribuida. La última vez que me dijeron esto fue cuando estaba explicando cómo hemos implementado un sumidero JDBC en Apache Spark que admite exactamente una vez la semántica. Estaba explicando esto a un grupo de desarrolladores que planeaban usar Spark por primera vez, y el propietario del producto dijo: “¿Por qué no actualizas la tabla de la base de datos en una transacción?”. Dije: “Las aplicaciones distribuidas no trabaja de la manera que piensas “. Digamos que tiene un lote de datos que se divide en 20 particiones y se distribuye a 10 nodos. Cada nodo funciona en una partición antes de elegir la siguiente. Ahora, no puede tener particiones cruzadas de transacciones de bases de datos. Definitivamente no puede tener transacciones de base de datos en máquinas cruzadas. Para poder “revertir” y todo el lote de datos, debe usar algún mecanismo fuera de las transacciones de la base de datos

En términos generales, incluso los programadores que no han creado aplicaciones distribuidas subestiman la complejidad de las operaciones distribuidas. Por ejemplo: las operaciones de “Unir” parecen triviales. Es mucho más complicado cuando unes 1 millón de filas con 100 millones de filas en un clúster.

Diseño frontal

Ni siquiera los otros ingenieros de software entienden la complejidad y la naturaleza volátil de un diseño frontal.

  1. Compatibilidad del navegador: los desarrolladores front-end conocen el dolor insoportable de hacer que una página web sea compatible con IE <9. Aunque el futuro parece prometedor con el soporte final de Microsoft para IE, los navegadores que implementan FlexBox, todavía hay muchas diferencias en la forma en que Google Chrome y Mozilla Firefox admite CSS. Siempre tiene que buscar ¿Puedo usar ... Tablas de soporte para HTML5, CSS3, etc. antes de usar cualquier nueva propiedad CSS.
  2. Resoluciones de pantalla: se puede acceder a una página web desde un monitor enorme o un pequeño teléfono inteligente de 4 pulgadas. Tiene que responder y verse bien en cualquier resolución de pantalla.
  3. Navegadores: con los nuevos navegadores integrados en aplicaciones como Facebook, ahora tenemos aún más navegadores de los que preocuparnos.

Sólo acerca de todo.

Como alguien que creció con una generación que ha tenido acceso ubicuo a las computadoras, solía, como muchas personas no técnicas, subestimar la complejidad de crear software.

Un ejemplo sencillo sería: imagine que está escribiendo código para hablar con una API, y lo que sea que esté tratando de implementar hizo 10 llamadas a la API.

Para cada llamada, puede obtener numerosas respuestas de error, como 404 no encontrado, un servicio 503 no disponible o un conflicto 409 además de una respuesta exitosa.

Al instante, su programa ahora tiene que manejar 30 posibles “caminos” más.

¡Pero espera!

Lo que sucede si, por ejemplo, en la quinta llamada, la respuesta significa que ya no desea continuar con las 10 llamadas.

Ahora tiene que implementar la inversión del efecto que las llamadas X tuvieron en su sistema, para volver a una lista limpia.

Esta parte de su programa, por cierto, podría ser para un pequeño elemento GUI en la página de inicio de su aplicación iOS. (y tendrías que implementar lo mismo para Android, y si sentías simpatía por Microsoft, Windows también).

La mayoría del software es enormemente más complejo de lo que la mayoría de las personas que no usan software imaginan.

Hay una cita que encontré hace años en Hacker News que uso a menudo, que resume muy bien las complejidades del desarrollo de software (en mi opinión).

Esto es lo que los clientes, gerentes y desarrolladores menos experimentados tienen en común: entienden que nada es difícil. Pero no tienen en cuenta que administrar la complejidad entre mil, cien mil o un millón de reglas es muy, muy difícil.

El software que es más complejo de desarrollar de lo que los no desarrolladores se dan cuenta, es el que tiene muchas piezas de interconexión. Estos no son lo que podríamos llamar piezas de “nivel macro”, como bases de datos o módulos de código, sino sus piezas de nivel de código, como las reglas de negocios y los tipos de datos.

Como desarrolladores tenemos que comprometer, retener y desarrollar continuamente una gran cantidad de información de bajo nivel sobre el código en la memoria. Comprender que un cambio en una parte del sistema tendrá consecuencias para otras partes del sistema es una parte importante de nuestros trabajos diarios.

Esto lleva a una de las porciones más grandes de esta gestión de complejidad y eso es “casos extremos” y comprender que los programas a menudo no tienen una sola ruta de ejecución. Las solicitudes HTTP, las consultas de la base de datos y la administración del sistema de archivos, por ejemplo, pueden fallar por muchas razones diferentes y, a menudo, necesitan controladores específicos para cada error. Encadene algunos de estos tipos de operaciones (lo que hacemos muy a menudo) y esa pequeña característica del programa ya tiene potencialmente 100 rutas de ejecución diferentes que deben tenerse en cuenta, aunque solo 1 de ellas es la que realmente queremos. también tome y el único en el que el cliente habrá pensado, y si desea revertir los cambios, eso es un dolor de cabeza completamente diferente para agregar.

Sin embargo, esta es la razón por la cual la gente viene a nosotros por nuestra experiencia y habilidad. Si fuera simple, lo harían ellos mismos. Mi trabajo es realmente resolver problemas, escribir soluciones en código resulta ser la herramienta más común que uso. Es mi trabajo encontrar una solución y comunicar esa solución sin ninguna complejidad a mi cliente (junto con un precio, por supuesto). Me complace explicar por qué el costo puede no coincidir con sus expectativas si lo solicitan, pero no espero que comprendan completamente las complejidades de lo que hago y eso ayuda a evitar mucha frustración y permite una comunicación mucho más fácil.

Bien, me preocupa que obtengas respuestas de ingenieros de software o informáticos que dirán que no hay otros usos. Como ingeniero de software, y antes de que otros te digan exactamente eso, ¡te diré que eso es codswallop!

Las materias que ha mencionado son fundamentales para las matemáticas y, por lo tanto, de manera crucial, se aplican en casi todas las materias de ingeniería. De hecho, cualquier tema en el que esté involucrado algo parecido a un sistema.

Los algoritmos son inherentemente procesos justos. Por lo tanto, cualquier proceso es una forma de algoritmo y el estudio algorítmico de su complejidad de tiempo y espacio es tan útil en esos procesos como lo son en TI.

Considere la planificación urbana. Las rutas no son tan populares, pero cada cruce se puede modelar como un nodo con las carreteras entre ellas como arcos. Eso es un gráfico.

Gestión de proyectos de edificios, barcos, trenes o cualquier otra cosa. Los gráficos proporcionan redes para ejecutar análisis de red y optimizar dependencias.

Los gráficos también proporcionan cadenas de Markov para la identificación de riesgos.

Están involucrados en el diseño de circuitos, ya que los gráficos bipartitos son fundamentales para determinar si los tableros son de 1 capa, 2 capas o incluso más (es decir, se puede dibujar un circuito para que las pistas no se crucen. Ese es el problema básico del vendedor ambulante).

El flujo de trabajo a través de las empresas se puede modelar como un gráfico y un análisis de complejidad realizado al respecto. Los cerebros son solo gráficos si las neuronas, con la fuerza de las conexiones y la conductividad son los pesos en la matriz de adyacencia.

¡Genuinamente, las posibilidades y, de hecho, los usos reales son infinitos!

En mi experiencia, software de dispositivos médicos. Cualquier dispositivo médico que ingrese al cuerpo humano o dentro de él es requerido por la ley y una gran cantidad de regulaciones para tener “mitigaciones” por cualquier falla concebible (y muchas inconcebibles) tanto del software como del hardware. Al menos el 99% de estas fallas nunca ocurrirán ni una sola vez, pero tienen que tener mitigaciones y se debe demostrar que esas mitigaciones funcionan. Es bastante difícil demostrar que su mitigación para la falla de, por ejemplo, un circuito temporizador dentro de una MPU manejará correctamente el problema, cuando no puede causar la falla de HW a pedido y tal falla es tan rara que no es estadísticamente significativamente diferente de una probabilidad cero

Alrededor de 1995, creamos el acceso a Internet y los servicios aquí en Suiza. Fue muy divertido proporcionar acceso a Internet, crear sistemas de pago, correo, juegos, chat o servidores de listas y estábamos creciendo rápidamente. Unos años después, al convertirnos en una empresa más grande, surgió la idea de que necesitábamos una estructura de empresa profesional. No fue posible tener 5 técnicos de TI y unos cientos de personas de soporte telefónico dirigiendo todo el espectáculo.

Entonces obtuvimos algunos analistas y decidieron traer toneladas de gente nueva. Contamos con los mejores gerentes de productos de Nestle, Swissair, UBS y Lindt chocolate para organizarnos.

Un tipo que había sido responsable de los productos de clase empresarial en Swissair tuvo la increíble idea de que deberíamos buscar como Google … pero mejor. Convenció a los accionistas, vino a mí entusiasmado con su idea genial y no podía entender por qué no cumpliría. “Es solo una página web con un campo de entrada y algunos datos detrás”. Llegamos a un punto muerto. Se convirtió en una confrontación de la Guerra Fría entre la gestión de productos y la gestión de proyectos.

Ya no producimos nada nuevo, pero desde una perspectiva comercial, esto no importó. Siendo una empresa tan bien organizada ahora, nos compraron por una cantidad increíble de dinero. Pero esa compañía realmente no tenía los 4 mil millones, por lo que la obtuvieron de los bancos. ¡Ellos estaban felices de ayudar, si hacemos telefonía IP para Suiza! Telefonía … Fácil, ¿verdad?

Dejé la compañía allí mismo! No podía soportar la idea de pasar 10 años de mi vida con unos cientos de personas tratando en vano de hacer que eso funcione.

Cuando regresé a Suiza, 15 años después, lo tenían en funcionamiento. No estoy seguro de si alguna vez recuperarán los cientos de millones que gastaron en él. ¿Quién necesita un teléfono fijo más?

Como muestran las otras respuestas, muchas cosas son más complejas de desarrollar de lo que la gente podría darse cuenta. Pero hay una cosa que incluso los ingenieros de software pueden sorprenderse por su complejidad: contar.

En realidad, cualquier tipo de operación para almacenar cosas en sistemas distribuidos. Los contadores son un buen ejemplo porque están en todas partes y a menudo se incrementan rápidamente. Incrementar un contador en una sola máquina local también es fácil, pero tome algo como un recuento de reproducción de YouTube, por ejemplo:

  • Cada vez que alguien reproduce este video, el contador debe aumentar
  • Mucha gente puede ver el video en paralelo
  • Por razones de rendimiento y seguridad, también desea almacenar dicho contador en más de un sistema

Construir dicho contador distribuido es sorprendentemente difícil, tan difícil que YouTube inicialmente “falsificó” las vistas de reproducción hasta cierto punto porque actualizarlas en cada vista era demasiado costoso. [1]

Y así es como se implementaría algo como esto hoy: cómo construir un contador distribuido

Notas al pie

[1] 7 años de lecciones de escalabilidad de YouTube en 30 minutos – Alta escalabilidad –

Mucho más complejo de lo que la gente piensa:

  • GUI (“Te hice un dibujo, solo impleméntalo, estúpido”)
  • Juego (“Tengo una idea para un juego que es como una combinación de GTA V, Skyrim y Civilization, ¿puedes hacerlo por mí?”)
  • Integración de sistemas (“solo hágales hablar sin problemas, como mi iPhone y iPad”)
  • Aplicación móvil aleatoria (“Le daré el 0.1% de las ganancias si solo implementa mi idea”)
  • Sitio web (“Tengo un presupuesto de $ 1000”)
  • Aplicación web empresarial (“Tengo un presupuesto de $ 10,000”)
  • Módulo de aprendizaje automático (“simplemente inserte los datos en la API cerebral de [gran empresa de tecnología], cualquiera puede hacerlo”)
  • Solución IoT (“es plug and play”)
  • Arquitectura de Big Data (“yo quiero Big Data, dalo”)
  • Arreglando un error (“solo haz que funcione”)
  • Facebook (“mi idea es hacer el nuevo Facebook, excepto que mejor. Lo llamo … Facepalm”)

Sin mencionar mi favorito, estimar el proyecto (“¿por qué no me dices cuánto tiempo tomará?”)

Mucho más fácil de lo que la gente piensa:

  • Script que reemplaza su gran hoja de Excel que pasó años ajustando y manteniendo 10 horas a la semana (“de ninguna manera es posible”)

Prácticamente todo.

Pero supongo que quieres ejemplos divertidos, ¡así que hablemos de matemáticas básicas!

¡Numeros decimales! Las computadoras no pueden manejarlos.

Los procesadores de computadora funcionan con electricidad, por lo tanto, solo tiene un estado binario de información: hay electricidad o no la hay. Esto da origen a un sistema numérico binario básico que se puede convertir a cualquier sistema que desee, incluido el sistema decimal, para que pueda usar las computadoras para hacer cálculos. Las computadoras son excelentes para sumar, multiplicar y restar números enteros, pero cuando entra en el ámbito de la división, las cosas comienzan a ponerse raras. En pocas palabras, las computadoras tienen una capacidad limitada de almacenamiento de información, por lo que deben redondear los números hacia arriba o hacia abajo. Incluso cuando no hay necesidad de redondeo, las computadoras simplemente no funcionan con decimales.

En la mayoría de los lenguajes de computadora, intentar una operación como 0.1 + 0.2 probablemente arrojará algo como 0.30000000000000004.

En términos nerd, este es un problema aritmético de coma flotante. Hay un estándar llamado IEEE 754 que puede buscar para obtener más información. La mayoría de los idiomas lo siguen.

El problema generalmente aparece cuando se trata de finanzas y física.

Todo, en mi experiencia.

Es realmente difícil explicar exactamente lo que implica hacer que un botón de ‘comprar ahora’ realmente le lleve un producto a su puerta.

La cantidad de diseño de interacción del usuario, la cantidad de pruebas automatizadas, la gran escala de millones de líneas de código para algo ‘simple’ se pierde en tipos no técnicos.

Hay una cosa que se me ocurre.

Cualquier software que desee replicar las acciones de los humanos con pensamientos que se entienden implícitamente.

Permítanme ilustrar esto con un ejemplo. Supongamos un escenario en el que mi amigo y yo deseamos tener samosa de un vendedor ambulante. El vendedor no mantiene un registro de sus pedidos. Solo recuerda los pedidos, sabe qué cliente aún no le ha pagado y cuál aún no ha recibido una samosa. En una tarde ocupada cuando las ventas son altas, voy primero con él y le pido 2 samosas. Mi amigo que estaba en otra llamada hablando con alguien llega un poco más tarde a la escena. Se acerca, con un gesto amistoso me mira y asume que todavía no he ordenado nada y le dice al vendedor “dale 2 samosas hermano”.

¿Ahora el vendedor asumirá que son 2 pedidos o un solo pedido? De hecho, no lo toma como 2 órdenes separadas, pero entiende que dado que parecíamos estar esperando juntos y parecer amigos, debe ser el mismo orden. No nos preguntó si las órdenes eran separadas o iguales.

Ahora supongamos que intentamos construir una máquina dispensadora de samosa robótica. con 6 brazos (2 ayudantes), capacidades de reconocimiento facial y reconocimiento de voz que toma órdenes y entrega samosas simultáneamente como un humano. Ignoremos la operación de moneda / moneda por ahora y supongamos que reconoce la voz de un cliente genuino. Puede funcionar perfectamente bien hasta el escenario descrito anteriormente.

Es posible que necesitemos un conjunto complejo de algoritmos para poder distinguir / relacionar entre pedidos y obtener una imagen clara de cuántas samosas realmente se deben dispensar. Puede haber varios enfoques diferentes al respecto. Pero supongamos que tenemos que recrear un robot que pueda ” pensar ” como el vendedor que entendió automáticamente que las dos personas estaban relacionadas sin tener ningún detalle de cómo y, por lo tanto, tanto el pedido 1 como el pedido 2 eran duplicados y no dos pedidos diferentes.

PD: Podría haber hipotetizado y asumido pocas condiciones para presentar un escenario. Podría haber varias soluciones alternativas al problema que deberían ser evidentes para nosotros. La intención aquí es solo demostrar una posibilidad de instancias del mundo real que, cuando se replican con inteligencia artificial, podrían presentar un desafío para implementar.

Software que intenta realizar múltiples funciones diferentes en un solo módulo.

A menudo, un programador recibirá una especificación para un programa que tiene que realizar múltiples trabajos diferentes. Si el programador no tiene suficiente experiencia, intentarán escribir un solo programa para hacer todo. Esto da como resultado un programa muy complejo lleno de errores y difícil de mantener.

Una vez tuve que corregir los errores en un programa que produjo declaraciones de reembolso de hipotecas. Este programa recuperó todos los datos que necesitaba de la base de datos, realizó los cálculos necesarios y mostró los resultados en la pantalla. Eso hubiera estado bien, pero su trabajo no se detuvo allí. También generó resúmenes de canje impresos para ser enviados a los clientes. También tenía que almacenar las declaraciones y recuperar las declaraciones generadas previamente, a veces para su visualización y otras para ser reimpresas.

No era ciencia espacial y logré hacer que todo funcionara, pero hubiera sido mucho más simple si hubiera habido tres programas diferentes. Una calculadora de canje, un programa de recuperación y visualización y un programa de impresión.

Hace mucho tiempo aprendí que si duplicas el trabajo que quieres que haga un programa, requerirás cuatro veces más esfuerzo para desarrollarlo.

Cliente: Hola, acabo de ver esta increíble web del sitio web AWWWARD, ¿puede cambiar nuestro sitio web como este * show web on tablet “.

Yo: Uh … claro, ¿hay alguna fecha límite? o características específicas?

Cliente: No, así, con nuestro producto en él. Bueno … ¿podrías llegar en 2 semanas? Y por favor, es solo el front-end ¿verdad? Escuché que es menos complicado.

Yo: Uh … lo siento, pero …

Cliente: ¿Qué? no puedes Es solo front-end, ¿verdad? Eres nuestro mejor vendedor.

Yo: * facepalm * * llama al diseñador * Lucy, haz las maletas, viviremos en el estudio durante 2 semanas.

Por lo general, cada software es difícil de desarrollar. Si la gente no se da cuenta de la dificultad detrás de escena, ese software está bien desarrollado. El objetivo final de las empresas de desarrollo de software debe ofrecer un producto que los usuarios puedan usar fácilmente sin enfrentar ninguna dificultad. Entonces este es un logro para los desarrolladores.

El desarrollo de software necesita una planificación y dedicación sistemáticas que solo las personas relacionadas con el campo comprenderán.

Generalmente es un trabajo muy complejo en el que un desarrollador tiene que pensar y recordar muchos detalles de bajo nivel. Esos detalles solo son visibles para la persona que realiza el trabajo real y requerirá demasiado tiempo para explicar a las personas que no participan directamente en ellos. Esa es la razón por la que muchos ingenieros de software quieren pasar a roles gerenciales porque el esfuerzo realizado por un ingeniero de software no es tan visible para el mundo exterior y parece simple. Además, en general, los ingenieros de software tienden a minimizar el valor que crean porque, en su mayoría, son personas altamente educadas y bien intencionadas.

Sistemas de sincronización de datos de la OMI. No estoy hablando de intentar conectar algo como Firebase. Estoy hablando de codificar algo como Firebase desde cero. Eso es alucinante.

Toma Tinder como ejemplo.

Es una aplicación donde puedes subir una foto.

Se muestran otras fotos y puede decir sí / no y luego

Tienes una ventana de chat. Simple derecho?

Ahora piense en la escalabilidad.

Ahora calcule las distancias GPS entre todos estos dispositivos.

Ahora implemente un algoritmo de coincidencia.

Ahora implemente el inicio de sesión con Facebook.

Ahora agregue lógica de negocios con precios.

Hágalo confiable y hágalo disponible en varias plataformas.

Puede observar prácticamente cualquier pieza de software decente y los que no sean ingenieros no tendrán absolutamente ninguna idea de lo que se necesita para implementar algo así.

Como han dicho otros, todo.

Agregaré que la mayoría de las personas no se dan cuenta de que a menudo es más difícil de mantener que de desarrollar, ¡especialmente cuando se trata del código de otra persona!

El tema más importante “es qué tipos de software son mucho más complejos de desarrollar que las personas que * son * ingenieros de software”. La respuesta es “cualquier tipo”.

Para cada tipo de software hay toneladas de ingenieros listos para dar una cotización o comprometerse a una fecha límite, independientemente de si son conscientes de lo ignorantes que son.