É uma má idéia listar todos os argumentos de função / método em uma nova linha e por quê?


22

Eu trabalho com alguém que, toda vez que chama uma função, coloca os argumentos em uma nova linha, por exemplo

aFunction(
    byte1,
    short1,
    int1, 
    int2,
    int3,
    int4,
    int5
) ;

Eu acho isso muito irritante, pois significa que o código não é muito compacto, então eu tenho que escanear mais e mais para realmente entender a lógica. Estou interessado em saber se isso é realmente uma má prática e, em caso afirmativo, como convencê-los a não fazer isso?


25
+1, não sei o suficiente para responder à sua pergunta, mas também odeio isso. Se você tiver muitos argumentos em uma função, no entanto, sua função provavelmente está fazendo muito.
maple_shaft

28
Mais ao ponto, por que ainda precisamos ver as preferências uns dos outros sobre isso? por que nossos IDEs não podem apresentá-lo automaticamente no estilo que queremos?
Alex Feinman

5
Mike, eu gosto de ter código que ocupa pouco espaço na tela. Mas é um compromisso. Coloquei {em uma linha separada porque facilita a correspondência com o fechamento} e a compreensão correta do escopo do bloco. Vale a pena a troca de perder uma linha de imóveis na tela.
Brian Schroth

2
@ Alex: Você está totalmente certo. Eu acho que a coisa certa a fazer seria ter um idioma em que a árvore de análise do código seja armazenada no disco e exibida de acordo com as preferências do usuário.
Neil G.

1
@maple_shaft Detesto declarações como essa. Não porque não exista verdade, mas porque muitas pessoas seguem esse conselho sem deixar espaço para nuances.
Stijn

Respostas:


38

É apenas uma diretriz de codificação da qual você pode ou não gostar. O importante é que você e seus colegas concordem em usá-lo ou não.

Obviamente, a melhor maneira de aumentar a legibilidade é limitar o número de argumentos.


24
Muitas pessoas reduzem os argumentos despejando-os em uma matriz. Prefiro ver uma bagunça feia do que um código mais limpo, com complexidade oculta.
30611 Satanicpuppy

18
Matrizes não são o caminho a percorrer. Pode haver uma estrutura oculta nos argumentos, ou talvez a função esteja fazendo muito e deva ser dividida.
Michael K

4
Acho que o uso de várias linhas ajuda a tornar o código legível se os parâmetros são expressões longas ou são muitos. Caso contrário, é apenas irritante.
PedroC88 30/06

3
Colocá-los em um objeto de transferência de dados apenas move o problema. Se todos os argumentos forem necessários, todos deverão ser argumentos obrigatórios do construtor do DTO, o que significa que você ainda possui muitos argumentos.
Scott Whitlock

21

É uma questão de preferência. Para chamadas de função complicadas onde você deseja documentar cada parâmetro ou onde as variáveis ​​são bastante longas e existem muitas delas, isso pode ser bom.

Por exemplo:

do_complex_op(
      0, //Starting state, always 0, ask Joe why
      X, //X-coord of thingy
      y, //Y-coord of thingy
      73, //in this case, we don't want to use Z but want constant 
      dlogMessageTitle, //message for dialogue title
      dlogMessageText, //message for dialogue contents, don't care about this.
      SomethingIP, //IP of something-or-other server, can be NULL, won't crash.
      someObject.childObject.getValue(key1).HVAL, //very long path to HVAL
      someObject.childObject.getValue(key1).LVAL, //very long path to LVAL
      this.parentWindow.owner.mainTextBox.text.value.trim, //get the trimmed text, untrimmed text causes weird output
      pvrMainSettingForLongBlahs.getObjectByPath(somePath),
      pvrMainSettingForLongBlahs.K_TCA_UPPER_LIMIT,
      pvrMainSettingForLongBlahs.K_ENDPOINT_COMPLIANCE_LEVEL,
 );

Com idiomas que permitem parâmetros nomeados, isso é mais comum se você usar os nomes dos parâmetros (o exemplo está em PL / SQL):

PKG_SOME_TEST_CODE.FN_DO_SOMETHING( in_text => 'test text',
                                    in_id => v_id,
                                    in_ref_id => v_ref_id,
                                    out_array_for_storage => v_bArray); 

