Diretriz de codificação: Os métodos não devem conter mais de 7 declarações?

78

Eu estava olhando as Diretrizes de codificação da AvSol para C # e concordo com quase tudo, mas estou realmente curioso para ver o que os outros pensam de uma regra específica.

AV1500

Os métodos não devem exceder 7 instruções Um método que requer mais de 7 instruções está executando demais ou com muitas responsabilidades. Também requer que a mente humana analise as declarações exatas para entender o que o código está fazendo. Divida-o em vários métodos pequenos e focados, com nomes autoexplicativos.

A maioria de vocês segue esta regra? Mesmo que haja pouco a ser salvo na criação de um novo método (seu código ainda está SECO ), além de aumentar muito a legibilidade? E seu número ainda é tão baixo quanto 7? Eu tenderia mais para 10.

Não estou dizendo que viole essa regra em todo o lugar - pelo contrário, meus métodos são 95% pequenos e focados, mas dizer que você nunca deve violar essa regra realmente me deixou impressionado.

Eu realmente só quero saber o que todos pensam de NUNCA violar essa regra (é um '1' no padrão de codificação - o que significa NUNCA fazer isso). Mas acho que você teria problemas para encontrar uma base de código que não funciona.

brian
fonte
48
Eles contam casedeclarações em um chamuscado switchtambém? De qualquer forma, não passa de um requisito idiota e inútil. Quem o escreveu não sabe nada sobre programação.
SK-logic,
86
A única regra que deve ser um '1' no padrão de codificação deve ser a regra "você seguirá todas as diretrizes de codificação com um grão de sal".
Mike Nakis
6
O SK-logic 1027 também não é ruim - deve ser divertido escrever código que deve lidar com dados ausentes, se você precisar tratar uma string vazia como igual a uma string nula.
quant_dev 27/02/12
25
Ao ler esta diretriz, eu esperaria ver uma base de código cheia de: void DoSomething () {DoSomethingFirstSevenLines (); DoSomethingSecondSevenLines (); DoSomethingThirdSevenLines (); etc; }
rebocadores
12
Tente refletindo a maior parte do .NET Framework e ver quantos métodos têm menos de 7 declarações ...
David Boike

Respostas:

195

Este é um "cheiro de padrões" para mim. Sempre que vejo padrões de codificação com limites específicos, eu me preocupo. Você quase sempre encontra um caso em que um método precisa ser maior do que o padrão permite (seja comprimento / contagem de linhas, número de variáveis, número de pontos de saída etc.). Os padrões devem ser mais parecidos com as diretrizes e permitir uma margem de manobra suficiente para o bom julgamento. Não me interpretem mal, é bom ter padrões, mas eles não devem se tornar "microgerenciamento por proxy".

TMN
fonte
25
+1 para "microgerenciamento por proxy". Eu suspeito que alguém leu sobre a regra "7 mais ou menos 2" ( en.wikipedia.org/wiki/… ) e confundiu retenção de fatos a curto prazo com armazenamento a longo prazo, como, você sabe, um editor de código.
fofo
25
Qualquer norma sensata- mente pensada proíbe números mágicos no código, certo? Você pensaria que o padrão de codificação também seria mantido nesse padrão. O número 7 definitivamente tem certamente uma qualidade "mágica".
Adam Crossland
2
Sua resposta faria mais sentido se o título do documento não foi "Codificação Guidlinespara C # 3.0 e 4.0.
Andy
+1 Na minha opinião, a única razão pela qual você deve seguir os padrões de codificação é nunca seguir dogmaticamente um número arbitrário, mas para garantir que você não cause problemas desnecessários de mesclagem no controle de versão (ou seja, problemas associados ao trabalhar em equipe). Geralmente, arquivos mais curtos e mais componentes significam menos chances de você ter problemas ao mesclar alterações de código.
Spoike 28/02
3
Baixei este documento e comecei a procurá-lo. Em 1.6, ele declara: "O documento não declara que os projetos devem obedecer a essas diretrizes, nem indica quais diretrizes são mais importantes que outras. No entanto, incentivamos os projetos a decidirem por si mesmos quais diretrizes são importantes, quais desvios serão levados em consideração por um projeto. use, quem é o consultor em caso de dúvida e que tipo de layout deve ser usado para o código-fonte ". Mesmo que 1 signifique "Diretrizes que você nunca deve ignorar e deve ser aplicável a todas as soluções", você pode optar por modificá-las.
ChrisH
83

