Quais “melhores práticas” populares nem sempre são as melhores e por quê? [fechadas]

100

As "melhores práticas" estão por toda parte em nosso setor. Uma pesquisa no Google sobre "práticas recomendadas de codificação" mostra quase 1,5 milhão de resultados. A idéia parece trazer conforto para muitos; basta seguir as instruções e tudo ficará bem.

Quando leio sobre uma prática recomendada - por exemplo, acabei de ler várias no Clean Code recentemente - fico nervoso. Isso significa que eu sempre deveria usar essa prática? Existem condições anexadas? Existem situações em que pode não ser uma boa prática? Como posso ter certeza até aprender mais sobre o problema?

Várias das práticas mencionadas no Código Limpo não se encaixam bem comigo, mas sinceramente não tenho certeza se isso é potencialmente ruim ou se é apenas o meu viés pessoal falando. Sei que muitas pessoas proeminentes na indústria de tecnologia parecem pensar que não existem práticas recomendadas ; portanto, pelo menos minhas dúvidas incômodas me colocam em boa companhia.

O número de práticas recomendadas sobre as quais eu li é simplesmente muito numeroso para listar aqui ou fazer perguntas individuais, portanto, gostaria de colocar isso como uma pergunta geral:

Quais práticas de codificação popularmente rotuladas como "melhores práticas" podem ser subótimas ou até prejudiciais sob certas circunstâncias? Quais são essas circunstâncias e por que elas tornam a prática ruim?

Eu preferiria ouvir sobre exemplos e experiências específicas.

Aaronaught
fonte
8
Quais são as práticas com as quais você não concorda ?, apenas curioso.
Sergio Acosta
Qualquer um pode escrever um livro, e eu não tenho que concordar com isso - é tão simples assim.
Job
Uma coisa que eu gosto no livro "Code Complete", de Steve McConnell, é que ele faz backup de todas as suas dicas com fortes evidências e pesquisas. Apenas dizendo
JW01 17/01
5
@ Walter: Isso está aberto há meses, é definitivamente construtivo, por que fechá-lo?
Orbling 18/01
2
Considerando como meu nome está sendo mencionado aqui, suponho que devo entrar em contato: acredito que as respostas aqui são valiosas, mas a pergunta pode ser reformulada em algo definitivamente menos semelhante a uma pesquisa sem invalidar nenhuma das respostas. Exemplo de título: "Quais práticas recomendadas populares às vezes podem ser prejudiciais e quando / por quê?"
precisa saber é o seguinte

Respostas:

125

Eu acho que você acertou a cabeça com esta declaração

Eu odiaria levar as coisas pelo valor nominal e não pensar nelas criticamente

Ignoro quase todas as práticas recomendadas quando não são fornecidas explicações sobre por que existem

Raymond Chen coloca melhor neste artigo quando ele diz

Um bom conselho vem com uma justificativa para que você possa saber quando se torna um mau conselho. Se você não entende por que algo deve ser feito, você caiu na armadilha da programação de cultos de carga e continuará fazendo isso mesmo quando não for mais necessário ou se tornar prejudicial.

Conrad Frix
fonte
4
Citação maravilhosa.
David Thornley
O próximo parágrafo dessa citação de Raymond Chen provavelmente descreve a notação húngara! A maioria das empresas que vejo o utiliza sem um motivo real que possa explicar.
Craig
3
Espero que as pessoas não tomem isso como uma desculpa para não procurar o que está por trás das melhores práticas. ;) Infelizmente, vi desenvolvedores com essa atitude.
Vetle 27/10/10
3
A justificativa é boa. Pesquisa é melhor.
Jon Purdy
7
Absolutamente verdade, e eu já disse o mesmo antes. Talvez o primeiro padrão em qualquer documento de "Padrões" deva ler: "No interesse de compartilhar conhecimento e fornecer as informações necessárias para rescindir os padrões posteriormente, todos os padrões devem incluir os motivos de sua existência".
Scott Whitlock
95

É melhor jogar isso no ringue:

Premature optimization is the root of all evil.

Não, não é.

A citação completa:

"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".

Isso significa que você aproveita aprimoramentos específicos e estratégicos de desempenho em todo o processo de design. Isso significa que você usa estruturas de dados e algoritmos que são consistentes com os objetivos de desempenho. Isso significa que você está ciente das considerações de design que afetam o desempenho. Mas isso também significa que você não otimiza frivolamente ao fazê-lo, proporcionando ganhos menores à custa da manutenção.

Os aplicativos precisam ser bem arquitetados, para que não caiam no final quando você aplica um pouco de carga neles, e então você os reescreve. O perigo da citação abreviada é que, com muita frequência, os desenvolvedores a usam como desculpa para não pensar em desempenho até o final, quando pode ser tarde demais para fazer algo a respeito. É melhor obter um bom desempenho desde o início, desde que você não se concentre nas minúcias.

Digamos que você esteja criando um aplicativo em tempo real em um sistema incorporado. Você escolhe Python como a linguagem de programação, porque "A otimização prematura é a raiz de todos os males". Agora não tenho nada contra o Python, mas é uma linguagem interpretada. Se o poder de processamento for limitado, e uma certa quantidade de trabalho precisar ser realizada em tempo real ou quase em tempo real, e você escolher um idioma que exija mais poder de processamento para o trabalho do que o seu, você estará realmente ferrado, porque agora tem que começar de novo com uma linguagem capaz.

Robert Harvey
fonte
4
+1 para os fortes Não, não é.
Stephen
21
Mas se você já reconheceu que uma otimização específica está dentro desses 3% críticos, é prematuro para otimizá-la?
John
7
@ Robert: Então, qual é o ponto de discordância com a afirmação de que "a otimização prematura é a raiz de todo mal"?
John
8
Nunca é prematuro otimizar o design de alto nível e as decisões técnicas, como a escolha do idioma. No entanto, muitas vezes é somente depois que você conclui um projeto que suas ineficiências se tornam aparentes, e é por isso que Fred Brooks disse que a maioria das equipes escreve uma versão descartável, querendo ou não. Outro argumento para prototipagem.
Dominique McDonnell
8
@ Robert, a citação Knuth foi otimizado prematuramente ...
94

Um retorno por função / método.

iMacUwhAK
fonte
7
Eu ia colocar isso. Eu me amo algumas declarações de retorno antecipado.
Carson Myers
4
Absolutamente! As pessoas inventam algum fluxo de programa bastante interessante para evitar uma returndeclaração precoce . Estruturas de controle profundamente aninhadas ou verificações contínuas. Isso pode realmente inchar um método quando um if returnpoderia realmente simplificar esse problema.
snmcdonald
4
Se você precisar de vários retornos em uma função (além dos guardas), sua função provavelmente será muito longa.
EricSchaefer
18
Não faz sentido ter uma palavra-chave de retorno, a menos que ela tenha a intenção de aparecer em vários locais. Volte cedo, volte sempre. Isso servirá apenas para simplificar ainda mais seu código. Se as pessoas conseguem entender como as declarações de interrupção / continuação funcionam, por que lutam com o retorno?
Evan Plaice
7
Penso que esta é uma prática recomendada muito ultrapassada. Não acho que seja uma prática recomendada moderna.
Skilldrick
87

Não reinventar a roda é um dogma amplamente mal utilizado. Sua idéia é que, se existir uma solução adequada, use-a em vez de criar a sua própria; além do esforço de economia, a solução existente provavelmente é melhor implementada (sem erros, eficiente, testada) do que a que você apresentaria inicialmente. Por enquanto, tudo bem.

O problema é que raramente existe uma solução 100% adequada. Uma solução adequada a 80% pode existir e usá-la provavelmente é boa. Mas que tal 60% adequado? 40%? Onde você desenha a linha? Se você não desenhar a linha, poderá acabar incorporando uma biblioteca inchada ao seu projeto porque está usando 10% de seus recursos - apenas porque deseja evitar "reinventar a roda".

