Eu encontrei muitas pessoas que são dogmaticamente contra qualquer coisa que possa ser considerada "otimização" no sentido geral da palavra em inglês, e elas frequentemente citam literalmente a citação (parcial) "otimização prematura é a raiz de todo mal" como justificativa para a posição deles, o que implica que eles interpretam o que estou falando como "otimização prematura". No entanto, essas visões às vezes são tão ridiculamente arraigadas que descartam praticamente qualquer tipo de desvio algorítmico ou de estrutura de dados da mais pura implementação "ingênua" ... ou pelo menos qualquer desvio da maneira como fizeram as coisas antes.Como alguém pode abordar pessoas como essa de maneira a fazê-las "abrir os ouvidos" novamente depois que elas ficam impedidas de ouvir sobre "desempenho" ou "otimização"? Como discuto um tópico de design / implementação que afeta o desempenho sem que as pessoas pensem instantaneamente: "Esse cara quer passar duas semanas em dez linhas de código?"
Agora, a posição de "toda otimização é prematura e, portanto, má" já foi abordada aqui e em outros cantos da Web , e já foi discutido como reconhecer quando a otimização é prematura e, portanto , má , mas infelizmente, ainda existem pessoas no mundo real que não são tão abertas a desafios quanto à sua fé na antit Otimização.
Tentativas anteriores
Algumas vezes, tentei fornecer a citação completa de Donald Knuth para explicar que "a otimização prematura é ruim" ↛ "toda a otimização é ruim":
Devemos esquecer pequenas eficiências, digamos, 97% das vezes: a otimização prematura é a raiz de todo mal. No entanto, não devemos desperdiçar nossas oportunidades nesses 3% críticos.
No entanto, ao fornecer a cotação inteira, essas pessoas às vezes ficam mais convencidas de que o que estou fazendo é Premature Optimization ™, desenterram e se recusam a ouvir. É quase como se a palavra "otimização" os assusta: em algumas ocasiões, fui capaz de propor alterações reais no código para melhorar o desempenho sem que elas fossem vetadas, simplesmente evitando o uso da palavra "otimização (e | ação)" ( e "desempenho" também - essa palavra também é assustadora) e, em vez disso, usa alguma expressão como "arquitetura alternativa" ou "implementação aprimorada". Por essa razão, realmente parece que isso é realmente dogmatismo e não eles, de fato, avaliando o que digo criticamente e depois descartando-o como desnecessário e / ou muito caro.
fonte
Respostas:
Parece que você está procurando atalhos para não experimentar a "implementação ingênua mais pura" primeiro e implementar diretamente uma "solução mais sofisticada porque você sabe de antemão que a implementação ingênua não fará isso". Infelizmente, isso raramente funciona - quando você não possui fatos concretos ou argumentos técnicos para provar que a implementação ingênua é ou será muito lenta, você provavelmente está errado e o que está fazendo é a otimização prematura. E tentar discutir com Knuth é o oposto de ter um fato difícil.
Na minha experiência, você terá que concordar e tentar a "implementação ingênua" primeiro (e provavelmente ficará surpreso com a frequência com que isso é rápido o suficiente), ou pelo menos fará uma estimativa aproximada do tempo de execução, como:
"A implementação ingênua será O (n³), e n é maior que 100.000; isso durará alguns dias, enquanto a implementação não tão ingênua será executada em O (n), que levará apenas alguns minutos" .
Somente com esses argumentos em mãos, você pode ter certeza de que sua otimização não é prematura.
Há apenas uma exceção no IMHO : quando a solução mais rápida também é a mais simples e mais limpa, você deve usar a solução mais rápida desde o início. O exemplo padrão é o de usar um dicionário em vez de uma lista para evitar códigos de loop desnecessários para pesquisas ou o uso de uma boa consulta SQL que fornece exatamente o registro de um resultado necessário, em vez de um grande conjunto de resultados que deve ser filtrado posteriormente no código. Se você tiver esse caso, não discuta sobre desempenho- o desempenho pode ser um benefício adicional, mas provavelmente irrelevante, e quando você o menciona, as pessoas podem ficar tentadas a usar Knuth contra você. Discuta sobre legibilidade, código mais curto, código mais limpo, capacidade de manutenção - não é necessário "mascarar" nada aqui, mas porque esses (e somente esses) são os argumentos corretos aqui.
De acordo com a minha experiência, o último caso é raro - o mais comum é o caso de se poder primeiro implementar uma solução simples e ingênua, que seja melhor compreensível e menos propensa a erros do que uma mais complicada, mas provavelmente mais rápida.
E, é claro, você deve conhecer os requisitos e o caso de uso suficientemente bem para saber qual desempenho é aceitável e quando as coisas ficam "muito lentas" aos olhos dos usuários. Em um mundo ideal, você obteria uma especificação formal de desempenho por seu cliente, mas em projetos do mundo real, o desempenho exigido costuma ser uma área cinzenta, algo que seus usuários só dizem quando observam que o programa se comporta "muito devagar" na produção. E, muitas vezes, essa é a única maneira de descobrir quando algo é muito lento - o feedback do usuário, e então você não precisa citar Knuth para convencer seus colegas de equipe de que a "implementação ingênua" não era suficiente.
fonte
Pergunte a si mesmo:
Essas são razões para otimizar. Portanto, se as pessoas se opuserem, apenas mostre a especificação e volte a elas e explique que precisamos otimizar porque não estamos atendendo às especificações. Fora isso, seria difícil convencer os outros de que a otimização é necessária.
Acho que o principal ponto da citação é que, se você não tiver um problema, não execute otimizações desnecessárias, pois tempo e energia poderiam ser gastos em outros lugares. Do ponto de vista comercial, isso faz todo o sentido.
Secundário, para aqueles que temem a otimização, sempre faça backup das descobertas de desempenho com métricas. Quanto mais rápido é o código? Quanto o desempenho melhorou em relação ao anterior? Se alguém gastasse duas semanas apenas para melhorar o código em 2% em relação à versão anterior, se eu fosse seu chefe, não ficaria feliz. Essas duas semanas poderiam ter sido gastas implementando um novo recurso que poderia atrair mais clientes e ganhar mais dinheiro.
Finalmente, a maioria dos softwares não precisa ser altamente otimizada. Somente em algumas indústrias especializadas a velocidade é realmente importante. Portanto, na maioria das vezes é possível usar bibliotecas e estruturas preexistentes com bons resultados.
fonte
Comece com princípios compartilhados que se baseiam na direção estratégica do seu grupo.
Meus princípios:
Meus princípios pessoais sobre como escrever código devem primeiro buscar a correção no meu programa, depois analisá-lo e determinar se ele precisa de otimização. Eu perfil meu código porque outros programadores são consumidores potenciais do meu código - e eles não o usarão se for lento - portanto, para o meu código, a velocidade é um recurso.
Se seus consumidores são clientes, eles lhe dirão se você precisa de um código mais rápido.
No entanto, existem escolhas comprovadamente melhores no código que se pode fazer. Prefiro acertar no meu primeiro rascunho por vários motivos:
Supondo que a necessidade de otimização esteja correta
Supondo que essa é uma parte realmente importante do seu código que precisa de otimização, você pode contar a parábola de Schlemiel, o Pintor , ou enfatizar o restante da citação:
Pesar os custos de complexidade adicional
Às vezes, há um custo real em termos de manutenção da complexidade adicionada. Nesse caso, você pode manter a implementação secundária em uma função ou subclasse diferente e aplicar os mesmos unittests nela, para que não haja dúvida de que ela está correta. Posteriormente, se você criar um perfil de seu código e considerar a implementação ingênua um gargalo, poderá alternar seu código otimizado e comprovadamente melhorar seu programa.
Liderança
Às vezes, o problema é o ego - algumas pessoas preferem usar código abaixo do ideal ou com erros do que alguém mais certo do que é. Você provavelmente quer evitar trabalhar com essas pessoas.
Liderança, especialmente quando você não tem autoridade posicional sobre as pessoas, é fazer sugestões razoáveis e guiar outras pessoas a um consenso. Se você não pode guiar sua equipe para um encontro de mentes, talvez não valha a pena insistir no assunto. Provavelmente há peixes maiores para fritar.
fonte
O caminho a seguir é esquecer a citação real e as várias interpretações - é dogmatismo de qualquer maneira concentrar-se tanto em uma citação específica de um guru. Quem disse que Knuth está sempre certo, afinal?
Em vez disso, concentre-se no projeto em questão, o software que você está desenvolvendo junto com os colegas dos quais você não concorda. Quais são os requisitos para um desempenho aceitável para este software? É mais lento que isso? Então otimize.
Você não precisa chamá-lo de "otimização", pode chamá-lo de "consertar um bug", pois é por definição um bug se a implementação falhar em conformidade com os requisitos.
De maneira mais geral, existem duas possibilidades em relação às otimizações:
O código otimizado também é mais curto, mais simples de entender e mais fácil de manter.
O código otimizado é mais complexo de entender, leva mais tempo para escrever e testar ou seria mais complexo mudar no futuro se os requisitos mudarem de maneiras inesperadas.
Se o caso for (1), você nem precisa discutir sobre otimização. Mas se (2) for o caso, você estará envolvido em uma decisão de troca . Na verdade, essa é uma decisão em nível de negócios, não puramente técnica. Você precisa pesar o custo da otimização em relação ao benefício. Para que haja um benefício, a ineficiência deve ser um problema em primeiro lugar, como má experiência do usuário ou aumento significativo do custo de hardware ou outros recursos.
fonte
Eu acho que a citação completa no contexto é instrutiva. Vou copiar de um post que fiz no Reddit sobre o tema:
- Donald Knuth, Programação Estruturada com ir para Declarações , ACM Computing Surveys, Vol. 6, No. 4, Dez. 1974, p.268
O ponto e a implicação é que há coisas mais importantes com que se preocupar do que dedicar sua atenção à otimização muito cedo. Certamente, você deve considerar cuidadosamente suas estruturas de dados e algoritmos (isso é de 3%), mas não deve se preocupar se a subtração é mais rápida que o módulo (sendo de 97%) até ficar claro que a otimização de baixo nível é necessário.
O primeiro não é necessariamente otimização no sentido em que seus colegas estão pensando, mas é otimização no sentido de que algoritmos e estruturas de dados mal escolhidos são abaixo do ideal.
fonte
Na minha experiência, se você se opõe a esse tipo de otimização regularmente , as pessoas não estão realmente reclamando da otimização. Eles estão reclamando do que você está sacrificando em nome da otimização. Isso geralmente é legibilidade, capacidade de manutenção ou pontualidade. Se o seu código for entregue na mesma quantidade de tempo e fácil de entender, as pessoas não se importarão se você estiver usando estruturas e algoritmos de dados mais eficientes. Minha sugestão nesse caso é trabalhar para tornar seu código mais elegante e sustentável.
Se você está recebendo esse tipo de oposição em relação ao código de outras pessoas, geralmente é porque está sugerindo uma quantidade significativa de retrabalho. Nesses casos, você realmente precisa de algumas medidas reais para mostrar que vale a pena o esforço, ou talvez tente se envolver mais cedo na fase de design, antes que o código seja escrito. Em outras palavras, você precisa provar que está nos 3%. Se reescrevéssemos todo o código que não era exatamente como gostávamos, nunca conseguiríamos realizar nada.
fonte
Deque
da biblioteca padrão Java para substituir uma enorme quantidade de lógica construída em torno de umaArrayList
usada como uma pilha enquanto trabalhava no código ... e isso foi marcado como mudança na revisão. Em outras palavras, o revisor queria ter mais código, que também é mais lento e mais propenso a erros, porque ele não estava familiarizadoDeque
.De fato, existem muitos mal-entendidos sobre essa citação; portanto, é melhor dar um passo atrás e analisar qual é o problema real. O problema não é tanto que você nunca deve "otimizar". É que "otimizar" nunca é uma tarefa que você deve se preparar. Você nunca deve acordar de manhã e dizer para si mesmo "ei, eu deveria otimizar o código hoje!".
Isso leva ao desperdício de esforço. Basta olhar para o código e dizer "Eu posso torná-lo mais rápido!" leva a muito esforço para fazer algo mais rápido que foi rápido o suficiente em primeiro lugar. Você pode se orgulhar de dizer a si mesmo que fez um pouco de código quatro vezes mais rápido, mas se esse código era um cálculo que acontecia com o pressionar de um botão e, em primeiro lugar, eram necessários 10 ms antes de exibir para um usuário humano, ninguém vai dar a mínima.
Esse é o "prematuro" na "otimização prematura". Quando não é "prematuro"? Quando os clientes dizem "isso é muito lento, conserte!" É quando você digita o código e tenta torná-lo mais rápido.
Isso não significa que você deve desligar seu cérebro. Isso não significa que você deve manter 10.000 registros de clientes em uma lista vinculada individualmente. Você sempre deve entender os impactos no desempenho do que faz em mente e agir em conformidade. Mas a ideia é que você não gaste tempo extra deliberadamente tentando torná-lo mais rápido. Você está simplesmente escolhendo a opção com melhor desempenho dentre as opções iguais.
fonte
Você pode fazer as coisas da maneira errada ou fazer as coisas da maneira certa.
Freqüentemente, as coisas são feitas da maneira errada e o código é refatorado para que seja feito da maneira certa. Se você vai escrever um novo código e sabe que pode fazer as coisas da maneira certa sem uma grande penalidade, eu iria errar ao fazê-lo da maneira certa. (Observe que, após testes de desempenho, etc., algumas coisas podem precisar mudar - mas tudo bem. Como alternativa, uma implementação completamente ingênua raramente é, se é que alguma vez, é correta.)
Não é necessariamente uma otimização prematura se você a) souber que isso ajudará no futuro ou b) saber que o caminho abaixo do ideal levará a problemas futuros. É como um jogo de xadrez, na verdade.
Eu acho que as pessoas tendem a querer fazer as coisas certas, ao invés de fazerem errado. Use isso quando discutir estratégias alternativas com seus colegas.
fonte
Isso parece ser um problema de comunicação e não um problema de programação. Tente entender por que as pessoas se sentem assim e tente cristalizar por que você acha que seu caminho seria melhor. Quando você tiver feito isso, não inicie uma discussão de confronto em que seu objetivo é contar aos outros porque eles estão errados e você está certo. Explique seus pensamentos e sentimentos e deixe as pessoas reagirem a isso. Se você não consegue chegar a nenhum tipo de consenso e sente que esse é um problema muito crítico, provavelmente há alguns problemas sérios na equipe em geral.
Mais focado na programação real, não perca tempo com longas discussões sobre algo que você apenas sente que é "mais rápido". Se você vir alguém escrevendo um método chamado uma vez por solicitação em um aplicativo Web e ele tem complexidade de tempo O (n ^ 2) quando você SABE que é realmente um problema de tempo O (log (n)), então é claro, se é um acéfalo, vá em frente.
Esteja ciente, porém, que, como seres humanos, nós programadores somos péssimos (e quero dizer INCRÍVEIS) em adivinhar quais partes de nossos aplicativos serão prejudicadas. Eric Lippert escreve sobre esse assunto interessante nesta postagem do blog. Sempre favorecer a manutenção. Quaisquer problemas de desempenho que eventualmente sejam encontrados podem ser corrigidos facilmente (bem, relativamente) quando você tiver mais informações.
fonte