Geralmente, é uma boa ideia dividir as coisas em pequenos métodos. Mas o importante é dividir as coisas onde faz sentido.

Se não faz sentido dividir, não divida. Geralmente, esse é o caso de alguns procedimentos ou código da GUI.

Steve McConnell afirmou no Code Complete que você nem sempre é mais produtivo ao usar métodos curtos. Se você dividir quando não fizer sentido, adicione complexidade ao código sem nenhum benefício.

Como sempre com as diretrizes, é bom lembrar por que as restrições existem, para que você possa aprender quando elas não se aplicam. Na maior parte do código, os métodos serão curtos, ou você provavelmente terá um problema com DRY ou separação de preocupações . Mas se não for o caso, tudo bem.

deadalnix
fonte
1
Ótima resposta. As duas últimas linhas levam especialmente a sério o ponto.
Xonatron
6
Eu acho que a regra básica importante é verificar se os submétodos são ortogonais. Se eles são independentes, podem ser chamados em qualquer ordem e respeitarem a classe invariável, é melhor mantê-los separados. Se os métodos estiverem fortemente acoplados, quebre invariantes de classe e / ou precise ser chamado em uma determinada ordem, então talvez seja melhor mantê-los juntos.
hugomg 27/02
4
O código completo está cheio de coisas boas. Todo programador deve comer um pedaço dele no almoço todos os dias.
23412 deadalnix
29

Deve ser considerado como uma regra de ouro.

Coisas como "Não mais que 80 (100.120) colunas de texto", "um ponto de saída por método", "não mais que 2 níveis de aninhamento", são o que eu chamaria de limiares para indicadores de cheiro de código. Se você violá-los ocasionalmente, isso não significa necessariamente que o código esteja incorreto. Se você os violar de forma consistente, algo cheira ao código e você pode fazer uma pausa e repensar sua abordagem.

Para mim, os critérios mais importantes são: "Este código é compreensível?", "É repetitivo?", "É dividido em locais lógicos?", "É pouco acoplado?" Existem mais alguns, mas acho que a idéia básica pode ser resumida lembrando-se do conselho de Donald Knuth: "Os programas são feitos para serem lidos por humanos e apenas por acaso os computadores executam".

seggy
fonte
7
O limite das colunas "80/100/120" é para que possamos ler o código. A maioria dos terminais é aberta em 80 colunas, e é menos esforço fazer o autor quebrar em 80 colunas do que fazer com que todos os leitores redimensionem seus terminais sempre que quiserem ler o código. Diferentemente dos outros limites, o limite da coluna N não afeta a semântica do código, é uma regra puramente estilística; na mesma categoria que "use guias de 4 espaços" ou "coloque chaves de abertura para funções em sua própria linha".
Dietrich Epp
4
É verdade que é um aspecto estético mais que um aspecto semântico. No entanto, é aí que minha última frase se aplica. Não é incomum encontrar instruções Java que excedam a regra das 80 colunas sem um lugar "agradável" para dividir a linha. Isso afeta a legibilidade e a compreensão do código. Ele também pode indicar violações da Lei de Demeter
seggy
7
No século 21, meu IDE possui esse recurso chamado "quebra de linha dinâmica".
György Andrasek
9
@ GyörgyAndrasek: Mas nem todos estão sempre usando seu IDE: analisamos o código no GitHub, nos terminais com less, in vime emacs; e a embalagem automática parece, na melhor das hipóteses, aleatória. Os padrões de codificação não são para seu benefício, eles são para o benefício de pessoas que trabalham em equipe.
Dietrich Epp
2
@DietrichEpp Pessoalmente, tenho dificuldade em ler códigos, que estão sempre agrupados na coluna 80. Recentemente, tive que trabalhar em um projeto Java em que o formatador Eclipse padrão foi usado. E dentro de um método, era muito difícil acompanhar as linhas que ultrapassavam duas ou até três linhas (eu culpo as demais configurações do formatador por isso também). Resumindo, acho que os anos 80 estão um pouco desatualizados. Eu pessoalmente uso um limite de 120, tenho meus editores definidos para fazer cumprir isso, um console com 120 colunas de largura e o Github realmente exibe 125 colunas. E acho que é muito mais legível assim.
cutucar
18