Se você reinventar a roda, obterá exatamente o que deseja. Você também aprenderá a fazer rodas. Aprender fazendo não deve ser subestimado. E, no final, uma roda personalizada pode muito bem ser melhor que a roda genérica pronta para uso.

Joonas Pulakka
fonte
3
Já tive isso acontecendo ao contrário. Criei meu próprio componente de grade ajax porque, na época, não havia nenhum que fizesse o que eu queria, mas mais tarde o substitui por grades Ext JS. Isso ajudou desde que eu assumi desde o início que a camada de exibição seria substituída.
Joeri Sebrechts 28/10/10
20
Acordado. Se ninguém reinventasse o volante, estaríamos todos dirigindo nossos carros com pneus de madeira.
Aprendiz do Dr. Wily
6
Eu sempre me sinto como o seu exemplo de 10% quando adiciono o Boost a um projeto C ++. Eu sempre preciso de menos de 10% dele diretamente, mas é claro que as funções que eu preciso importar são outros módulos que importam outros módulos que ... #
1111 Roman Starkov
3
+1: apenas nesta semana, reinventei a roda (por exemplo, substitua o plug-in jquery inchado e popular que usamos por algo que se adapta às nossas necessidades ainda modulares) e resultou em enormes ganhos de desempenho. Além disso, existem pessoas cujo trabalho é literalmente reinventar a roda: como a Michelin, por exemplo, eles fazem pesquisa e desenvolvimento para melhorar os pneus.
wildpeaks
2
@Dr. Wily, essas rodas não foram reinventadas, foram refatoradas!
78

"Teste de unidade tudo".

Ouvi dizer muitas vezes que todo código deveria ter testes de unidade, um ponto em que não concordo. Quando você tem um teste para um método, qualquer alteração na saída ou estrutura desse método deve ser feita duas vezes (uma vez no código, uma vez no teste).

Como tal, os testes de unidade devem ser, na minha opinião, proporcionais à estabilidade estrutural do código. Se eu estiver escrevendo um sistema em camadas de baixo para cima, minha camada de acesso a dados terá testes do wazoo; minha camada de lógica de negócios será muito bem testada, minha camada de apresentação terá alguns testes e minhas visualizações terão pouco ou nenhum teste.

Fishtoaster
fonte
7
Suspeito que "Unit Test Everything" tenha se tornado um clichê, como a citação de "otimização prematura". Eu geralmente concordo com suas proporções e já vi muitos exemplos de desenvolvedores passando por um esforço monumental para zombar de um objeto da camada de aplicativo, um esforço que poderia ser mais bem gasto no teste de aceitação.
Robert Harvey
36
Se uma alteração na estrutura de um método causar uma alteração em seus testes, você poderá estar testando errado. Os testes de unidade não devem verificar a implementação, apenas o resultado.
Adam Lear
7
@ Anna Lear: Eu acho que ele estava falando sobre fazer mudanças de design / estruturais (refatoração). Como o design não é maduro o suficiente, quando você encontra a melhor maneira de fazê-lo, pode ser necessário modificar muitos testes no caminho. Concordo que, quando você é um testador mais experiente, pode notar com mais facilidade onde o teste seria uma má ideia (por esse motivo e outros), mas se o design não for realmente maduro, você provavelmente ainda terá alguns testes no maneira.
N1ckp 27/10/10
13
Eu acho que é também por isso que a idéia "faça o teste primeiro" não funciona. Para fazer os testes primeiro, você precisa ter o design certo. Mas ter o design correto exige que você tente as coisas e veja como elas funcionam para que você possa aprimorá-las. Portanto, você não pode realmente fazer os testes antes de ter o design, e para obter o design correto é necessário codificar e ver como ele funciona. A menos que você tenha algum super-arquiteto, não vejo como essa ideia funcionará.
N1ckp 27/10/10
13
@ n1ck TDD não é realmente um exercício de teste, mas sim um exercício de design. A idéia é que você desenvolva seu design por meio de testes (pois isso expõe rapidamente uma API razoável para suas coisas) em vez de ajustá-los a um design existente (que pode ser ruim / insuficiente). Portanto, não, você não precisa ter o design certo para realizar os testes primeiro.
Adam Lear
57

Sempre programe para interfaces.

Às vezes, haverá apenas uma implementação. Se atrasarmos o processo de extração de uma interface até o momento em que percebermos a necessidade, frequentemente descobriremos que ela não é necessária.

Eric Wilson
fonte
4
Concordo, você programa para uma interface quando precisa de uma interface (ou seja, uma API estável para trabalhar).
Robert Harvey
45
Na minha leitura, esta regra não se refere a interfaces como construções de linguagem. Isso significa que você não deve fazer suposições sobre o funcionamento interno de uma classe ao chamar seus métodos e deve confiar apenas nos contratos da API.
Zsolt Török
2
Ok, aqui está uma pergunta interessante - eu sou principalmente um desenvolvedor .NET, portanto, para mim, minhas interfaces se parecem com IBusinessManager ou IServiceContract. Para mim, isso é extremamente fácil de navegar (e geralmente mantenho minhas interfaces em outro espaço de nome [ou mesmo em outro projeto]). Quando eu usei Java, realmente achei isso confuso (geralmente as implementações de interface que eu vi estão com o sufixo .impl - e as interfaces não têm delineamento). Então, isso poderia ser um problema de padrões de código? Obviamente, as interfaces em java fazem com que o código pareça confuso - elas parecem exatamente iguais às classes normais à primeira vista.
Watson
5
@ Watson: um custo é que toda vez que clico em F3 ('jump to Declaration') em uma chamada de método no Eclipse, pulo para a interface, e não para a implementação. Em seguida, tenho que controlar-T, seta para baixo, retornar para chegar à implementação. Ele também bloqueia algumas refatorações automáticas - você não pode incorporar um método em uma definição de interface, por exemplo.
Tom Anderson
4
@ Tom: Bem, senhor, eu ficaria feliz em envolvê-lo nessa guerra, Eclipse vs. Intellij - no entanto, eu tenho um excelente código moral que me impede de entrar em confrontos físicos com alguém que tem uma desvantagem óbvia. ESTRONDO. Não estou dizendo que o Eclipse é ruim, estou dizendo que se os poderes do Eixo o tivessem usado para construir ou projetar suas máquinas de guerra, a Segunda Guerra Mundial seria agora conhecida como a "confusão de dois dias". Sério, eu descobri que falta um pouco de polimento que recebo em IDEs prontos para uso (Intellij / VS + ReSharper). Eu me vi lutando contra isso em mais de uma ocasião - o que é demais.
Watson
46

Não use nada de código aberto (ou que não seja da Microsoft para desenvolvedores .NET)

Se a Microsoft não a desenvolveu - não a usamos aqui. Deseja usar o ORM-EF, deseja usar o IOC-Unity, deseja registrar o bloco do aplicativo de log corporativo. Existem tantas bibliotecas melhores - mas eu sempre fico presa em pedidos no menu do mundo do desenvolvimento. Juro que sempre que ouço as Melhores Práticas da Microsoft, penso em "Diretrizes Nutricionais do McDonald's". Claro, você provavelmente viverá se os seguir, mas também estará desnutrido e com sobrepeso.

  • Observe que essa pode não ser sua melhor prática, mas é comum, seguida em quase todos os lugares onde trabalhei.
