Me he encontrado con muchas personas que están dogmáticamente en contra de cualquier cosa que pueda considerarse "optimización" en el sentido general de la palabra en el idioma inglés, y muy a menudo citan textualmente la cita (parcial) "la optimización prematura es la raíz de todo mal". como justificación de su postura, lo que implica que interpretan lo que estoy hablando como "optimización prematura". Sin embargo, estas opiniones a veces están tan ridículamente arraigadas que descartan casi cualquier tipo de desviaciones algorítmicas o de estructura de datos de la implementación "ingenua" más pura ... o al menos cualquier desviación de la forma en que han hecho las cosas antes.¿Cómo puede uno acercarse a las personas de esta manera para que vuelvan a "abrir los oídos" después de dejar de escuchar sobre "rendimiento" u "optimización"? ¿Cómo discuto un tema de diseño / implementación que tiene un impacto en el rendimiento sin que la gente piense instantáneamente: "Este tipo quiere pasar dos semanas en diez líneas de código?"
Ahora, la postura de si "toda la optimización es prematura y, por lo tanto, malvada" o no ya se ha cubierto aquí , así como en otros rincones de la Web , y ya se ha discutido cómo reconocer cuándo la optimización es prematura y, por lo tanto , mala , pero desafortunadamente todavía hay personas en el mundo real que no están tan abiertas a los desafíos a su fe en Anti-Optimization.
Intentos anteriores
Algunas veces, he intentado proporcionar la cita completa de Donald Knuth para explicar que "la optimización prematura es mala" ↛ "toda la optimización es mala":
Deberíamos olvidarnos de las pequeñas eficiencias, digamos alrededor del 97% del tiempo: la optimización prematura es la raíz de todo mal. Sin embargo, no debemos dejar pasar nuestras oportunidades en ese crítico 3%.
Sin embargo, al proporcionar la cotización completa, estas personas a veces se convencen más de que lo que estoy haciendo es Optimización Prematura ™ y profundizan y se niegan a escuchar. Es casi como si la palabra "optimización" los asustara: en un par de ocasiones, pude proponer cambios reales en el código para mejorar el rendimiento sin que fueran vetados simplemente evitando el uso de la palabra "optimiz (e | ation)" ( y "rendimiento" también, esa palabra también da miedo) y en su lugar usa alguna expresión como "arquitectura alternativa" o "implementación mejorada". Por esta razón, realmente parece que esto realmente es dogmatismo y no ellos, de hecho, evalúan lo que digo críticamente y luego lo descartan como no necesario y / o demasiado costoso.
Respuestas:
Parece que está buscando atajos para no probar primero la "implementación más pura e ingenua" e implementar directamente una "solución más sofisticada porque sabe de antemano que la implementación ingenua no lo hará". Desafortunadamente, esto rara vez funcionará: cuando no tiene hechos concretos o argumentos técnicos para demostrar que la implementación ingenua es o será demasiado lenta, lo más probable es que esté equivocado, y lo que está haciendo es la optimización prematura. Y tratar de discutir con Knuth es lo contrario de tener un hecho difícil.
En mi experiencia, tendrá que morder la bala e intentar primero la "implementación ingenua" (y probablemente se sorprenderá de la frecuencia con que esto es lo suficientemente rápido), o al menos hará una estimación aproximada sobre el tiempo de ejecución, como:
"La implementación ingenua será O (n³), yn es mayor que 100.000; eso se ejecutará algunos días, mientras que la implementación no tan ingenua se ejecutará en O (n), lo que tomará solo unos minutos" .
Solo con tales argumentos a mano puede estar seguro de que su optimización no es prematura.
En mi humilde opinión, solo hay una excepción : cuando la solución más rápida es también la más simple y limpia, entonces debe usar la solución más rápida desde el principio. El ejemplo estándar es el de usar un diccionario en lugar de una lista para evitar el código de bucle innecesario para las búsquedas, o el uso de una buena consulta SQL que le proporciona exactamente el único registro de resultados que necesita, en lugar de un gran conjunto de resultados que debe ser luego filtrado en código. Si tiene un caso así, no discuta sobre el rendimiento- el rendimiento puede ser un beneficio adicional, pero muy probablemente irrelevante, y cuando lo mencionas, la gente podría verse tentada a usar Knuth en tu contra. Discuta sobre la legibilidad, el código más corto, el código más limpio, la capacidad de mantenimiento: no es necesario "enmascarar" nada aquí, sino porque esos (y solo esos) son los argumentos correctos aquí.
Según mi experiencia, el último caso es raro: el caso más típico es que uno puede implementar primero una solución simple e ingenua que sea mejor comprensible y menos propensa a errores que una más complicada, pero probablemente más rápida.
Y, por supuesto, debe conocer los requisitos y el caso de uso lo suficientemente bien como para saber qué rendimiento es aceptable y cuándo las cosas se vuelven "demasiado lentas" a los ojos de sus usuarios. En un mundo ideal, obtendría una especificación formal de rendimiento por parte de su cliente, pero en proyectos del mundo real, el rendimiento requerido es a menudo un área gris, algo que sus usuarios solo le dirán cuando noten que el programa se comporta "demasiado lento" en la producción. Y a menudo, esa es la única forma de averiguar cuándo algo es demasiado lento: los comentarios de los usuarios y luego no es necesario citar a Knuth para convencer a sus compañeros de equipo de que su "implementación ingenua" no fue suficiente.
fuente
Pregúntate esto:
Estas son razones para optimizar. Entonces, si las personas se oponen, solo muéstreles la especificación y regrese a ellos y explique que necesitamos optimizar porque no estamos cumpliendo con las especificaciones. Aparte de eso, uno tendría dificultades para convencer a otros de que la optimización es necesaria.
Creo que el punto principal de la cita es que, si no tiene un problema, no realice una optimización innecesaria ya que el tiempo y la energía podrían gastarse en otro lugar. Desde una perspectiva empresarial, esto tiene mucho sentido.
Secundario, para aquellos que temen la optimización, siempre respalden los resultados de rendimiento con métricas. ¿Cuánto más rápido es el código? ¿Cuánto mejoró el rendimiento con respecto al anterior? Si uno pasara dos semanas solo para mejorar el código en un 2% con respecto a la versión anterior, si yo fuera su jefe, no sería feliz. Esas dos semanas podrían haberse dedicado a implementar una nueva característica que podría atraer a más clientes y ganar más dinero.
Finalmente, la mayoría del software no tiene que estar altamente optimizado. Solo en unas pocas industrias especializadas la velocidad es realmente importante. Por lo tanto, la mayoría de las veces uno puede usar bibliotecas y marcos preexistentes con buenos resultados.
fuente
Comience con principios compartidos que se basan en la dirección estratégica de su grupo.
Mis principios:
Mis principios personales en la escritura de código son primero apuntar a la corrección en mi programa, luego perfilarlo y determinar si necesita optimización. Yo mismo perfilo mi código porque otros programadores son consumidores potenciales de mi código, y no lo usarán si es lento, por lo tanto, para mi código, la velocidad es una característica.
Si sus consumidores son clientes, sus clientes le dirán si necesita un código más rápido.
Sin embargo, hay opciones conocidas y demostrablemente mejores en el código que uno puede hacer. Prefiero hacerlo bien en mi primer borrador por varias razones:
Asumir que la necesidad de optimización es correcta
Asumiendo que esta es una parte verdaderamente importante de su código que necesita optimización, podría contar la parábola de Schlemiel el pintor , o enfatizar el resto de la cita:
Sopesar los costos de la complejidad adicional.
A veces hay un costo real en términos de mantenibilidad de la complejidad añadida. En este caso, puede mantener la implementación secundaria en una función o subclase diferente, y aplicarle las mismas pruebas unitarias para que no haya dudas de que es correcta. Más tarde, si perfila su código y encuentra que la implementación ingenua es un cuello de botella, puede cambiar su código optimizado y mejorar su programa de manera demostrable.
Liderazgo
A veces, el problema es el ego: algunas personas prefieren usar un código subóptimo o defectuoso antes de que alguien más tenga más razón de lo que ellos son. Probablemente quieras evitar trabajar con estas personas.
El liderazgo, especialmente cuando no tienes autoridad posicional sobre las personas, consiste en hacer sugerencias razonables y guiar a otros a un consenso. Si no puede guiar a su equipo a una reunión de las mentes, quizás no valga la pena presionar el asunto. Probablemente hay peces más grandes para freír.
fuente
El camino a seguir es olvidarse de la cita real y las diversas interpretaciones: es dogmatismo de cualquier manera enfocarse tanto en una cita específica de un gurú. ¿Quién dice que Knuth siempre tiene razón de todos modos?
En lugar de eso, enfóquese en el proyecto en cuestión, el software que está desarrollando junto con los colegas con los que no está de acuerdo. ¿Cuáles son los requisitos para un rendimiento aceptable para este software? ¿Es más lento que esto? Entonces optimiza.
No tiene que llamarlo "optimización", puede llamarlo "corregir un error", ya que, por definición, es un error si la implementación no cumple con los requisitos.
En términos más generales, hay dos posibilidades con respecto a las optimizaciones:
El código optimizado también es más corto, más simple de entender y más fácil de mantener.
El código optimizado es más complejo de entender, lleva más tiempo escribirlo y probarlo, o sería más complejo cambiarlo en el futuro si los requisitos cambian de manera inesperada.
Si el caso es (1), ni siquiera tiene que discutir sobre la optimización. Pero si (2) es el caso, entonces está tomando una decisión de compensación . Esta es en realidad una decisión de nivel empresarial, no puramente una decisión técnica. Debe sopesar el costo de la optimización contra el beneficio. Para que haya incluso un beneficio, la ineficiencia tiene que ser un problema en primer lugar, ya sea como mala experiencia del usuario o aumento significativo del costo del hardware u otros recursos.
fuente
Creo que la cita completa en contexto es instructiva. Copiaré de una publicación que hice en Reddit sobre el tema:
- Donald Knuth, Programación estructurada con ir a declaraciones , Encuestas de computación de ACM, Vol. 6, No. 4, diciembre de 1974, p.268
El punto, y la implicación, es que hay cosas más importantes de las que preocuparse que poner su atención en la optimización demasiado pronto. Ciertamente, debe considerar cuidadosamente sus estructuras de datos y algoritmos (esto está en el 3%), pero no debe preocuparse por si la resta es más rápida que el módulo (esto está en el 97%) hasta que quede claro que la optimización de bajo nivel es necesario.
Lo primero no es necesariamente optimización en el sentido en que piensan sus colegas, pero es optimización en el sentido de que los algoritmos y estructuras de datos mal elegidos son subóptimos.
fuente
En mi experiencia, si obtienes este tipo de oposición a la optimización regularmente , la gente no se queja realmente de la optimización. Se quejan de lo que está sacrificando en nombre de la optimización. Esto suele ser legibilidad, mantenibilidad o puntualidad. Si su código se entrega en la misma cantidad de tiempo y es igual de fácil de entender, a la gente no le importaría menos si está utilizando estructuras de datos y algoritmos más eficientes. Mi sugerencia en este caso es trabajar para que su código sea más elegante y fácil de mantener.
Si está obteniendo este tipo de oposición con respecto al código de otras personas, generalmente es porque está sugiriendo una cantidad significativa de retrabajo. En esos casos, realmente necesita algunas mediciones reales para demostrar que vale la pena el esfuerzo, o tal vez intente involucrarse más temprano en la fase de diseño, antes de escribir el código. En otras palabras, debes demostrar que está en el 3%. Si reescribiéramos todo el código que no era exactamente como nos gustaba, nunca lograríamos nada.
fuente
Deque
de la biblioteca estándar de Java para reemplazar una gran cantidad de lógica construida alrededor de unaArrayList
utilizada como una pila mientras trabajo en el código ... y esto fue marcado para cambio en la revisión. En otras palabras, el revisor quería tener más código, que también es más lento y más propenso a errores porque no estaba familiarizadoDeque
.De hecho, hay muchos malentendidos sobre esta cita, por lo que es mejor dar un paso atrás y ver cuál es el problema real. El problema no es tanto que nunca debas "optimizar". Es que "optimizar" nunca es una tarea que debe hacer. Nunca debes levantarte por la mañana y decirte a ti mismo "¡Hola, hoy debería optimizar el código!".
Esto lleva a un esfuerzo perdido. Simplemente mirando el código y diciendo "¡Puedo hacerlo más rápido!" conduce a un gran esfuerzo para hacer algo más rápido que fue lo suficientemente rápido en primer lugar. Puede que te enorgullezca decirte a ti mismo que hiciste un poco de código cuatro veces más rápido, pero si ese código fue un cálculo que sucedió al presionar un botón, y tomó 10 ms en primer lugar antes de mostrarlo a un usuario humano, nadie va a importar un bledo
Ese es el "prematuro" en "optimización prematura". ¿Cuándo no es "prematuro"? Cuando los clientes te digan "esto es demasiado lento, ¡arréglalo!" Ahí es cuando cavas el código e intentas hacerlo más rápido.
Esto no significa que debas apagar tu cerebro. No significa que deba mantener 10,000 registros de clientes en una lista vinculada individualmente. Siempre debe comprender los impactos en el rendimiento de lo que hace en mente y actuar en consecuencia. Pero la idea es que no estás gastando tiempo extra deliberadamente tratando de hacerlo más rápido. Simplemente está eligiendo la opción más eficiente de otras opciones iguales.
fuente
Puedes hacer las cosas de la manera incorrecta o hacer las cosas de la manera correcta.
A menudo, las cosas se hacen de la manera incorrecta y el código se refactoriza para que se haga de la manera correcta. Si va a escribir un código nuevo, y sabe que puede hacer las cosas de la manera correcta sin una penalización importante, simplemente me equivocaría al hacerlo de la manera correcta. (Tenga en cuenta que, después de las pruebas de rendimiento, etc., es posible que algunas cosas necesiten cambiar, pero está bien. Alternativamente, una implementación completamente ingenua rara vez, si alguna vez, es correcta).
No es necesariamente una optimización prematura si a) sabe que ayudará en el futuro ob) sabe que el camino subóptimo conducirá a problemas en el futuro. Es como un juego de ajedrez, de verdad.
Creo que la gente tenderá a querer hacer las cosas bien, en lugar de hacerlas mal. Use esto cuando discuta estrategias alternativas con sus compañeros.
fuente
Esto parece un problema de comunicación y no un problema de programación. Intenta entender por qué las personas sienten lo que sienten y trata de cristalizar por qué crees que tu camino sería mejor. Cuando haya hecho eso, no comience un argumento de confrontación en el que su objetivo sea decirles a los demás por qué están equivocados y usted tiene razón. Explica tus pensamientos y sentimientos y deja que la gente reaccione a eso. Si no puede llegar a ningún tipo de consenso y siente que este es un problema realmente crítico, entonces probablemente tenga algunos problemas serios en el equipo en general.
Más centrado en la programación real, no pierda el tiempo en largas discusiones sobre algo que simplemente tiene una intuición es "más rápido". Si ve a alguien que escribe un método que se llama una vez por solicitud en una aplicación web y tiene una complejidad de tiempo O (n ^ 2) cuando SABE que realmente es un problema de tiempo O (log (n)), entonces seguro, si es así un obvio, adelante.
Sin embargo, tenga en cuenta que, como humanos, los programadores somos realmente malos (y me refiero a HORRIBLE) al adivinar qué partes de nuestras aplicaciones tendrán un cuello de botella. Eric Lippert escribe sobre este interesante tema en esta publicación de blog. Siempre favorece la mantenibilidad. Cualquier problema de rendimiento que finalmente se encuentre se puede solucionar fácilmente (bueno, relativamente) cuando tenga más información.
fuente