Mas concordo que, se a chamada de função for simples e não houver muitos parâmetros, isso pode ser irritante, como:

setColour (
    r,
    g,
    b
 );

Acho muito mais fácil ler como

 setColour(r,g,b);

Para @ammoQ:

rc=a(b,c(d,e(f)))

rc=a(
     b,
     c(
       d,
       e(
         f
        )
      )
    )

11
O primeiro exemplo é uma resposta errada para um problema real. Por que não usar variáveis ​​variáveis ​​explícitas em primeiro lugar?
deadalnix

@deadalnix: Bom ponto, limpou um pouco.
FrustratedWithFormsDesigner

1
Verdade. No entanto, nem sempre é um problema com nomes de variáveis. É mais a ver com nomes de variáveis longos, argumentos com valores padrão, etc
inspectorG4dget

4
Eu diria que a melhor solução para o problema é refatorar do_complex_op (), para que ele pegue uma estrutura como parâmetro. Então você pode fazer do_complex_op(new paramStruct { StartingState = 0, XCoord = xcoord }), então torna-se auto documentar e muito mais fácil de ler
KallDrexx

1
@KallDrexx: Eu concordo, mas às vezes alterar o código não é uma opção, como quando é uma função na biblioteca de outra pessoa. Claro, eu poderia criar um invólucro, mas ainda precisarei chamar a função original em algum momento.
FrustratedWithFormsDesigner

10

Na OMI, tudo o que é incomum é uma prática ruim, a menos que sua superioridade em relação ao estilo usual possa ser comprovada positivamente. “Questão de gosto” é uma desculpa ruim para escrever código mais difícil de ler do que o necessário para a maioria dos programadores, porque um dia uma alma pobre, não acostumada a esse estilo, precisará manter esse código.

Provar que isso é incomum é relativamente fácil, mostra a fonte de exemplos no MSDN ou em sites similares, mostra grandes bases de código-fonte aberto etc. Mostre a saída dos embelezadores de código. Por fim, mostre como todo mundo em sua equipe está fazendo isso. Não aceite um estilo ruim apenas porque alguém é muito teimoso.


Hum ... com essa abordagem, como poderíamos introduzir uma nova prática recomendada (ou gramaticalmente correta: uma prática melhor )?
Treb

2
Treb: Claro, apenas mostre que a melhor prática é de fato melhor , não apenas diferente .
user281377

4
Mas "mais difícil de ler" é, por si só, subjetivo e uma questão de opinião. Para mim, é mais fácil analisar visualmente um argumento por linha do que dois, três ou quatro argumentos por linha. E sempre divido uma chamada em várias linhas se ela ultrapassar aproximadamente a marca de 100 caracteres no editor.
Toby

2
Meh. "Mais difícil de ler" pode ser medido objetivamente. Apenas tende a não ser. Discutir sobre isso é mais divertido.
JasonTrue 30/06

1
pode ser medido objetivamente, mas não independentemente da pessoa que faz a leitura.
jk.

9

Bem, aqui estão algumas iscas de voto negativo. Eu nunca fui acusado de fazer a coisa popular. Claramente, se as coisas couberem em uma linha, então tudo bem, coloque-as em uma linha.

Mas minha principal preocupação não é se o código é "feio" ou "bonito". Minha principal preocupação é como é fácil entender e fazer alterações sem cometer erros.

Se os argumentos são longos e existem muitos, por que não colocá-los em linhas separadas? Na minha opinião, isso facilita a visualização do que são e a alteração, se necessário. Também me dá espaço para anexar um comentário a cada argumento, se eu quiser.

Também quero minimizar a chance de cometer um erro se adicionar ou remover um argumento a uma função, o que é mais provável que ocorra no final de uma lista de argumentos do que no início. Por esse motivo, prefiro colocar a vírgula (,) no início de uma linha do que no final. Então, se, por exemplo, desejo remover ou adicionar um argumento no final da lista, é uma edição em uma linha. Não preciso mexer na vírgula que precisa ir no final de todas as linhas, exceto a última, onde a última deve terminar entre parênteses.