Nunca dediquei tempo para contar o número de declarações em meus métodos, mas me esforço para escrever métodos que executem de maneira limpa um único objetivo claro. Desde que seu código seja limpo, legível e siga os princípios DRY e de responsabilidade única , você provavelmente já fez seu trabalho. Penso que dividir arbitrariamente um método apenas para impor o limite de sete instruções pode tornar seu código menos legível / sustentável.

Joshua Smith
fonte
1
+1 para facilitar a leitura. Não importa se um método tem 20, 30 ou 50 linhas. Se DRY e SRP são seus objetivos, não importa se os métodos parecem um pouco demorados ... embora na maioria das vezes você descubra que quanto mais legível você tenta criar seu código, menores são os métodos naturalmente se tornará.
S.Robins 27/02
11

É aproximado

Esses tipos de regras não devem ser tomadas de maneira muito literal. Eles poderiam ter dito que "os métodos devem ser curtos ". No entanto, algumas pessoas teriam interpretado isso como "menos de 1 página" e outras como "2 linhas no máximo".

Eu diria que eles disseram "7 declarações" para lhe dar uma idéia aproximada (embora eu ache que eles deveriam ter dito "cerca de 7"). Se precisar de 9 de vez em quando, não se preocupe. Mas se você estiver com 20 anos, saberá que não está no estádio certo para esta regra.

Nathan Long
fonte
Isso torna uma aproximação bastante explícita então. Está marcado em "Diretrizes que você nunca deve pular e deve ser aplicável a todas as situações".
brian
1
@ brian - talvez os escritores das diretrizes tenham omitido acidentalmente a palavra "grosso modo", ou talvez fossem do tipo ditador louco. Meu argumento é que o OP deve considerar isso como um número aproximado. Qualquer regra que o compilador ou intérprete não imponha é apenas uma sugestão.
Nathan Long
"Qualquer regra que o compilador ou intérprete não impõe é apenas uma sugestão" Não necessariamente verdade. Eu não olhei para as regras personalizadas de re-compartilhador ou fxcop e se elas realmente aplicam essa regra específica, mas há empresas que o forçam a validar todas as diretrizes de estilo. Eu conheci pessoas cuja empresa os obriga a escrever código que pode passar pelas rígidas diretrizes de codificação da Microsoft.
brian
Concordo que é aproximado e deve ser tomado por um grão de sal, pois um parágrafo do código-padrão traz um número arbitrário inevitavelmente causará confusão. Na maioria das vezes, os padrões são retirados do contexto e as "pessoas" seguem essa aproximação arbitrária como dogma.
Spoike 28/02
10

7 é um número completamente arbitrário com absolutamente nenhum significado.

A complexidade ciclomática é um problema maior que o número de declarações. Eu vi código que tinha centenas de instruções em um único método (que eu achei terrível), mas tinha uma complexidade ciclomática de 1 e realmente fez apenas uma coisa. Havia apenas muitos passos. Discutimos dividi-lo em métodos menores, mas esses métodos seriam chamados apenas por esse método.

Embora esse seja um caso bastante extremo, o ponto é que você precisa manter o código DRY e uma baixa complexidade ciclomática. Isso é mais importante que o número de linhas em um método.

Veja uma declaração de troca / caso, por exemplo. Se você tiver mais de 7 valores possíveis, precisará dividir a avaliação em vários métodos? Claro que não, isso seria bobagem.