Watson
fonte
13
Parece horrível ... = (Eu sou provavelmente muito sobre o outro lado, porém, eu evitar M $, tanto quanto possível.
Lizzan
Isso não deveria ser assim. Uma biblioteca deve ser escolhida por seu valor, não apenas considerando quem a criou. Por exemplo, eu amo a EF, mas tive uma experiência ruim com a Enterprise Library e encontrei melhores ferramentas para validação e registro, como FluentValidation, log4net e Elmah.
Matteo Mosca
4
Você não será demitido por comprar a IBM ^ wMicrosoft
Christopher Mahan
17
Há também a versão espelhada, ou seja, nunca use nada da Microsoft ou nunca use nada pelo qual você tenha que pagar.
Richard Gadsden
5
Tenho a sorte de trabalhar em uma organização em que esse não é um dogma amplamente aceito, mas nos lugares em que adotamos soluções comerciais, com certeza há muita dor. O problema surge quando alguma parte da solução comercial não funciona. Quando é de código aberto, você pode olhar para o código-fonte (a documentação final) e descobrir o que está acontecendo de errado. Com o código fechado, você precisa pagar pelo privilégio de acessar o conhecimento do suporte técnico que conhece ainda menos o produto que você faz. E essa é a única 'correção' disponível.
SingleNegationElimination
40

Orientação a objetos

Existe a suposição, apenas porque o código é "orientado a objetos", é magicamente bom. Então, as pessoas continuam pressionando a funcionalidade em classes e métodos, apenas para serem orientadas a objetos.

LennyProgrammers
fonte
7
Não consigo imaginar a construção de um sistema de software de tamanho significativo sem tirar proveito da organização que a Orientação a Objetos fornece.
Robert Harvey
18
Robert. O Unix não é orientado a objetos e certamente se qualifica como um sistema de software de tamanho significativo. Ele também parece ser bastante popular (acho que Mac OSX, iPhone, celulares com Android, etc)
Christopher Mahan
7
O que eu quis dizer é que acho que devemos usar a metodologia mais apropriada. Eu já vi pessoas usarem métodos e classes onde isso é complicado e não faz muito sentido, apenas porque "é orientado a objetos". Isso é culto à carga.
LennyProgrammers
8
Não há bala de prata. A programação funcional (Haskell) é bem-sucedida sem ser orientada a objetos. No final do dia, você tem várias ferramentas e é seu trabalho escolher a melhor variedade para a tarefa em questão.
Matthieu M.
9
O engraçado é que, além de usar classes, polimorfismo e afins, a maior parte do código orientado a objetos é de fato um procedimento.
Oliver Weiler
35

Todo o código deve ser comentado.

Não, não deveria ser. Algum tempo você tem um código óbvio, por exemplo, setters não devem ser comentados, até que façam algo especial. Além disso, por que devo comentar isso:

/** hey you, if didn't get, it's logger. */
private static Logger logger = LoggerFactory.getLogger(MyClass.class);
Vladimir Ivanov
fonte
13
Todo o código deve ser compreensível . Os comentários são uma ferramenta importante nisso, mas longe da única.
Trevel
Absurdamente, o código deve ser compreensível. Mas não há uma única razão para escrever um comentário que não adicione nada a, por exemplo, o nome do método. Se você escrever /** sets rank. */ void setRank(int rank) { this.rank = rank; }, assumo o comentário como estúpido. Por que está escrito?
Vladimir Ivanov
2
Documentação gerada. É para isso que /** */serve o formato, em vez do /* */comentário do formato. Ou, para o .NET seria///
#
10
Usando }//end if, }//end for, }//end whilesão o melhor exemplo de desperdício comentando que eu já encontrei. Eu já vi isso muitas vezes em que a chave de abertura não está mais do que 2 linhas acima. IMHO, se você precisar desses comentários, seu código precisará ser refatorado ... ou você precisará pagar US $ 20 e comprar um editor de IDE / Texto que destaque chaves correspondentes.
scunliffe
7
O código diz "como". Os comentários precisam dizer "por que".
32

Metodologias, particularmente scrum. Não consigo manter a cara séria quando ouço os adultos usarem a frase "Scrum Master". Fico tão cansado de ouvir desenvolvedores protestar que algum aspecto da Metodologia X não está funcionando para a empresa deles, apenas para ser informado pelo Guru So-and-So que a razão pela qual não está funcionando é que eles não são, de fato, verdadeiros praticantes da metodologia X. "Scrum mais difícil, você deve, meu aluno de Padawan!"

Existem pepitas de sabedoria nas metodologias ágeis - muitas delas -, mas elas são muitas vezes engolidas com tanto adubo que não posso combater meu reflexo de vômito. Veja esta parte da página scrum da Wikipedia :

Várias funções são definidas no Scrum. Todos os papéis se enquadram em dois grupos distintos - porcos e galinhas - com base na natureza de seu envolvimento no processo de desenvolvimento.

Realmente? Porcos e galinhas, você diz? Fascinante! Mal posso esperar para lançar este aqui para o meu chefe ...

evadeflow
fonte
Interessante. Eu concordo até um certo ponto. Porém, com essa última parte: chame-os como quiser, são mnemônicos, só isso.
Steven Evers
12
+1 ... você está certo, é difícil levar isso a sério. <grande voz estrondosa> * EU SOU O SCRUMMASTER * </voice> #
GrandmasterB
2
E as parábolas. Isso me lembra os sermões da igreja, ou os tipos de anedotas pelas quais os gurus de auto-ajuda (e comediantes) são famosos: "Pegue meu amigo Steve. Steve estava constantemente discutindo com sua esposa Sheryl. o ponto em que o casamento deles estava em perigo real. Então, um dia ... "Esses tipos de fios didáticos não me incomodam em outras esferas, mas eu odeio vê-los proliferar nas ciências da engenharia.
Evadeflow
2
E os Scrum Ninjas?
Berin Loritsch 12/01
1
Não concordo com a comparação "Porco e Frango" ... ela voa diretamente diante do Manifesto Ágil. Ou seja, "Colaboração do cliente sobre negociação de contrato". Os clientes são tão investidos (se não mais) no sucesso do projeto quanto a equipe do projeto. Chamar alguns papéis de porcos e outros papéis de galinhas cria uma mentalidade "nós contra eles" de que o IMHO é o maior obstáculo para projetos de sucesso.
Michael Brown
25

Mapeamento relacional de objetos ... http://en.wikipedia.org/wiki/Object-relational_mapping

Eu nunca quero ser abstraído dos meus dados, nem quero perder esse controle e otimização precisos. Minha experiência com esses sistemas tem sido extremamente ruim ... As consultas geradas por essas camadas de abstração são ainda piores do que as que vi fora do escoramento.

Fosco
fonte
19
Otimização prematura é a raiz de todo o mal. O código lento é, na vida real, apenas incrivelmente raramente um problema quando comparado ao código não sustentável. Use um ORM e, em seguida, recorte a abstração apenas onde for necessário.
Fishtoaster 26/10/10
28
Os ORM são uma ferramenta 80-20. Eles pretendem lidar com o CRUD de 80% que se torna tão cansativo para escrever todo esse código de encanamento sem fim depois de um tempo. Os outros 20% podem ser feitos de maneiras mais "convencionais", como usar procedimentos armazenados e escrever consultas SQL comuns.
Robert Harvey
18
@ Fishtoaster: Você não quer dizer: "Devemos esquecer pequenas eficiências, digamos cerca de 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".
Robert Harvey
5
@ Robert Harcey: Há uma razão pela qual não usei uma cotação direta. Eu acho que a maioria dos programadores se concentra demais na eficiência - é um problema que poucos deles realmente precisam resolver. É certo que existem certos domínios em que é mais importante que outros, mas a manutenção e a extensibilidade são um problema em todos os lugares. Outra citação modificada: "Faça o trabalho, mantenha-o, faça-o legível, faça-o extensível, faça-o testável e , em seguida , se você tiver tempo e for necessário, faça-o rapidamente".
Fishtoaster 26/10/10
12
@ Craig: Como você não reconheceu a ironia em sua declaração? A necessidade de um ano para aprender como obter um bom desempenho de um ORM é um excelente argumento contra ORMs, assim como a necessidade de "controlar" o SQL produzido e injetar procedimentos armazenados. Se você tem o conhecimento para isso, tem o conhecimento necessário para ignorar completamente o ORM.
Nicholas Knight
22