Então (garoto, eu vou ser queimado por isso) eu escrevo assim:

nameOfFunction(firstArgument
    , secondArgument // optional comment
       ...
    , lastArgument   // optional comment
    );

Quando há uma função com de cinco a vinte argumentos, a função não fica assim de uma só vez. Ele cresceu com o tempo, o que significa que houve muitas edições. Qualquer edição não concluída é um erro de sintaxe ou um bug. Então eu não afirmo que isso é bonito. Eu afirmo que ajuda a obter as edições corretas.

(E para aqueles que dizem que eu deveria passar uma estrutura, tudo o que faz é substituir o problema, porque você precisa de várias linhas de código para preencher a estrutura, sem mencionar o código extra para declarar e alocá-la.)


1
Pessoalmente, acho que essa é uma ótima resposta, porque você explicou muito bem o seu raciocínio. Bom trabalho, Mike.
Jordan

8

Eu também não chamaria. A melhor prática em que trabalhei geralmente era fazer com que as chamadas de função estivessem todas em uma linha, a menos que você tivesse que rolar horizontalmente qualquer quantia significativa para ver a chamada inteira. É um julgamento, mas eu definitivamente diria que, para colocar todos funções assim está fora de linha, a menos que esse seja o padrão estabelecido por sua organização.

É por isso que é uma boa prática para uma organização estabelecer um conjunto de guias aos quais todos os programadores devem aderir. É tudo sobre consistência e legibilidade.


5

Torna mais fácil:

  • Reordenar argumentos.
  • Comente ou desative argumentos.
  • Veja exatamente qual argumento mudou quando você vê diferenças no seu sistema de controle de versão
  • Evite recuar e agrupar tudo ao adicionar ou remover um argumento ou alterar o nome da função. (Mesmo que o editor recue automaticamente, você ainda estará criando muitas alterações inúteis no espaço em branco que dificultam o acompanhamento das alterações no sistema de controle de versão.)

4

Eu diria que as chamadas de função devem estar todas em uma linha, a menos que excedam significativamente a largura do código padrão (geralmente 80 caracteres, geralmente causa de argumentos :-).

Não vejo nenhuma vantagem nesse estilo. Parece subjetivamente feio, e acho difícil ao pesquisar código. Por exemplo, você pode procurar rapidamente e ver se a função é chamada com um determinado parâmetro passado como NULL. Isso é fácil visualmente quando todos os parâmetros estão em uma linha e mais difícil quando eles são divididos assim.


Essa coisa de 80 caracteres tem que desaparecer, simplesmente não existem mais razões tecnicamente válidas para isso. Agora vivemos em uma era de monitores 19xx X 16xx e fontes ajustáveis ​​E tamanhos de fonte.
anon

4
@anon: razões válidas para isso? Por que você acha que o texto é impresso em colunas e os livros são mais estreitos do que poderiam ser? Porque o olho humano perde a trilha ao ler linhas muito longas.
Zan Lynx

4
@anon: Também gosto de usar minha tela widescreen para abrir dois ou três arquivos em uma divisão horizontal que retorna de 80 a 100 caracteres em uma linha.
Zan Lynx

4
@anon: Tecnicamente não, praticamente: inferno SIM. O Zan Lynx tem toda a razão, além de outros motivos: mesclar, diferenciar, usar utilitários de linha de comando ... Ah, e boa sorte com o foco na fonte 8p à medida que você envelhece: o)
MaR

3

Eu sempre vi esse estilo em declarações ou definições de funções , mas nunca em uma chamada (até agora). Às vezes, faz sentido, pois permite adicionar um comentário para parâmetros individuais mais claramente. Parece que ele copiou esse estilo para ligações sem realmente conhecer as razões subjacentes a ela. Você tem um bom argumento contra e ele não parece ter um bom voto, então você tem meu voto, mas não sou eu quem você deve convencer.


Eu vejo as duas chamadas. Se a lista de parâmetros for muito longa, ela deverá ser dividida em várias linhas. Se os parâmetros não agruparem normalmente dentro dos limites de largura, espero que eles estejam em linhas separadas. Se os nomes de função e parâmetro se encaixam bem em uma linha, geralmente os vejo organizados dessa maneira.
BillThor