A quebra artificial de código em mais métodos, apenas para manter o número de instruções abaixo de 7, só piora o seu código.

A diretriz deve ser Cada método deve fazer uma coisa e manter seu código SECO.

Jim McKeeth
fonte
1
+1: Limites arbitrários são apenas arbitrariamente úteis. Um método deve conter uma única operação coerente em um único nível de abstração. Quebrar uma unidade atômica torna o código mais complexo, dificultando a compreensão do código.
Allon Guralnek
DRY é superestimado. Muitas vezes, isso significa acoplar firmemente dois aspectos de algo que não deve ser tão acoplado.
Brad Thomas
4

Bem, isso depende um pouco. Eu escrevo muito código que acessa bancos de dados. O código da placa da caldeira para manipulação de exceções tem mais de sete instruções em muitos casos. Eu diria que a melhor orientação é garantir que sua função tenha um propósito

Jaydee
fonte
8
Você não pode abstrair o código padrão no seu próprio método?
erjiang
Percebi depois de postar que este é C # não Java, mas estou pensando nesse tipo de coisa. stackoverflow.com/questions/321418/…
Jaydee
@ erjang: você pode. É muito feio em Java, já que você precisa agrupar cada consulta em uma classe anônima, mas ainda vale a pena. Não é tão feio em C # e definitivamente vale a pena.
kevin Cline
Pessoalmente, acho que algumas linhas extras do código de linha da Staight são mais legíveis. Mas talvez seja apenas eu.
21412 Jaydee
@ Jaydee A questão vinculada mostra uma prática comum, mas estranha: Quebrar uma exceção e registrar. No próximo nível, você pode fazer o mesmo ... dessa maneira, uma única exceção aparece várias vezes no log. Seria melhor declarar o método lançando e você salvou 3 linhas. Escrever um método auxiliar fechando ambos pse rse salvar outra. Ou escreva um método List<Row> readDb(String sql, Object... args)que faça todo o trabalho (funciona apenas para conjuntos de resultados que cabem na memória, mas buscar muitos dados geralmente implica que o trabalho deve ser feito no banco de dados de qualquer maneira).
Maaartinus 15/09/14
4

Tudo é uma troca. O problema com a abordagem proposta - refatorar em vários métodos e classes para que cada método seja curto - é que, embora por razões diferentes, leve a um código ilegível quando levado ao extremo.

Imagine um método foo()que faça 7 coisas. Você pode argumentar que 7 coisas são demais. Talvez em muitos casos você esteja certo. Por outro lado, essas sete coisas podem estar intimamente relacionadas; a lógica pode fluir sem problemas e ler como prosa; você pode ter problemas para entender quando realmente precisa. O que pode acabar muito pior é ter essas 7 coisas distribuídas em uma grande árvore de origem, para que, se você olhar, foo()não tenha idéia do que faz sem procurar em 7 lugares diferentes.

Muitas pessoas têm regras como essa na cabeça, e o resultado é o que eu penso como espaguete OO. Tudo é arrumado, encaixotado em seu próprio método ou classe, com pequenas microtransações atômicas ocorrendo em cada local. Mas é impossível chegar a essa base de código e saber o que está fazendo. Você se perde.

asveikau
fonte
4

não é uma má orientação. Eu nunca me arrependi de dividir métodos e classes (nunca achei que tinha muitos), desde que estejam agrupados e inter-relacionados o suficiente.

O truque é NÃO dividi-lo verticalmente (apenas aperte um método em um ponto e inicie um novo). O truque, como no teste de unidade, é manter essa regra em mente desde o início, para que você realmente projete melhor, passando 3 ou 4 instruções no meio do método para outro método, porque ter uma chamada de método descreve o que você está fazendo melhor do que essas 3 ou 4 instruções no meio do seu código.

Esse tipo de divisão, mesmo que seja arbitrário e usado apenas uma vez, pode levar a melhores refatorações mais tarde devido a uma nova clareza de código, isso também se aplica a classes menores.