Escrever nomes de funções como se fossem frases em inglês:

Draw_Foo()
Write_Foo()
Create_Foo()

etc. Isso pode parecer ótimo, mas é uma dor quando você está aprendendo uma API. Quão mais fácil é procurar em um índice por "Tudo o que começa com Foo"?

Foo_Draw()
Foo_Write()
Foo_Create()

etc.

Colen
fonte
2
Provavelmente, é tão fácil quanto digitar Foo na lista de funções da TM.
Josh K
68
Parece que você realmente gostaria que fosse Foo.Draw(), Foo.Write()e Foo.Create(), para que você pudesse fazer Foo.methods.sortouFoo.methods.grep([what I seek]).sort
Inaimathi 26/10/10
7
Começando com 'Get' é outro exemplo.
JeffO 26/10/10
1
Eu venho do mundo objetivo-c e sinto muita falta de nomes de métodos detalhados e notação de infixo quando faço java (minha outra vida). Desde que a conclusão do código começou a funcionar, também não encontrei um problema adicional para a digitação.
2
@ Scott Whitlock: Não tão desatualizado para alguns desenvolvedores .NET, o iirc, o VS 2008 não fez isso. 2010, porém, e é fantástico.
Steven Evers
22

MVC - costumo achar que colocar muitos problemas de design da web na abordagem MVC é mais sobre tornar um framework (trilhos etc.) feliz do que sobre simplicidade ou estrutura. O MVC é o favorito dos "astronautas da arquitetura" que parecem valorizar andaimes excessivos em detrimento da simplicidade. ymmv.

OO baseado em classe - na minha opinião incentiva estruturas complexas de estado mutável. os únicos casos convincentes que encontrei para OO baseado em classe ao longo dos anos são os brega "forma-> retângulo-> quadrado" exemplos que formam o capítulo 1 de qualquer livro de OO

Brad Clawsie
fonte
4
Eu desenvolvi a Web no ASP.NET e no ASP.NET MVC e, embora o MVC pareça um suporte, eu prefiro o ASP.NET, por vários motivos: simplicidade, manutenção e controle extremamente bom sobre a marcação. Tudo tem seu lugar e, embora tudo pareça um pouco repetitivo, é uma alegria mantê-lo. É completamente personalizável; portanto, se você não gostar de um comportamento imediato, poderá alterá-lo.
Robert Harvey
1
No que diz respeito ao OO, existem boas e más maneiras de fazê-lo. A herança é superestimada e usada com mais moderação no mundo real do que a maioria dos livros você imagina; Atualmente, existe uma tendência a um estilo de desenvolvimento mais funcional e imutável, mesmo no mundo OO.
Robert Harvey
1
+1 por mencionar o MVC. Embora o conceito de MVC (separar a lógica da camada de dados, a lógica de apresentação e a lógica de segundo plano seja uma boa idéia), separá-los fisicamente em uma hierarquia de pastas complexa com uma mistura de arquivos contendo trechos de código é estúpido. Eu culpo todo esse fenômeno pelo falta de suporte ao namespace do PHP e desenvolvedores iniciantes que glorificam as técnicas de décadas como 'a coisa mais nova'. É simples, crie um espaço de nome para os acessadores do banco de dados, a GUI e a lógica de segundo plano (e sub-namespaces, quando necessário).
Evan Plaice
3
Quanto ao OO, você realmente não verá seus benefícios até que seu projeto cresça a um tamanho em que o gerenciamento da complexidade se torne importante. Siga o princípio de responsabilidade única sempre que possível e se seu código estiver acessível publicamente exposto (por exemplo, para uma DLL), oculte a implementação interna de classes / métodos / propriedades sempre que possível para tornar o código mais seguro e simplificar a API.
Evan Plaice
1
Pessoalmente, acho que o exemplo de forma-> retângulo-> quadrado é um dos argumentos mais elegantes contra oop. por exemplo, para Square(10).Draw()isso é suficiente Rectangle(10, 10).Draw(). então acho que isso significa que quadrado é uma subclasse de retângulo. Mas mySquare.setWidthHeight(5,10)isso não faz sentido (ou seja, falha no princípio da substituição de Liskov), um quadrado não pode ter altura e largura diferentes, embora um retângulo possa, de modo que implica que esse retângulo é uma subclasse de quadrado. Isso é conhecido em outros contextos como o "Círculo, problema da elipse"
SingleNegationElimination
22

YAGNI

( Você não vai precisar disso )

Essa abordagem me custou horas e horas em que eu tive que implementar recursos em uma base de código existente, onde um planejamento cuidadoso incluiria esses recursos antecipadamente.

As minhas idéias muitas vezes foram rejeitadas por causa do YAGNI, e na maioria das vezes alguém teve que pagar por essa decisão mais tarde.

(É claro que alguém poderia argumentar que uma base de código bem projetada também permitiria que recursos fossem adicionados posteriormente, mas a realidade é diferente)

Sean Patrick Floyd
fonte
15
Eu concordo com YAGNI, mas vejo o que você está recebendo. O objetivo do YAGNI é lidar com pessoas que desejam planejar tudo de antemão, nos mínimos detalhes. Nove em cada dez vezes, porém, é usado como uma desculpa para sub-codificar ou ignorar completamente o planejamento.
Jason Baker
12
P.Floyd, @ Jason Baker: +1 Absolutamente certo. O velho ditado se aplica aqui "meses no laboratório podem economizar horas na biblioteca"
Steven Evers
Uma especificação geralmente deixa (e principalmente deveria) deixar a maior parte da implicação e parte da interface aberta. tudo que não está diretamente nas especificações, mas é necessário para implementá-las, seja uma decisão de implementação, uma interface visível ao usuário ou qualquer outra coisa, também é um requisito indireto da especificação. Se um recurso não estiver na especificação e não estiver implícito na especificação, não será necessário. Como isso pode ser confuso?
SingleNegationElimination
1
@TokenMacGuy o aspecto crucial é o implícito na parte de especificação . É aí que as opiniões diferem bastante.
Sean Patrick Floyd
20

Para SQL

  1. Não use gatilhos
  2. Sempre ocultar tabelas atrás das visualizações

Em ordem:

  1. Eles são um recurso que tem seu lugar. Você possui vários caminhos de atualização para uma tabela ou requer auditoria 100%?

  2. Só por que? Eu faria se estivesse refatorando para manter um contrato, mas não quando li que as pessoas mudam a visualização para corresponder a qualquer alteração na tabela

Editar:

Número 3: Evitando * com EXISTS. Tente 1/0. Funciona. A lista de colunas não é avaliada conforme o padrão SQL. Page 191

gbn
fonte
3
# 2 é uma prática recomendada?
Hogan
1
@ Hogan: Uma visão que simplesmente espelha uma tabela base não adiciona segurança ao usar a tabela base diretamente. Se você ingressar em uma tabela securityuser, ou mascarar algumas colunas, será justo o suficiente. Mas SELECIONE todas as colunas da tabela ou exibição: não há diferença. Pessoalmente, eu uso procs armazenados de qualquer maneira.
gbn 27/10/10
3
@Hogan: Eu sei algo sobre o SQL Server :-) stackoverflow.com/users/27535/gbn O que quero dizer é GRANT SELECT na tabela não é diferente de GRANT SELECT ON VIEW se a exibição for SELECT * FROM TABELA
gbn
1
@gbn: eu concordo. Não há diferença lá. Eu acho que podemos estar dizendo a mesma coisa. Acho que meu comentário original ("# 2 é uma prática recomendada?") Se baseou mais na minha experiência pessoal de que visualizações (como gatilhos) são mais frequentemente usadas erroneamente do que usadas corretamente. Assim, essa prática recomendada levaria apenas a abuso e não aprimoramento. Se for considerada uma prática recomendada, você está 100% certo, é uma má.
Hogan
20

