É uma má prática reutilizar parâmetros de método?

12

Há momentos em que precisarei modificar um valor passado para um método de dentro do próprio método. Um exemplo seria desinfetar uma string como este método aqui:

void SanitizeName(string Name)
{
    Name = Name.ToUpper();

    //now do something here with name
}

Isso é puramente inofensivo, pois o Nameargumento não está sendo transmitido por referência. No entanto, se, por algum motivo, um desenvolvedor decidir no futuro passar todos os valores por ref, qualquer higienização da string afetará o valor fora do método, o que pode ter resultados negativos.

Portanto, em vez de reatribuir ao próprio argumento, eu sempre crio uma cópia local assim:

void SanitizeName(string Name)
{
    var SanitizedName = Name.ToUpper();

    //now do something here with name
}

Isso garante que a alteração do valor transmitido nunca afetará o andamento fora do método, mas estou me perguntando se estou sendo excessivamente paranóico sobre isso.

oscilatingcretin
fonte
1
Sim, é uma má prática; e não, não é inofensivo. A linha Name = Name.ToUpper();torna o código mais difícil de seguir em sua mente conforme o valor das Namealterações. Seu segundo exemplo não é apenas mais à prova de futuro, é mais fácil entender o que está fazendo.
David Arno
2
Mas que tal if (param == NULL) param = default_value;?
aragaer
Eu acho que não é tão fácil quanto sim / não.
MrSmith42
3
Se "um desenvolvedor no futuro decidir passar todos os valores passados ​​por ref" , eu provavelmente teria um argumento com esse desenvolvedor, com a reutilização de parâmetros envolvida ou não ;-) Honestamente, quando alguém decide passar um valor by refque não foi aprovado de maneira antecipada e, portanto, convertendo o acesso local em um acesso não local por algum motivo, ele sempre deve verificar as consequências com cuidado.
Doc Brown
2
Trabalho principalmente em um paradigma em que nunca reatribuímos nenhuma variável. Sempre. É engraçado imaginar alguém lutando com a possibilidade de reatribuir uma pequena minoria de variáveis ​​e depois não se preocupar em ficar louco com o resto.
Karl Bielefeldt

Respostas:

10

Eu acho que depende das suas convenções de codificação no seu projeto.

Pessoalmente, deixei o eclipse adicionar automaticamente a finalpalavra-chave a todas as variáveis ​​e parâmetros. Dessa forma, você vê à primeira vista se um parâmetro é reutilizado.

No projeto em meu trabalho, não recomendamos a reutilização de parâmetros, mas se você quiser chamar, por exemplo, .trim()ou definir um padrão em um nullcaso, reutilizamos o parâmetro na maioria das vezes, porque a introdução de uma nova variável é, nesses casos, menos legível do que a reutilização do parâmetro.

Você realmente não deve reutilizar um parâmetro para armazenar um conteúdo muito diferente porque o nome não se refere mais ao seu conteúdo. Mas isso é verdade para toda reatribuição de uma variável e não restrito a parâmetros.

Portanto, reúna-se com sua equipe e formule convenções de codificação que abordam esse assunto.

MrSmith42
fonte
0

Se você usar um analisador de código estático para fins de segurança, ele poderá ficar confuso e você achar que não validou ou higienizou a variável de parâmetro de entrada antes do uso. Se você usar Nameuma consulta SQL, por exemplo, ela poderá reivindicar uma vulnerabilidade de injeção SQL, o que custaria um tempo para explicar. Isso é mau. Por outro lado, o uso de uma variável com nome distinto para a entrada higienizada, sem realmente higienizar a entrada, é uma maneira rápida de silenciar os analisadores de código ingênuos (descoberta de vulnerabilidade negativa falsa).

Greg
fonte
Na maioria dos casos, você também pode usar algum tipo de anotação ou comentário especial para indicar ao analisador de código que isso se destina e não um risco despercebido.
MrSmith42
0

A resposta para isso depende 100% de quem vai ler seu código. Quais estilos eles acham mais úteis?

Eu descobri que o caso mais geral é que evita-se reatribuir valores a argumentos de função, porque muitos desenvolvedores têm modelos mentais de como funciona a chamada de função, assumindo que você nunca faz isso. Esse problema pode ser agravado por depuradores que imprimem os valores dos argumentos com os quais você chama cada função. Tecnicamente , essas informações não estão corretas se você editar os argumentos e isso pode levar a algumas frustrações estranhas.

Dito isto, os modelos mentais mudam. Em seu ambiente de desenvolvimento específico, pode ser desejável ter name"a melhor representação do nome neste momento". Pode ser desejável vincular mais explicitamente as variáveis ​​nas quais você está trabalhando aos argumentos deles, mesmo que você tenha feito algumas modificações nos valores deles ao longo do caminho. Pode até haver vantagens substanciais em tempo de execução para reutilizar algumas variáveis ​​específicas, em vez de criar objetos mais volumosos. Afinal, quando você trabalha com sequências de 4 GB, é bom minimizar o número de cópias extras que você precisa fazer!

Cort Ammon
fonte
-1

Eu tenho um problema completamente diferente com seu exemplo de código:

O nome do seu método é SanitizeName. Nesse caso, espero que ele desinfete um nome ; porque isto é, o que você diz ao leitor sobre sua função.

A única coisa que você deve executar é desinfetar um determinado nome . Sem ler seu código, eu esperaria o seguinte:

string SanitizeName(string Name)
{
    //somehow sanitize the name
    return Result;
}

Mas você implica que seu método faz um pouco mais do que apenas higienizar. Esse é um cheiro de código e deve ser evitado.

Sua pergunta não é sobre: É uma má prática reutilizar os parâmetros do método? É mais: os efeitos colaterais e o comportamento não esperado são más práticas?

A resposta para isso é clara: sim!

Isso é puramente inofensivo, pois o argumento Name não está sendo transmitido por referência. No entanto, se, por alguma razão, um desenvolvedor decidir no futuro passar todos os valores por ref, qualquer higienização da string afetará o valor fora do método, o que pode ter resultados negativos.

Você engana seu leitor ao não retornar nada. O nome do método indica claramente que você está fazendo algo Name. Então, para onde deve ir o resultado? Pela sua função, a assinatura voidlê: eu uso, Namemas não prejudico o id, nem falo sobre o resultado (explicitamente). Talvez haja uma exceção lançada, talvez não; mas Namenão é alterado . Essa é a semântica oposta ao nome do seu método.

O problema é menos a reutilização do que os efeitos colaterais . Para evitar efeitos colaterais , não reutilize uma variável. Se você não tiver efeitos colaterais, não há problema.

Thomas Junk
fonte
4
-1 Isso não responde à pergunta original. O código fornecido é apenas um código de amostra para mostrar a pergunta em questão. Por favor, responda à pergunta, em vez de "atacar" / revisar o código de amostra fornecido.
Niklas H
1
@ NiklasH Isso responde perfeitamente à pergunta: se você manipula o parâmetro dentro da função e, como o TO mencionado, acidentalmente trabalha com uma referência em vez de uma cópia, isso causa efeitos colaterais (como eu disse) e isso é ruim. Para evitar que isso indique que você vai alterar a variável, escolha cuidadosamente o nome do método (pense em Ruby '!') E / ou escolha um tipo de retorno. Se você não alterar a variável, trabalhe apenas com cópias.
23416 Thomas Junk