Pense nisso como se fosse um teste de unidade. Se você tentar adicionar testes de unidade após o fato, é difícil e, às vezes, parecer impossível, mas se você o criar desde o início, realmente melhorará todo o seu código.

Resumo? Se comparar o cheiro de design de "Use menos de 7 instruções" com o cheiro de código de "Eu usei mais de 7 instruções", prefiro eliminar o cheiro de código.

Bill K
fonte
4

Uau! Eu nunca esperei encontrar uma discussão tão intensa sobre uma diretriz simples que diga aproximadamente que seus métodos devem ser muito pequenos. Como eles são sempre desenvolvedores que desejam que suas diretrizes sejam explícitas, escolho 7 porque isso soou como um bom limite.

Alguns de vocês já citaram o aviso no início do documento. Mas, para deixar claro, este documento representa uma coleção de diretrizes que tentam ajudá-lo a escrever melhor código e projetar melhores sistemas. Eu nunca afirmei que algo deveria ser uma regra, mesmo que uma diretriz seja marcada como nível 1. Esses níveis são simplesmente a opinião coletiva de muitas pessoas que usam este documento há algum tempo.

Eu também nunca afirmei ser um especialista. Mas estou nessa profissão há 15 anos, com cerca de 4 anos de experiência em C ++ e 11 anos de experiência em C #. Ele foi originalmente baseado no Industrial Strength C ++, mas eu o refino desde então com a contribuição da comunidade.

Independentemente disso, o ponto que eu estava tentando levantar é que você deve continuar pensando por si mesmo. Se você acha que a diretriz das 7 declarações não é útil, basta prolongá-la. Caramba, eu até viole essa diretriz de vez em quando. Eu apenas a vi violentamente e aceito as consequências.

Dennis Doomen
fonte
3
Que bom que você se intromete, e acho que você faz um argumento razoável. Dito isto, não concordo com a sua lógica "eles sempre desenvolvem que desejam que suas diretrizes sejam explícitas": você nem sempre pode atender a idiotas e não deve tentar. Tornar explícitas as diretrizes é bom, desde que isso não as torne incorretas: agora não é mais uma diretriz, é uma regra arbitrária. A introdução de números arbitrários, como você testemunhou, é uma maneira absolutamente certa de ser abatida e justificada.
21911 Konrad Rudolph
3

Em primeiro lugar: é uma diretriz, não uma regra. É chamado de orientação, portanto, trate-o como tal. Isso implica que seu próprio julgamento também é necessário (como sempre)

Além disso, posso pensar em vários exemplos de bons códigos que não aderem a essa restrição. Mesmo que seja apenas uma orientação, é péssima.

Dominic Cronin
fonte
2

Eu concordo com a afirmação acima de mim. Isso é apenas orientação e, em um mundo perfeito, tudo seria objeto, reutilizado em todos os programas, e o mundo seria um lugar bonito. Nem sempre é verdade e, às vezes, isso levaria a muitos custos indiretos ou desperdiçados. Você precisa colocar isso em mente também.

Falcon165o
fonte
6
"Concordo com a afirmação acima de mim" Evite esse tipo de sentença em sites de troca de pilhas. Lembre-se de que a ordem em que as respostas são postadas não é necessariamente a ordem em que são exibidas.
luiscubal
Eu sei, não pensei até que fosse tarde demais. Mas ainda vou marcar você com +1 por apontar meu peido de cérebro.
Falcon165o
2

Muito bobo quando você adiciona manipulação de exceção à mistura.

Depois de "tentar, pegar, finalmente", você terá quatro instruções por método!

Considere também um método "validateForm" para um formulário de 20 campos, mesmo se você manipular todas as validações individuais em métodos separados, você ainda terá 20 métodos de validação de campo para invocar. De acordo com essas diretrizes, você terminaria com uma divisão inútil, como "validateTopOfScreen", "validateMiddleOfScreen" e "validateBottomOfScreen".