Padrões de design principalmente. Eles são muito utilizados e pouco utilizados.

Geek
fonte
13
+1 Ainda não vejo como os Design Patterns são soluções bonitas ou elegantes. São soluções alternativas para deficiências de linguagem, nada mais.
Oliver Weiler 30/11
2
Apenas veja isso como um esforço para erradicar o cheiro da linguagem usando a própria linguagem.
Filip Dupanović
15

O princípio da responsabilidade única

("toda classe deve ter apenas uma única responsabilidade; em outras palavras, toda classe deve ter um e apenas um motivo para mudar")

Discordo. Eu acho que um método deve ter apenas um motivo para mudar, e todos os métodos em uma classe devem ter um relacionamento lógico entre si , mas a própria classe pode realmente fazer várias coisas (relacionadas).

Na minha experiência, esse princípio muitas vezes é aplicado com zelo demais, e você acaba com muitas pequenas classes de método único. As duas lojas ágeis em que trabalhei fizeram isso.

Imagine se os criadores da API .Net tivessem esse tipo de mentalidade: em vez de List.Sort (), List.Reverse (), List.Find () etc., teríamos as classes ListSorter, ListReverser e ListSearcher!

Em vez de argumentar mais contra o SRP (o que em si não é terrível em teoria) , vou compartilhar algumas de minhas experiências anedóticas há muito tempo:


Em um local em que trabalhei, escrevi um solucionador de fluxo máximo muito simples que consistia em cinco classes: um nó, um gráfico, um criador de gráficos, um solucionador de gráficos e uma classe para usar o criador / solucionador de gráficos para resolver um problema. problema do mundo real. Nenhuma era particularmente complexa ou longa (o solucionador era de longe o mais longo, com ~ 150 linhas). No entanto, foi decidido que as classes tinham muitas "responsabilidades", então meus colegas de trabalho começaram a refatorar o código. Quando terminaram, minhas 5 classes foram expandidas para 25, cujas linhas de código totais eram mais do que o triplo do que eram originalmente. O fluxo do código não era mais óbvio, nem era o objetivo dos novos testes de unidade; Agora eu tinha dificuldade em descobrir o que meu próprio código fazia.


No mesmo local, quase todas as classes tinham apenas um único método (sua única "responsabilidade"). Seguir o fluxo dentro do programa era quase impossível, e a maioria dos testes de unidade consistia em testar se essa classe chamava código de outra classe , cujo objetivo era igualmente um mistério para mim. Havia literalmente centenas de classes onde deveria haver (IMO) apenas dezenas. Cada classe fez apenas uma "coisa" , mas mesmo com convenções de nomenclatura como "AdminUserCreationAttemptorFactory" , era difícil distinguir o relacionamento entre as classes.


Em outro lugar (que também tinha a mentalidade de que as classes deveriam ter apenas um método ), estávamos tentando otimizar um método que ocupava 95% do tempo durante uma determinada operação. Depois de (um tanto estupidamente) otimizá-lo um pouco, voltei minha atenção para o motivo de ser chamado de bajilhão de vezes. Ele estava sendo chamado em um loop em uma classe ... cujo método estava sendo chamado em um loop em outra classe .. que também estava sendo chamado em um loop ..

Ao todo, havia cinco níveis de loops espalhados por 13 classes (sério). O que qualquer classe realmente estava fazendo era impossível de determinar apenas olhando para ela - você tinha que esboçar um gráfico mental de quais métodos ela chamava e de quais métodos esses métodos chamavam, e assim por diante. Se tudo tivesse sido agrupado em um método, teria apenas cerca de 70 linhas com o nosso método-problema aninhado dentro de cinco níveis de loops imediatamente óbvios.

Meu pedido para refatorar essas 13 classes em uma classe foi negado.

BlueRaja - Danny Pflughoeft
fonte
6
Parece que alguém recebeu "febre do padrão" ou, neste caso, "febre do princípio" nesse trabalho. A classe da lista não viola o SRP. Todas as suas funções servem a um propósito, manipulando uma coleção de objetos. Ter apenas uma função em uma classe parece um exagero para mim. O princípio por trás do SRP é que uma unidade de código (seja método, classe ou biblioteca) deve ter uma única responsabilidade que pode ser declarada de maneira sucinta.
Michael Brown
3
Comecei a ver esse tipo de loucura de pessoas que acham impossível escrever código funcional puro e simples. Educar demais para que todos os problemas do mundo possam ser resolvidos a partir de um livro de padrões. Não basta pensar em pragmatismo. Como você, já vi algum código OO baseado em classe que é tão horrível que é totalmente impossível segui-lo. E é enorme e inchado.
quickly_now
3
Segundo comentário aqui. Muitos "princípios" são aplicados em excesso. Há muitas coisas que são boas idéias, onde fazer exatamente o oposto às vezes é apropriado. BOM programadores sabem quando a quebra das regras. Como as regras não são "regras", são declarações de "boas práticas na maioria das vezes, exceto quando é realmente uma idéia idiota".
quickly_now
"Imagine se os criadores da API .Net tivessem esse tipo de mentalidade: em vez de List.Sort (), List.Reverse (), List.Find () etc., teríamos as classes ListSorter, ListReverser e ListSearcher ! ". Isso é exatamente o que é feito em C ++, e é maravilhoso . Os algoritmos são separados das estruturas de dados; portanto, se eu escrever meu próprio contêiner, todos os algoritmos que funcionam com a biblioteca padrão simplesmente funcionarão com meu novo contêiner. Deve ser horrível no terreno .Net, escrevendo uma nova função de classificação para cada novo contêiner que você deseja classificar.
Mankarse 26/10/11
14

Agora que você mencionou o Código Limpo, embora ele contenha algumas boas idéias, acho que sua obsessão em refatorar todos os métodos em submétodos e aqueles em subsubmetodos etc. foi levada longe demais. Em vez de alguns métodos de dez linhas, você deve preferir vinte one-liners (supostamente bem nomeadas). Obviamente alguém pensa que é limpo, mas para mim parece muito pior do que a versão original.

Além disso, substituindo coisas simples e elementares, como

0 == memberArray.length

dentro de uma classe com uma chamada para o próprio método da classe, como

isEmpty()

é um questionável "melhoria" IMHO. Adição: A diferença é que a primeira verificação faz exatamente o que diz: verifica se o comprimento da matriz é 0. Ok, também isEmpty()pode verificar a duração da matriz. Mas também pode ser implementado assim:

return null != memberArray ? 0 == memberArray.length : true;

Ou seja, inclui uma verificação nula implícita! Esse pode ser um bom comportamento para um método público - se a matriz for nula, então algo certamente está vazio - mas quando estamos falando de informações internas da classe, isso não é tão bom. Embora o encapsulamento para o exterior seja obrigatório, os internos da classe devem saber exatamente o que está acontecendo dentro da classe. Você não pode encapsular a classe por si mesma . Explícito é melhor que implícito.


Isso não quer dizer que quebrar métodos longos ou envolver comparações lógicas não seja bom; é claro que sim, mas até que ponto fazê-lo - onde está o ponto ideal - é obviamente uma questão de gosto. Quebrar um método longo resulta em mais métodos, e isso não é de graça. Você precisa pular o código-fonte para ver o que realmente está acontecendo, quando você pode ver rapidamente se todas essas coisas estavam em um único método.

