Conforme indicado no título, os parâmetros opcionais, como os usados em C #, são úteis ou são um obstáculo à manutenção do aplicativo e devem ser evitados, pois podem dificultar a compreensão do código?
Conforme indicado no título, os parâmetros opcionais, como os usados em C #, são úteis ou são um obstáculo à manutenção do aplicativo e devem ser evitados, pois podem dificultar a compreensão do código?
Respostas:
Parâmetros opcionais, na minha experiência, foram uma coisa boa. Eu nunca os achei confusos (pelo menos não mais confusos do que a função real), pois sempre posso obter os valores padrão e saber o que está sendo chamado.
Um uso para eles é quando eu tenho que adicionar outro parâmetro a uma função que já está em uso geral, ou pelo menos na interface pública. Sem eles, eu teria que refazer a função original para chamar uma que tenha outro argumento, e isso pode ficar muito antigo se eu acabar adicionando argumentos mais de uma vez.
new Circle(size, color, filled, ellipseProportions)
onde size
e color
são necessários e o restante é o padrão.
Em geral, se você precisar de muitos parâmetros opcionais / muitas vezes, suas funções estão fazendo muito e devem ser divididas. Você provavelmente está violando o SRP (princípio de responsabilidade única).
Procure por parâmetros que podem ser agrupados, por exemplo (x e y, tornam-se um ponto).
Esses parâmetros opcionais são sinalizadores com um padrão? Se você estiver usando sinalizadores, a função deve ser dividida.
Isso não significa que você nunca deve ter parâmetros opcionais, mas, em geral, mais de um ou dois parâmetros sugerem um cheiro de código.
Também pode ser uma pista de que a função deve realmente ser uma classe, com os parâmetros opcionais alterados para propriedades e os parâmetros necessários como parte do construtor.
Parâmetros opcionais são ótimos
Normalmente, a justificativa é que: a) você sabe que possui muitos argumentos possíveis para seu método, mas não deseja sobrecarregar por medo de obstruir sua API ou b) quando não conhece todos os argumentos possíveis, mas não deseja forçar seu usuário a fornecer uma matriz. Em cada caso, os parâmetros opcionais são resgatados de maneira organizada e elegante.
aqui estão alguns exemplos:
1. Você deseja evitar sobrecargas e não deseja especificar uma matriz
Dê uma olhada em printf () de C, Perl, Java etc. É um ótimo exemplo do poder dos parâmetros opcionais.
Por exemplo:
printf("I want %d %s %s",1,"chocolate","biccies");
printf("I want %d banana",1);
Sem sobrecarga, sem arrays, simples e intuitivo (depois de entender os códigos de formato de sequência padrão). Alguns IDEs dirão até se sua string de formato não corresponde aos seus parâmetros opcionais.
2. Você deseja permitir o uso de padrões e mantê-los ocultos do usuário do método
sendEmail ("test@example.org");
O método sendEmail detecta que vários valores essenciais estão ausentes e os preenche usando padrões definidos (assunto, corpo, cc, cco etc.). A API é mantida limpa, mas flexível.
Uma observação sobre muitos parâmetros
No entanto, como outros declararam, ter muitos parâmetros obrigatórios para um método indica que você provavelmente tem algo errado com seu design. Isso é particularmente verdadeiro se eles compartilham o mesmo tipo, pois podem ser alternados pelo desenvolvedor por acidente, causando resultados estranhos no tempo de execução:
String myMethod(String x, String y, String z, String a, int b, String c, int d) {}
é um candidato ideal para a refatoração do Introduce Parameter Object para criar
String myMethod(ParameterObject po) {}
class ParameterObject {
// Left as public for clarity
public String x;
public String y;
... etc
}
Por sua vez, isso pode levar a um design melhor baseado em um padrão de fábrica com uma especificação fornecida como objeto de parâmetro.
Um dos problemas com os parâmetros padrão em C # (estou pensando em fazer DoSomething nulo (int x = 1)) é que são constantes. Isso significa que, se você alterar o padrão, terá que recompilar os consumidores dessa chamada de método. Embora isso seja fácil o suficiente, há ocasiões em que isso é perigoso.
Depende do que seu código está fazendo. Se houver padrões sensíveis, você deve usar parâmetros opcionais, mas se não houver padrões sensíveis, a adição de parâmetros opcionais tornará seu código mais complicado. Em muitos casos, os parâmetros opcionais são uma maneira clara de evitar verificações e eliminar a lógica de ramificação. Javascript não possui parâmetros opcionais, mas existe uma maneira de imitá-los com || (lógico ou) e eu o uso o tempo todo ao fazer coisas relacionadas ao banco de dados, porque se o usuário não fornecer algum valor, substituo meus próprios valores com a ajuda de || o que me poupa o trabalho de escrever um monte de declarações if then.
Parâmetros opcionais são uma ótima maneira de tornar simples coisas simples e complicadas possíveis simultaneamente. Se houver um padrão claro e razoável que a maioria dos usuários deseje, pelo menos em casos de uso rápidos e sujos, eles não deverão escrever um padrão para especificá-lo manualmente sempre que chamarem sua função. Por outro lado, se as pessoas tiverem um bom motivo para querer alterá-lo, ele precisará ser exposto.
Usar uma classe é IMHO uma solução terrível, pois é detalhada, ineficiente e inconsistente com o modelo mental típico do que uma classe faz. Uma função é a abstração perfeita para um verbo, ou seja, fazer alguma coisa e retornar. Uma classe é a abstração correta para um substantivo, ou seja, algo que possui estado e pode ser manipulado de várias maneiras. Se o primeiro for o modelo mental do usuário da API, não faça dele uma classe.
O problema com argumentos opcionais é que as pessoas tendem a apenas colocar mais e mais (e mais) argumentos para a função em vez de extrair o código relevante em uma nova função. Isso é levado ao extremo em php . Por exemplo:
bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
[, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Inicialmente, eu amei esse recurso em python e o usei para 'estender' os métodos já usados. E parecia agradável e fácil, mas voltou logo; porque quando adicionei um parâmetro opcional, isso modificava o comportamento de um método existente no qual o cliente antigo contava e de uma maneira que não era detectada pelos casos de teste de unidade existentes. Basicamente, fazer isso é violar o Princípio Aberto Fechado; o código está aberto para extensão, mas fechado para modificação. Portanto, acredito que usar esse recurso para modificar o código existente não é uma boa ideia; mas tudo bem se usado desde o início
Eu acho que seria melhor sobrecarregar uma função com assinaturas diferentes (ou seja, parâmetros) do que usar parâmetros opcionais.