Os parâmetros opcionais são úteis ou dificultam a manutenção do aplicativo? [fechadas]

14

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?

rjzii
fonte
3
Isenção de responsabilidade: qualquer recurso de idioma nas mãos erradas pode ser abusado. Se uma linguagem implementa isso de maneira inteligente, e esse recurso de linguagem não se sobrepõe muito a um recurso de idioma existente de maneira monótona, então eles estão bem, de fato bastante úteis. O Python possui alguns parâmetros puros para empacotar / descompactar e outros parâmetros "truques" (truques no sentido bom, não no Perl).
Job
Tente escrever um aplicativo em C # que faça interface com o Excel sem usar parâmetros opcionais. Isso deve responder à sua pergunta além de qualquer dúvida razoável.
Dunk

Respostas:

22

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.

David Thornley
fonte
1
+1 E é valioso com métodos sobrecarregados que adicionam um argumento como new Circle(size, color, filled, ellipseProportions)onde sizee colorsão necessários e o restante é o padrão.
Michael K
15

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.

CaffGeek
fonte
1
+1 por ter cuidado. Qualquer recurso, por melhor que seja, pode ser abusado.
Michael K
3
Esse é um ótimo conselho para a produção de código ravioli com engenharia excessiva, em que os usuários da sua API precisam usar pelo menos 6 classes e 15 funções para que aconteça a coisa mais simples.
dsimcha
1
@dsimcha, como você tira isso do que eu escrevi? Uau. Por favor explique? Isso seria um projeto igualmente ruim para ter uma "super função", que é o que você obtém quando possui muitos parâmetros opcionais. Leia sobre os princípios de design do SOLID e escreva código testável. De preferência usando TDD. Então volte e tente me explicar que reduzir parâmetros em funções é uma coisa ruim.
CaffGeek
1
O código testável é bom, mas também é uma API limpa e utilizável que não é excessivamente refinada ou detalhada e não classifica as classes em situações em que uma função é a abstração adequada. Acredito no princípio da responsabilidade única, com responsabilidades definidas em um alto nível de abstração. Se as responsabilidades são definidas em um nível muito baixo, as unidades individuais ficam simplificadas demais, de modo que suas interações são excessivamente complexas.
dsimcha
1
@dsimcha, você está perdendo o objetivo. As unidades individuais devem permanecer unidades individuais e não devem ser agrupadas em uma única função. Isso também não significa que todas são funções acessíveis ao público. Sua API é a porta de entrada para o código e deve ser limpa e concisa. Uma função com vários parâmetros opcionais não é limpa nem concisa. No entanto, sobrecarregar uma única função com parâmetros lógicos é muito mais clara. Por exemplo, existem funções em muitas APIs em que dois parms são opcionais, mas um ou outro é necessário. O que está claro sobre isso quando ambos estão marcados como opcionais?
CaffGeek
4

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 ("[email protected]");

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.

Gary Rowe
fonte
1
funções de formatação de string como printf são a exceção à regra, alguém poderia argumentar que, embora eles usem uma lista ilimitada de parâmetros opcionais, é mais como o argumento é uma matriz do que parâmetros opcionais, apesar de implementados.
CaffGeek
@Chad Eu ajustei minha resposta para diferenciar melhor os parâmetros opcionais e quando eles passam para um cheiro de código (como você mencionou na sua resposta).
Gary Rowe
@ Gary Rowe, muitos parâmetros opcionais também são ruins na maioria dos casos.
CaffGeek
@Chad Eu concordo, mas a maioria dos idiomas não fornece uma maneira de especificar um limite no número de argumentos opcionais, portanto é uma abordagem de tudo ou nada. Você é forçado a deixar o seu método aplicar e, obviamente, se o seu método estiver lidando com 500 variáveis, ele definitivamente precisará ser refatorado.
Gary Rowe
@ Gary Rowe, o que você quer dizer com "a maioria dos idiomas não fornece uma maneira de especificar um limite para o número de argumentos opcionais"? Na maioria dos idiomas, você os marca como tal ou não fornece valores ao chamar a função, mas o cabeçalho da função ainda possui os parâmetros definidos. É verdade que, em alguns idiomas, você pode adicionar quantos parâmetros desejar depois de preencher os definidos, mas não acho que esse seja o tipo de parâmetro opcional que estamos falando aqui. (com exceção de exceção formato string)
CaffGeek
2

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.

Po-ta-toe
fonte
1

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.

davidk01
fonte
1

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.

dsimcha
fonte
1

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 $... ]]] )
Martin Wickman
fonte
1

Parâmetros opcionais são basicamente uma maneira diferente de sobrecarregar uma função. Então isso basicamente se resume a: "sobrecarregar uma função é ruim"?

Pieter B
fonte
1

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

Alex Punnen
fonte
0

Eu acho que seria melhor sobrecarregar uma função com assinaturas diferentes (ou seja, parâmetros) do que usar parâmetros opcionais.

Código difícil
fonte
Por quê? Eu acho que é mais limpo se você pode combinar um monte de métodos sobrecarregados em um método que usa parâmetros padrão se todos os métodos têm a mesma funcionalidade básica
Amit Wadhwa
Você pode pensar isso. Não acho que a Microsoft faça tudo da maneira certa, mas se você fosse preciso, nunca veria sobrecargas ao usar o .NET framework, apenas uma enorme assinatura de função - como no antigo VB6.
HardCode