Eu diria até que, em alguns casos, um método de 1 linha é muito curto para merecer ser um método.

Joonas Pulakka
fonte
6
Eu raramente vejo isso como um problema. Principalmente porque geralmente vejo muito em um único método, não muito pouco. No entanto, de acordo com alguns estudos, a complexidade muito baixa nos métodos também apresenta uma taxa de erros um pouco maior que a complexidade moderadamente baixa. enerjy.com/blog/?p=198
MIA
Sim, esse é definitivamente um problema apenas no Código Limpo. Na vida real, os métodos tendem a ser muito longos, como você disse. Mas é interessante ver essa curva! De fato, as coisas devem ser feitas o mais simples possível, mas não mais simples.
Joonas Pulakka 27/10/10
1
Acho o seu segundo exemplo eminentemente mais legível, e essa forma (ou algo semelhante, como uma propriedade Length na própria classe) é obrigatória se você a tornar pública.
Robert Harvey
@ Robert Harvey: O segundo exemplo é um bom método público, mas chamá-lo de dentro da própria classe é questionável, porque você não sabe exatamente o que faz antes de ver como é implementado. Poderia verificar nulo, por exemplo. Veja minha adição acima.
Joonas Pulakka 28/10/10
@ Joonas: Justo.
Robert Harvey
13

"Seja liberal com comentários"

Os comentários são definitivamente uma coisa boa, mas muitos são tão ruins se não piores do que suficientes. Por quê? Bem, as pessoas tendem a ignorar os comentários se veem muitos desnecessários. Não estou dizendo que você pode ter um código perfeitamente auto-documentado, mas é preferível codificar que precisa de comentários para explicação.

Jason Baker
fonte
1
código de auto-documentação é definitivamente bom. Embora eu goste de ter comentários ao lado de algo como cálculos simples (para expressar qual é o tipo de retorno ou o valor retornado). No entanto, se seus comentários precisarem de mais palavras que o próprio código, provavelmente é hora de reescrevê-lo.
sova
6
Eu tenho que concordar com a maneira que a sova colocou esta. Código limpo é preferível a comentários.
riwalk
4
Você ainda precisa do porquê!
Eu prefiro ter comentários explicando o porquê. Isso significa que tenho que PENSAR menos na engenharia reversa do código pretendido quando chego a olhar para ele.
precisa saber é o seguinte
12

GoTo considerado prejudicial

Se você estiver implementando uma máquina de estado, uma instrução GOTO pode fazer mais sentido (legibilidade e código eficiente) do que uma abordagem de "programação estruturada". Isso realmente preocupou alguns colegas de trabalho quando o primeiro código que escrevi em um novo trabalho incluía não apenas uma, mas várias declarações goto. Felizmente, eles eram inteligentes o suficiente para perceber que era realmente a melhor solução nesse caso específico.

Qualquer "prática recomendada" que não permita exceções sensatas e documentadas a suas regras é simplesmente assustadora.