2

É contra os padrões de codificação da empresa?

Caso contrário, inicie uma discussão sobre os padrões e o que as pessoas gostariam que mudassem. Lembre-se de trazer isso como uma das coisas que você gostaria de mudar.

Tenha uma discussão completa sobre por que você acha que isso não é útil e espero que você ganhe o dia. Você nunca sabe que seu colega pode convencê-lo de que o caminho dele é o melhor, afinal;)

Depois de ter um padrão atualizado, é documentado o que todos deveriam estar codificando; portanto, se o seu colega persistir, você poderá aumentá-lo nas revisões de código.


2

Pode parecer estranho para você, mas facilita o trabalho no código. Ao refatorar, você pode comentar argumentos individuais com muita facilidade e verificar seu refatorador antes de excluir as coisas. Você também pode comentar e substituir temporariamente tipos facilmente.

Também é mais fácil de ler do que:

int f(int, int, int,
      char, double, int
      X const&, Y)
{}

Eu não fui tão extremo quanto você está mostrando (já que não há nomes nos parâmetros, isso não ajuda muito), mas adquiri o hábito de dividir cada parâmetro em sua própria linha ou não fazer divisão.

A parte importante é que seu código pode ser impresso ou exibido em telas padrão de 80 cores e ainda assim legível.


2

Você raramente obterá uma resposta honesta de um programador para algo assim. Todos responderão apenas com o que fazem ou não. A verdade é que, por mais que todos lutemos com isso às vezes, a única "má prática" aqui é a sua própria inflexibilidade.

Você precisa ser brutalmente honesto consigo mesmo para poder distinguir entre coisas que são realmente ruins e coisas que apenas o incomodam. A verdade é que, em C / C ++ e linguagens similares, você raramente encontrará uma prática de indentação que tenha um efeito tangível na compreensibilidade do código. A maioria das discussões sobre esse tipo de coisa tem ambos os lados empilhados, com pessoas fazendo argumentos ridículos e fingidos para tentar justificar sua preferência pessoal.

O que, para minha leitura ..., é exatamente o que você está solicitando nesta pergunta: um argumento ridículo e falso para justificar sua preferência pessoal.


0

Para ser honesto, depende da pessoa. Eu diria que para funções complexas, como demonstrado pelo primeiro exemplo de FrustratedWithForms, então sim; caso contrário, um grande NÃO. Então, novamente, é por isso que prefiro aplicar a funcionalidade IDE do código arbitrariamente.


0

"Estou interessado em saber se isso é realmente uma má prática ..."

Sim, é uma prática ruim, exceto quando a lista de variáveis ​​é anormalmente longa. Mas, nesse caso, o problema provavelmente se deve ao design da função. Por que não passar um objeto que encapsula muitos dos parâmetros?

"... e se sim, como posso convencê-los a não fazer isso?"

Amarre-os e continue fazendo cócegas até eles concordarem em parar com essa porcaria.


"Por que não passar um objeto que encapsula muitos dos parâmetros?" OK, agora você mudou o problema para esse novo objeto. Ele ainda precisa da mesma quantidade de parâmetros (por meio de seu construtor, por exemplo), para que você ainda tenha o mesmo problema.
Stijn

-2

Por que você está desperdiçando ciclos com uma preocupação tão trivial? Basta iniciar o seu confiável IDE, abrir o arquivo e reformatar. Voila! Será da forma que você quiser.

Agora vamos para a questão realmente importante - vi ou emacs, LOL.


E então, quando você vem conferir isso no controle de origem?
Pd

-2

Eu diria que, se os argumentos se encaixarem em uma linha, faça-o. Caso contrário, um argumento por linha garante grande legibilidade.

foo(arg1, arg2, arg3, arg4, arg5)

vs.

foo(
    arg1=arg1,
    arg2=arg2,
    arg3=arg3,
    arg4=arg4,
    arg5=arg5,
    arg6=arg6,
    arg7=arg7
)

3
este não parece oferecer nada substancial sobre pontos feitos e explicado em anteriores 14 respostas
mosquito
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.