James Anderson
fonte
Eu acho que é bastante seguro dizer que try/ catch/ finallynão são declarações em c #. Consulte Ecma-334 § 12.3.3.15 e seções vizinhas. (abreviado) " uma instrução try-catch-finalmente do formulário : tente try-block catch (...) catch-block-n finalmente finalmente block "
um CVn
Bem, como eu disse antes, é uma decisão que você deve tomar repetidamente. No entanto, seu exemplo específico pode ser um exemplo de não executar corretamente o design orientado a objetos. Você pode dividir sua tela em vários controles que fazem a validação eles mesmos.
Dennis Doomen
@ Dennis - verdade, vem fazendo formulários HTML há muito tempo!
James Anderson
@ James E é para isso que essa diretriz específica se destina. Tentando fazer você pensar em soluções alternativas, potencialmente melhores.
Dennis Doomen
2

A questão está misturando "regras" com "diretrizes". Regras devem ser obedecidas - diretrizes são conselhos que devem levar você a considerar o que está fazendo e se realmente pode ser feito de uma maneira melhor.

Eu diria que, em média, a maioria da programação provavelmente é aprimorada seguindo as diretrizes, mas sempre haverá casos em que seguir as diretrizes dogmaticamente causará mais problemas do que eles pretendiam resolver. É por isso que eles não são apresentados como regras, mas como diretrizes.

Um respondente anterior mostrou que os autores das diretrizes nunca pretendiam que elas fossem aplicadas dogmaticamente e incluiu declarações nesse sentido em seus documentos.

authentictech
fonte
0

Eu concordo com soe dos comentários acima. 7 para mim é arbitrário e pode ser útil em algumas linguagens em que ruby, mas para linguagens como C #, Java, C ++ duvido desta convenção de "7 linhas". Deixe-me dar um exemplo. Meu aplicativo atual possui 22 campos de texto e eu faço a validação no servidor. O método é chamado validateInput () e minha preferência é validar todos os campos em um método, a menos que eu valide algo complexo como checkEmailFormat (). Então, basicamente, meu código de método validateInput é 108 linhas com chamadas ocasionais para validação complexa.

Agora imagine se eu chamasse 25 métodos para validar cada campo. Se um novo desenvolvedor entrar, ele terá que entrar e sair do método principal para passar por 25 métodos que, por sua vez, podem estar chamando alguns outros. Ele é obrigado a se perder em grandes projetos.

O que realmente faço para tornar meu código claro é fornecer comentários simples, que basicamente dizem o que essas quatro linhas estão fazendo ex -

validateInput (usuário UserObj) {

// Valida o primeiro nome ....... ......

// validar sobrenome ...... ......

// validar email ..... // muito complexo para verificar o formato do email expressão regular checkEmailFormat (); .... .....

e assim por diante.. }

Dinesh Arora
fonte
1
Veja também minha resposta à pergunta de James Andersons. No seu caso particular, pergunto-me se esse método de validação não está violando vários princípios e diretrizes ao mesmo tempo.
Dennis Doomen
0

Má regra. Com o código para manipulação de exceções, definindo campos de banco de dados, validação, como a maioria dos métodos pode ter menos de sete instruções? Nunca devemos executar funções lambda embutidas?

Linhas de código são uma contagem arbitrária de complexidade. Com métodos de extensão, posso criar código como

                Parallel.ForEach(regions, region => {   Console.Write(region.Resorts.Where(x => x.name == "Four Seasons").OrderBy(x => x.RegionId).ThenBy(x => x.ResortId).ThenBy(x => x.name).ToList());   });
Justin
fonte
Novamente, um ótimo exemplo de fazer muito em um único método. Em quase todos os contra-argumentos, as pessoas estão violando o Princípio da Responsabilidade Única (no contexto de um método).
Dennis Doomen
-1

Todos os programadores juniores devem ser forçados a aderir a esse princípio. Isso os forçaria a pensar na estrutura do que eles estão ocupados, em vez de apenas adicionar mais e mais código de linhas.

Atualmente, estou olhando para um método de 550 linhas de código com muitas instruções if else e continua e retorna tecidas nele. É porcaria. O programador apenas foi forçado a pensar no que estava fazendo ...

dawidg
fonte