MZB
fonte
16
Vou continuar nove anos programando sem uma única instrução goto (incluindo várias máquinas de estado, como você mencionou). Expanda sua mente para novas idéias.
riwalk
3
@Mathieu M. - concordou - misturar o GOTO com instruções de controle estruturadas não é sensato. (Isso foi pura C e não foi um problema.
MZB
1
@ Stargazer2 - com um FSM simples, depende se colocar o estado em uma variável e usá-lo como um índice para chamar um procedimento (não é o mesmo que um GOTO computado?) Fornece código mais claro / rápido do que usar o contador de programa como o estado FSM. Não estou defendendo isso como a melhor solução na maioria das circunstâncias, apenas a melhor solução em algumas circunstâncias. Expanda sua mente para abordagens alternativas.
MZB
5
@MZB, você não concorda que uma chamada de função também é apenas um GOTO computado? O mesmo vale para / while / if / else / switch construções, entre outros. Os designers de idiomas abstraem as alterações diretas no contador do programa por um motivo. Não use goto.
riwalk
3
A implementação direta de uma máquina de estado é provavelmente um antipadrão. Existem muitas maneiras de ter uma máquina de estados sem expressar os estados e transições literalmente. por exemplo,import re
SingleNegationElimination
12

Os sacrifícios que fazemos para tornar o código testável

Eu pulo muitos obstáculos para tornar meu código testável, mas não finjo que não faria se tivesse a opção. No entanto, muitas vezes ouço pessoas insistindo na ideia de que essas são "melhores práticas". Essas práticas incluem (escritas no idioma .Net, mas também se aplicam a outros idiomas) :

  • Criando uma interface para cada classe. Isso dobra o número de classes (arquivos) para lidar e duplica o código. Sim, a programação da interface é boa, mas é para isso que servem os especificadores público / privado.
  • Toda classe que não é instanciada na inicialização precisa de uma fábrica. Claramente, new MyClass()é muito mais simples do que escrever uma fábrica, mas agora o método que a cria não pode ser testado isoladamente. Se não fosse por esse fato, eu faria apenas 1/20 do número de classes de fábrica que faço agora.
  • Torne pública todas as classes, o que anula o propósito de ter especificadores de acesso nas classes. No entanto, classes não públicas não podem ser acessadas (e, portanto, testadas) de outros projetos; portanto, a única outra opção é mover todo o código de teste para o mesmo projeto (e, portanto, liberá-lo com o produto final).
  • Injeção de dependência. Claramente, ter que dar a todas as outras classes que eu use um campo e um parâmetro construtor é muito mais trabalhoso do que apenas criá-las quando preciso; mas não posso mais testar esta classe isoladamente.
  • O princípio da responsabilidade única, que me causou tantas dores de cabeça, mudei para a sua própria resposta .

Então, o que podemos fazer para corrigir isso? Precisamos de uma mudança drástica na arquitetura da linguagem:

  • Precisamos da capacidade de zombar de classes
  • Precisamos da capacidade de testar métodos particulares de classes internas, de outro projeto (isso pode parecer uma vulnerabilidade de segurança, mas não vejo problema se o testado for forçado a nomear suas classes de testadores) .
  • A injeção de dependência (ou localização do serviço), bem como algo equivalente ao nosso padrão de fábrica existente, teria que ser uma parte essencial do idioma.

Em resumo, precisamos de uma linguagem projetada desde o início com a testabilidade em mente .

BlueRaja - Danny Pflughoeft
fonte
Acho que você nunca ouviu falar do TypeMock ? Permite zombar de classes, particulares, estática (fábrica), qualquer coisa.
Allon Guralnek
@ Allon: eu tenho, mas está longe de ser gratuito , o que não é uma opção para a maioria das pessoas.
BlueRaja - Danny Pflughoeft 20/01
Se você tiver que escrever muitas aulas de fábrica, estará fazendo algo errado. As bibliotecas inteligentes de DI (por exemplo, Autofac for C #) podem utilizar Func <T>, Lazy <T>, Delegates etc. para fábricas, sem escrever você mesmo qualquer documento.
gix
10

Separando aplicativos em camadas; Camada de dados, camada de negócios, camada de interface do usuário

A principal razão pela qual não gosto disso é que a maioria dos lugares que seguem esse método usa estruturas muito frágeis para fazê-lo. O IE UI Layer é codificado manualmente para lidar com objetos da camada de negócios, os objetos da camada de negócios são codificados manualmente para lidar com regras e banco de dados de negócios, o banco de dados é SQL e já é bastante quebradiço e gerenciado pelo grupo "DBA" que não gosta de mudanças.

Por que isso é ruim? A solicitação de aprimoramento mais comum é provável "Preciso de um campo na tela X que tenha Y". Bang! Você tem apenas um novo recurso que afeta todas as camadas e, se você separar camadas com diferentes programadores, tornou-se um grande problema envolvendo várias pessoas e grupos, para uma mudança muito simples.

Além disso, não sei quantas vezes estive em argumentos que são mais ou menos assim. "O campo de nome é limitado a um comprimento máximo de 30, é um problema da camada da interface do usuário, da camada de negócios ou da camada de dados?" E há cem argumentos, e não há resposta certa. A resposta é a mesma, ela afeta todas as camadas, você não quer mudar a interface do usuário, precisa passar por todas as camadas e falhar no banco de dados, apenas para que o usuário descubra que sua entrada é muito longa. Se você mudar, isso afeta todas as camadas, etc.

As "camadas" tendem a vazar também; Se qualquer camada for fisicamente separada pelos limites do processo / máquina (UI da web do IE e lógica de back-end comercial), as regras serão duplicadas para que tudo funcione razoavelmente bem. Ou seja, alguma lógica de negócios acaba na interface do usuário, mesmo que seja uma "regra de negócios", porque o usuário precisa que a interface do usuário seja responsiva.

Se a estrutura usada ou a arquitetura usada for resiliente a pequenas alterações e vazamentos, ou seja, com base em metadados e ajustada dinamicamente em todas as camadas, pode ser menos dolorosa. Mas na maioria das estruturas, isso é uma dor real, exigindo alterações na interface do usuário, alterações na camada de negócios e alterações no banco de dados, a cada pequena alteração, causando mais trabalho e menos ajuda do que a técnica deveria produzir.

Provavelmente vou ser criticado por isso, mas aí está :)

Jay
fonte
+1, parece o meu último local de trabalho nos mínimos detalhes! Eu respeito, por princípio, aplicativos em camadas, no entanto, muitas pessoas o tratam como uma bala de prata quando não faz sentido. A maioria dos softwares de negócios possui uma quantidade incrivelmente baixa de lógica de negócios e o que ele possui é relativamente simples. Isso pode tornar a lógica de negócios em camadas um pesadelo do código padrão. Muitas vezes, as linhas podem ficar borradas entre o acesso a dados e a lógica de negócios, porque a consulta é a lógica de negócios.
Maple_shaft
... além disso, a maioria das lojas falha absolutamente ao reconhecer a lógica da interface do usuário ou a lógica de apresentação. Como eles não entendem o quão pouca lógica de negócios existe em um aplicativo CRUD típico, eles sentem que devem estar fazendo algo errado quando a maioria de sua lógica reside na camada de apresentação como lógica de apresentação. Ele é falsamente identificado como lógica de negócios e as pessoas o enviam para o servidor para mais uma chamada. Um Thin Client pode e deve ter lógica de apresentação, por exemplo. (Oculte textField2 se a opção1 estiver selecionada em dropDown3).
Maple_shaft
7

Histórias de usuários / casos de uso / personas

 

Entendo a necessidade disso quando você está programando para um setor com o qual não está familiarizado, mas acho que, quando implementados com força total, tornam-se muito corporativos e perdem tempo.

riwalk
fonte
7

Limites de 80 caracteres / linha são burros

Entendo que alguns compromissos precisam ser feitos para corresponder ao ritmo do corredor mais lento do lado da GUI (limitações de resolução de tela etc.), mas, por que essa regra se aplica à formatação de código?

Veja ... Havia uma pequena invenção chamada barra de rolagem horizontal que foi criada para gerenciar o espaço da tela virtual fora do limite de pixels mais à direita. Por que os desenvolvedores, que conseguiram criar excelentes ferramentas de aprimoramento da produtividade, como destaque de sintaxe e preenchimento automático, não o usam?

Certamente, existem editores de CLI usados ​​religiosamente pelos dinossauros * nix que seguem as antigas limitações cansadas de seus terminais VT220, mas por que o restante de nós é mantido no mesmo padrão?

Eu digo, estrague o limite de 80 caracteres. Se os dinossauros são épicos o suficiente para invadir o emacs / vim o dia todo, por que não é possível criar uma extensão que quebra linhas automaticamente ou fornece recursos de rolagem horizontal para seus IDEs de CLI?

Os monitores de pixel de 1920x1080 acabarão se tornando a norma e os desenvolvedores em todo o mundo ainda vivem sob as mesmas limitações, sem importar o porquê, exceto isso, é o que eles disseram aos seus anciãos quando estavam começando a programar.

Os limites de 80 caracteres não são uma prática recomendada, mas uma prática de nicho para uma minoria de programadores e devem ser tratados como tal.

Editar:

É compreensível que muitos desenvolvedores não gostem da barra de rolagem horizontal porque requer um gesto do mouse, então ... Por que não aumentar o limite da largura da coluna para um número maior (que 80) para aqueles que usam telas modernas.

Quando os monitores de computador 800x600 se tornaram a norma para a maioria dos usuários, os desenvolvedores da Web aumentaram as larguras de seus sites para acomodar a maioria ... Por que os desenvolvedores não podem fazer o mesmo.

Evan Solha
fonte
1
@Orbling A boa lógica GWB com o ___ é um ângulo maligno. Então você detesta o hScroll, tem algum motivo válido para que a largura da coluna seja limitada a 80 caracteres? Por que não 160 ou 256? Acho que todos podemos supor que a maioria dos desenvolvedores aposentou seus terminais VT220 e os substituiu por puTTY, para que eles possam estender a largura programaticamente de qualquer maneira.
Evan Solha
4
Eu prefiro que atenhamos ao limite de 80 caracteres. Assim que você me der mais espaço horizontal, tentarei abrir documentos adicionais lado a lado com o restante. Eu odiaria ter que rolar de quatro maneiras. Além disso, notei muitas vezes que sou forçado a escrever um código mais legível com o limite de 80 caracteres.
Filip Dupanović
2
como você o imprimiria?
5
Desculpe - tenho que discordar desta. Eu realmente odeio longas filas - ele requer mais movimento dos olhos, requer gestos do mouse para rolar, é mais difícil ver coisas sutilmente obscuras no final de uma linha. Em cerca de 99% dos casos, existem maneiras limpas de fazer as coisas correrem por várias linhas (mais curtas), que são mais claras e fáceis de ler. 80 caracteres podem ser arbitrários e "porque era assim em dias de cartões perfurados", mas ainda é uma estrutura razoável para trabalhar dentro - na maioria das vezes - pelas razões acima.
precisa saber é o seguinte
3
Recuar por 2 espaços. E use um editor com um rastreador de indentação automático. Eu faço dessa maneira há anos, não é grande coisa. (Emacs com os modos corretos ajuda aqui.) #:
quick_now
5

Medida, Medida, Medida

Tão bem, meça a distância, mas para isolar os erros de desempenho, a medição funciona tanto quanto a eliminação sucessiva. Aqui está o método que eu uso.

Eu tenho tentado rastrear a fonte da "medida" medida "sabedoria". Alguém com uma caixa de sabão alta o suficiente disse isso e agora ela viaja.

Mike Dunlavey
fonte
5

Meu professor exige que eu inicie todos os meus identificadores (sem incluir constantes) com letras minúsculas, por exemplo myVariable.

Eu sei que parece uma coisa pequena, mas muitas linguagens de programação exigem variáveis ​​para começar com letras maiúsculas. Eu valorizo ​​a consistência, por isso é um hábito meu começar tudo com letras maiúsculas.

Maxpm
fonte
9
Eu tinha um professor que exigia o camelCase porque ele insistia que era isso que as pessoas usam no mundo real ... Ao mesmo tempo, eu estava programando em dois grupos diferentes no meu trabalho - os dois grupos insistiam em notas menores. O que importa é o que seu grupo usa. Ele poderia ter se definido como o programador principal e tudo ficaria bem em meu livro - seguimos suas convenções - mas ele estava sempre dando sua opinião como "a maneira como as coisas são feitas no mundo real" como se não houvesse outro maneira.
Xnine
@ xnine Ainda não tenho representante suficiente neste site para avaliar seu comentário, então responderei com este comentário de aprovação.
Maxpm 30/11/2010
5
O caso de camelo (primeira letra minúscula) é uma convenção bastante comum, bem como o caso de Pascal (primeira letra de cada palavra em maiúscula). Na maioria dos idiomas, o camelCase é usado em variáveis ​​privadas / internas, onde o PascalCase é usado em classes, métodos, propriedades, espaços para nome e variáveis ​​públicas. Não é uma prática ruim se acostumar apenas a estar pronto para projetos que podem usar um esquema de nomeação diferente.
Evan Plaice
2
Apenas um FYI. Alguns idiomas inferem significado se a primeira letra de uma variável é maiúscula ou não. Em um desses idiomas, se a primeira letra for maiúscula, a variável será tratada como constante - qualquer tentativa de alterá-la causará um erro.
Berin Loritsch 12/01
1
No Go , métodos públicos e membros das classes começam com uma letra maiúscula; particulares com letra minúscula.
Jonathan Leffler
5

Use Singletons

Quando você deve ter apenas uma instância de alguma coisa. Não posso discordar mais. Nunca use um singleton e apenas aloque-o uma vez e passe o ponteiro / objeto / referência conforme necessário. Não há absolutamente nenhuma razão para não fazer isso.

user2528
fonte
2
Isso é um monte de negativos que me deixaram bastante confuso quanto à sua posição real em singletons.
Paul Butcher
1
@ Paul Butcher: Eu odeio singletons e nunca deve ser usado
1
@rwong: Pessoalmente, acho que nenhum motivo é legítimo. Basta escrever como uma classe normal. Realmente, não há razão para usar um singleton que não seja a preguiça e promover maus hábitos ou design.
6
Quem disse que usar Singeltons é uma prática recomendada?
Phil Mander
2
Os singletons têm seu lugar, especialmente nos casos em que uma estrutura operacional é alocada e preenchida na inicialização, e basicamente se torna somente leitura durante todo o tempo de execução do programa. Nesse caso, ele se torna um cache do outro lado de um ponteiro.
Tim Post
5

Usando int não assinado como iterador

Quando eles aprenderão que usar o int assinado é muito mais seguro e menos propenso a erros. Por que é tão importante que o índice de matriz possa ser apenas um número positivo, que todos tenham prazer em ignorar o fato de que 4 - 5 é 4294967295?

AareP
fonte
Ok, agora estou curioso, por que você diz isso? Estou me sentindo um pouco idiota - você pode fornecer alguns exemplos de código para fazer backup de suas declarações?
Paul Nathan
4
@ Paul Nathan: no que diz respeito ao buggy, aqui está um exemplo: for (unsigned int i = 0; i <10; i ++) {int crash_here = my_array [max (i-1,0)];}
AareP
@AareP: Para ter certeza - presumo que você esteja fazendo referência ao fato de que, quando um int não assinado 0é diminuído por 1, você realmente acaba com o valor positivo máximo que um int não assinado pode armazenar?
quer
1
@ Adam Paynter: sim. Isso pode parecer normal para programadores de c ++, mas vamos ser sinceros, "unsigned int" é uma "implementação" ruim de números somente positivos.
AareP
Não é uma boa ideia em pequenas máquinas incorporadas - entradas frequentemente não assinadas geram código menor e mais rápido. Depende do compilador e processador.
precisa saber é o seguinte
4

Os métodos não devem ter mais que uma única tela

Concordo totalmente com o princípio da responsabilidade única, mas por que as pessoas o percebem como "uma função / método não pode ter mais do que uma única responsabilidade no mais alto nível de granularidade lógica"?

A ideia é simples. Uma função / método deve realizar uma tarefa. Se parte dessa função / método puder ser usada em outro lugar, corte-a em sua própria função / método. Se puder ser usado em outro lugar do projeto, mova-o para sua própria classe ou classe de utilidade e torne-o acessível internamente.

Ter uma classe que contém 27 métodos auxiliares que são chamados apenas uma vez no código é idiota, um desperdício de espaço, um aumento desnecessário na complexidade e um grande tempo gasto. Parece mais uma boa regra para pessoas que querem parecer ocupadas refatorando código, mas não produzem muito.

Aqui está a minha regra ...

Escreva funções / métodos para realizar algo

Se você estiver prestes a copiar / colar algum código, pergunte-se se seria melhor criar uma função / método para esse código. Se uma função / método é chamada apenas uma vez em outra função / método, existe realmente um ponto em tê-la em primeiro lugar (será chamada com mais frequência no futuro). É valioso adicionar mais saltos dentro / fora das funções / métodos durante a depuração (ou seja, o salto adicionado torna a depuração mais fácil ou mais difícil)?

Concordo plenamente que funções / métodos maiores que 200 linhas precisam ser examinadas, mas algumas funções realizam apenas uma tarefa em tantas linhas e não contêm partes úteis que possam ser abstraídas / usadas no restante do projeto.

Eu olho para ele da perspectiva de um desenvolvedor de API ... Se um novo usuário examinasse o diagrama de classes do seu código, quantas partes desse diagrama fariam sentido no conjunto maior do projeto e quantas existiriam apenas como auxiliares de outras partes internas do projeto.

Se eu escolher entre dois programadores: o primeiro tem tendência a escrever funções / métodos que tentam fazer demais; o segundo divide cada parte de cada função / método no mais alto nível de granularidade; Eu escolheria as primeiras mãos para baixo. O primeiro realizaria mais (ou seja, escreveria mais detalhes do aplicativo), seu código seria mais fácil de depurar (devido a menos saltos dentro / fora de funções / métodos durante a depuração), e ele perderia menos tempo fazendo um trabalho ocupado, aperfeiçoando como o código parece vs aperfeiçoar como o código funciona.

Limite abstrações desnecessárias e não polua o preenchimento automático.

Evan Plaice
fonte
Este. Uma vez refatorei algumas funções longas em várias, apenas para perceber que quase todas elas precisavam de quase todos os parâmetros do código original. A manipulação de parâmetros foi tão difícil que foi mais fácil voltar ao código antigo.
L0b0
3
Acho que um contra-argumento é que refatorar partes de um método grande em chamadas separadas pode facilitar a leitura do método maior. Mesmo se o método for chamado apenas uma vez.
precisa saber é o seguinte
1
@Jeremy Como? Como abstrair uma seção do código e colocá-la em seu próprio método a torna mais legível do que apenas colocar um comentário de uma linha no topo desse pedaço de código que descreve o que ele faz? Supondo que o bloco de código seja usado apenas uma vez nessa seção do código. É realmente que difícil para a maioria dos programadores para decompor as peças de funcionamento do código, enquanto eles lê-lo e / ou colocar um pouco de uma linha comenta para lembrá-los que ele faz se eles não podem?
Evan Solha
4
@Evan: Colocar trechos de código em funções efetivamente lhes dá um nome , e espero explicar bem o que esse trecho de código faz. Agora, onde quer que esse pedaço de código seja chamado, você pode ver o nome explicando o que o código faz , em vez de precisar analisar e entender o próprio algoritmo. Se bem feito, isso pode facilitar muito a leitura e o entendimento do código.
sbi 19/01
1
+1 e eu daria mais se pudesse. Não há nada de errado com um pedaço de código C que é de 1000 linhas em uma única função (por exemplo, um analisador com uma chave massiva ()), desde que a intenção seja clara e simples. Rebentar todos os pedacinhos e chamá-los apenas torna a coisa mais difícil de entender. Claro que também há limites para isso ... julgamento sensato é tudo.
precisa saber é o seguinte