Uma função pode ser muito curta?

125

Sempre que me pego escrevendo a mesma lógica mais de uma vez, costumo colocá-la em uma função para que haja apenas um lugar no meu aplicativo que eu tenha para manter essa lógica. Um efeito colateral é que às vezes acabo com uma ou duas funções de linha, como:

function conditionMet(){
   return x == condition;
}

OU

function runCallback(callback){
   if($.isFunction(callback))
     callback();
}

Isso é preguiçoso ou é uma prática ruim? Eu só pergunto porque isso resulta em um número maior de funções que exigem peças muito pequenas de lógica.

Mark Brown
fonte
3
Não, não muito curto. Em C #, eu faria 'condição atendida' como uma propriedade, que é elegante e consideraria usar Assert.AreEqual<int>(expected, actual, message, arg1, arg2, arg3, ...);. O segundo está bem como está. Eu incluiria potencialmente um sinalizador bool opcional que ditaria se lançaria uma exceção / etc. caso o retorno de chamada não seja uma função.
38
Sim, em apenas um caso: function myFunction () {}
Spooks
5
def yes(): return 'yes'
precisa saber é o seguinte
3
@Spooks - Estou dividindo os cabelos aqui, mas funções vazias são válidas para pelo menos classes de adaptadores, por exemplo, MouseMotionAdapter em download.oracle.com/javase/6/docs/api/java/awt/event/… . Obviamente, essa é apenas uma maneira de solucionar as limitações de idioma.
Aleksi Yrttiaho
3
@dietbuddha: Os requisitos foram alterados - agora ele precisa suportar dois idiomas para uma demonstração na próxima semana. O cara que escreveu "def yes ()" se sentiu muito feliz por ter mudado para "def yes (: (IsFrench ()? 'Oui': 'Yes')"
Andrew Shepherd

Respostas:

167

Hehe, oh Sr. Brown, se eu pudesse convencer todos os desenvolvedores que encontro a manter suas funções tão pequenas quanto isso, acredite, o mundo do software seria um lugar melhor!

1) A legibilidade do seu código aumenta dez vezes.

2) É tão fácil descobrir o processo do seu código por causa da legibilidade.

3) SECO - Não se repita - você está se adaptando muito bem a isso!

4) testável. As pequenas funções são um milhão de vezes mais fáceis de testar do que os métodos de 200 linhas que vemos com muita frequência.

Ah, e não se preocupe com o "salto de função" em termos de desempenho. As versões "Release" e as otimizações do compilador cuidam disso muito bem para nós, e o desempenho é 99% do tempo em outro lugar no design de sistemas.

Isso é preguiçoso? - Muito pelo contrário!

Isso é uma prática ruim? - Absolutamente não. Melhor usar essa maneira de criar métodos do que as bolas de alcatrão ou "objetos de Deus", que são muito comuns.

Mantenha o bom trabalho, meu colega artesão;)

Martin Blore
fonte
40
Você não está respondendo à pergunta, apenas está pregando a regra cujas aplicações mais extremas são questionadas aqui.
4
Não é muito frequente que eu ache a limitação de apenas 1 voto positivo frustrante. Mas, para esta resposta, o +1 não parece fazer justiça.
Bevan
4
+5 ... oh, só posso fazer +1, tudo bem! E para dar suporte ao MeshMan, sugiro o seguinte livro de Robert C. Martin Código limpo . Este livro está realmente mudando a maneira como agora programo.
Eric-Karl
10
Resposta muito agradável, mas discordo da maioria: 1) Funções extremamente pequenas resultam em mais código geral, devido a todo o encanamento necessário para cada função. Isso pode reduzir a legibilidade, especialmente para um projeto realmente grande. Além disso, depende do idioma. 2) Depende inteiramente do ponto 1 e, portanto, não tem nada a ver com a questão. 3) O que? runCallback repete "retorno de chamada" quatro vezes e três vezes se refere à mesma variável para executar uma única função. 4) É claro que mais de 200 métodos de linha não podem ser testados, mas existe um longo caminho até uma linha.
l0b0
10
-1: A coisa mais assustadora aqui é o número de votos dados para esta resposta.
Luca
64

Eu diria que um método refatorado é muito curto se:

  • Duplica uma operação primitiva, sem outra finalidade senão torná-la um método:

Ex:

boolean isNotValue() {
   return !isValue();
}

ou...

  • O código é usado apenas uma vez e sua intenção é fácil de entender rapidamente.

Ex:

void showDialog() {
    Dialog singleUseDialog = new ModalDialog();
    configureDialog(singleUseDialog);
    singleUseDialog.show();
}

void configureDialog(Dialog singleUseDialog) {
    singleUseDialog.setDimensions(400, 300);
}

Esse poderia ser um padrão válido, mas eu apenas incorporaria o método configureDialog (), neste exemplo, a menos que pretendesse substituí-lo ou reutilizar esse código em outro local.

RMorrisey
fonte
7
Separar um método de linha única no segundo caso pode ser benéfico para manter consistente o nível de abstração dos métodos de chamada. O exemplo fornecido está em cima do muro se esse raciocínio for usado: a largura e a altura exatas dos pixels são muitos detalhes para mostrar uma caixa de diálogo?
Aleksi Yrttiaho 02/04
2
O método "isNotValue ()" tem um nome incorreto e deve ser refatorado para nomear a questão real do domínio.
4
@ Aleksi: eu discordo; os detalhes já estão ocultos no método showDialog () neste exemplo; não há necessidade de refatorá-lo duas vezes. O exemplo pretende mostrar um caso de uso isolado; se um padrão for necessário com diferentes configurações de diálogo em diferentes casos, faria sentido voltar e refatorar uma vez que o padrão seja estabelecido.
precisa saber é o seguinte
1
@ Thorbjorn: Eu pude ver um argumento para isso, quando você está respondendo a uma pergunta de domínio comercial cuja lógica pode não ser óbvia. Estou apenas apontando que há alguns casos em que é um exagero.
#RedReady
3
Talvez isso seja preciso, mas eu diria que nos seus exemplos o problema não é que a função seja muito curta, mas que eles não agregam valor descritivo.
9123 keppla
59

Uma função pode ser muito curta? Em geral não.

De fato, a única maneira de garantir que:

  1. Você encontrou todas as classes em seu design
  2. Suas funções estão fazendo apenas uma coisa.

É manter suas funções tão pequenas quanto possível. Ou, em outras palavras, extraia funções de suas funções até que você não possa mais extrair. Eu chamo isso de "Extrair até cair".

Para explicar isso: Uma função é um escopo com blocos de funcionalidade que se comunicam por variáveis. Uma classe também é um escopo com blocos de funcionalidade que se comunicam por variáveis. Portanto, uma função longa sempre pode ser substituída por uma ou mais classes com método pequeno.

Além disso, uma função que é grande o suficiente para permitir que você extraia outra função dela, está fazendo mais de uma coisa por definição . Portanto, se você pode extrair uma função de outra, deve extrair essa função.

Algumas pessoas temem que isso leve a uma proliferação de funções. Eles estão certos. Será. Isso é realmente uma coisa boa. É bom porque as funções têm nomes. Se você for cuidadoso ao escolher bons nomes, essas funções atuam como postagens de sinalização que direcionam outras pessoas através do seu código. De fato, funções bem nomeadas dentro de classes bem nomeadas dentro de namespaces bem nomeados são uma das melhores maneiras de garantir que seus leitores NÃO se percam.

Há muito mais sobre isso no episódio III do código limpo em cleancoders.com

Tio Bob.
fonte
5
Tio Bob! Ótimo vê-lo a bordo aqui. Como esperado, conselhos fantásticos. Eu nunca ouvi o termo "Extrair até cair" antes e certamente usará esse termo no escritório na segunda-feira;).
Martin Blore
1
Você gostaria de elaborar seu ponto # 1? Explicar que pelo exemplo seria ótimo.
Daniel Kaplan
53

Uau, a maioria dessas respostas não ajuda muito.

Nenhuma função deve ser escrita cuja identidade seja sua definição . Ou seja, se o nome da função for simplesmente o bloco de código da função escrito em inglês, não a escreva como uma função.

Considere sua função conditionMete essa outra função addOne(perdoe-me pelo meu JavaScript enferrujado):

function conditionMet() { return x == condition; }

function addOne(x) { return x + 1; }

conditionMeté uma definição conceitual adequada; addOneé uma tautologia . conditionMeté bom porque você não sabe o que conditionMetimplica apenas dizendo "condição atendida", mas pode ver por que addOneé bobo se você ler em inglês:

"For the condition to be met is for x to equal condition" <-- explanatory! meaningful! useful!

"To add one to x is to take x and add one." <-- wtf!

Pelo amor de qualquer coisa que ainda possa ser santa, por favor, não escreva funções tautológicas!

(E pelo mesmo motivo, não escreva comentários para todas as linhas de código !)

Rei Miyasaka
fonte
Algumas das construções de linguagem mais complexas podem não ser familiares ou difíceis de ler, tornando esse truque útil.
3
Concordado, o que exatamente deveria ser transformado em uma função dependeria amplamente do idioma em que está sendo escrito. Uma função como addOne seria útil se você estivesse em um idioma como VHDL, onde na verdade está definindo o significado de adicionar um em um nível de teoria binária ou de número. Eu gostaria de pensar que nenhuma linguagem lá fora é tão enigmática que é difícil de ler, mesmo para programadores experientes (talvez brainf # ck), mas se for esse o caso, a mesma idéia permaneceria, já que a função é efetivamente uma tradução do inglês para esse idioma - portanto, o nome não é o mesmo que a definição.
Rei Miyasaka 02/04
1
Estou falando de coisas função identidade da biblioteca padrão Haskell - Eu não acho que você pode obter mais "tautológico" então que :)
hugomg
1
@missingno Bah, isso é trapaça: D
Rei Miyasaka
5
Se você nomear as funções pelo objetivo, e não pelo conteúdo, elas imediatamente deixarão de ser tolas. Portanto, seus exemplos podem ser, por exemplo, ser function nametoolong() { return name.size > 15; }ou. function successorIndex(x) { return x + 1; } O problema com suas funções é, na verdade, apenas que o nome delas é ruim.
Hans-Peter Störr
14

Eu diria que, se você acha que a intenção de algum código pode ser aprimorada adicionando um comentário, em vez de adicionar esse comentário, extraia o código em seu próprio método. Não importa o tamanho do código.

Por exemplo, se o seu código for parecido com:

if x == 1 { ... } // is pixel on?

faça com que seja assim:

if pixelOn() { ... }

com

function pixelOn() { return x == 1; }

Ou, em outras palavras, não é sobre o tamanho do método, mas sobre o código de auto-documentação.

Julio
fonte
5
Meu estimado colega salienta que você também pode escrever if x == PIXEL_ON. Usar uma constante pode ser tão descritivo quanto usar um método e é um pouco mais breve.
Tom Anderson
7

Eu acho que isso é exatamente o que você quer fazer. No momento, essa função pode ter apenas uma ou duas linhas, mas com o tempo ela pode crescer. Também ter mais chamadas de função permite ler as chamadas de função e entender o que está acontecendo lá dentro. Isso torna seu código muito seco (não se repita), que é muito mais sustentável.

mpenrow
fonte
4
Então, o que há de errado em fatorá-lo mais tarde, quando você pode provar que precisa, em vez de agora, quando é apenas um peso morto?
dsimcha
As funções não crescem por conta própria. IMHO os exemplos são ruins. conditionMeté um nome muito genérico e não aceita argumentos, por isso testa algum estado? (x == xCondition) é, na maioria dos idiomas e situações, tão expressivo quanto 'xConditition'.
usuário desconhecido
Sim, e é por isso que você deseja ter mais de 75% de sobrecarga no seu código? O revestimento simples, escrito como 3 linhas, é na verdade 300%.
Coder
5

Concordo com todos os outros posts que vi. Este é um bom estilo.

A sobrecarga de um método tão pequeno pode ser nula, pois o otimizador pode otimizar a ligação e alinhar o código. Um código simples como esse permite que o otimizador faça seu melhor trabalho.

O código deve ser escrito para maior clareza e simplicidade. Eu tento limitar um método a uma das duas funções: tomar decisões; ou realizando trabalho. Isso pode gerar métodos de uma linha. Quanto melhor eu estou fazendo isso, melhor eu acho o meu código.

Código como este tende a ter alta coesão e baixo acoplamento, o que é uma boa prática de codificação.

EDIT: Uma nota sobre os nomes dos métodos. Use um nome de método que indique o que o método não faz e como faz. Acho verb_noun (_modifier) ​​é um bom esquema de nomenclatura. Isso fornece nomes como Find_Customer_ByName em vez de Select_Customer_Using_NameIdx. O segundo caso pode ficar incorreto quando o método é modificado. No primeiro caso, você pode trocar toda a implementação do banco de dados do Cliente.

BillThor
fonte
+1 por mencionar inlining, na consideração principal em desempenho e funções curtas.
perfil completo de Garet Claborn
4

A refatoração de uma linha de código em uma função parece excessiva. Pode haver casos excepcionais, como ver muitoooooongo / cumprimento de linhas ou expessões, mas eu não faria isso a menos que saiba que a função aumentará no futuro.

e seu primeiro exemplo sugere o uso de globais (que podem ou não falar de outros problemas no código), refatoraria ainda mais e tornaria essas duas variáveis ​​como parâmetros:

function conditionMet(x, condition){
   return x == condition;
}
....
conditionMet(1,(3-2));
conditionMet("abc","abc");

O conditionMetexemplo pode ser útil se a condição for longa e repetitiva, como:

function conditionMet(x, someObject){
   return x == ((someObject.valA + someObject.valB - 15.4) / /*...whole bunch of other stuff...*/);
}
FrustratedWithFormsDesigner
fonte
1
Seu primeiro exemplo não sugere globais. Na verdade, é um método coeso em uma classe altamente coesa, na qual a maioria das variáveis ​​está no objeto.
Martin Blore
7
Essa conditionMetfunção é apenas um ==operador detalhado . Provavelmente, isso não é útil.
1
Definitivamente não uso globals. @MeshMan, é exatamente de onde o exemplo é ... um método em uma classe.
27668 Mark
1
@ Mark Brown: @MeshMan: Ok, eu acho que o exemplo de código era demasiado vago para saber com certeza ...
FrustratedWithFormsDesigner
Estou cheirando um conditionMet (x, relation condition) {aqui, onde você passa x, '==' e relação. Então você não precisa repetir o código para '<', '>', '<=', '! =' E assim por diante. Por outro lado - a maioria das linguagens tem essas construções incorporadas à medida que os operadores (condição x ==) fazem exatamente isso. Funções para instruções atômicas estão um passo longe demais.
usuário desconhecido
3

Considere isto:

Uma simples função de detecção de colisão:

bool collide(OBJ a, OBJ b)
{
    return(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) <= pow(a.radius + b.radius, 2));
}

Se você escreveu esse liner "simples" em seu código o tempo todo, pode cometer um erro. Além disso, seria realmente torturante escrever isso várias vezes.

muntoo
fonte
Se estamos lidando com C aqui, nós poderíamos apenas abuso #define;)
Cole Johnson
Você pode até querer trocar isso para o mais lento, mas estouro prova de hypot se os seus tamanhos ou distâncias tornam-se muito grandes. Obviamente, isso é muito mais fácil de fazer uma vez.
Matt Krause
2

Não, e isso raramente é um problema. Agora, se alguém sente que nenhuma função deve ter mais de uma linha de código (se pudesse ser assim tão simples), isso seria um problema e, de certa forma, preguiçoso, porque eles não estão pensando no que é apropriado.

JeffO
fonte
Eu não contaria isso em linhas de código, mas em expressões. "(x == condition)" é atômico, portanto, eu o colocaria apenas em um método / função, se for usado várias vezes E puder ser alterado, como function isAdult () = { age >= 18; }mas certamente não isAtLeast18.
usuário desconhecido
2

Eu diria que eles são muito curtos, mas esta é a minha opinião subjetiva.

Porque:

  • Não há razão para criar uma função se ela for usada apenas uma ou duas vezes. Saltar para defs é péssimo. Especialmente com códigos VS e C ++ incrivelmente rápidos.
  • Visão geral da aula. Quando você tem milhares de pequenas funções, isso me deixa com raiva. Gosto de ver as definições das classes e ver rapidamente o que elas fazem, não como SetXToOne, SetYToVector3, MultiplyNumbers, + 100 setters / getters.
  • Na maioria dos projetos, esses auxiliares perdem peso após uma ou duas fases de refatoração e, em seguida, você "pesquisa todos" -> exclui para se livrar do código obsoleto, geralmente ~ 25% + dele.

Funções longas são ruins, mas funções menores que 3 linhas e executam apenas uma coisa são IMHO igualmente ruins.

Então, eu diria que apenas escreva função pequena se for:

  • Mais de 3 linhas de código
  • Coisas que os desenvolvedores juniores podem perder (não sei)
  • Faz validação extra
  • É usado ou será usado pelo menos 3x
  • Simplifica a interface usada com frequência
  • Não se tornará um peso morto durante a próxima refatoração
  • Tem algum significado especial, por exemplo, especialização de modelo ou algo
  • Faz algum trabalho de isolamento - referências constantes, afeta parâmetros mutáveis, recupera membros privados

Aposto que o próximo desenvolvedor (sênior) terá coisas melhores a fazer do que lembrar de todas as suas funções SetXToOne. Então eles se transformarão em peso morto em breve, de qualquer maneira.

Codificador
fonte
1

Eu não gosto do exemplo não. 1, por causa do i-ésimo nome genérico.

conditionMetnão parece ser genérico, significa uma condição específica? Gostar

isAdult () = { 
  age >= 18 
}

Isso seria bom. É uma diferença semântica, enquanto

isAtLeast18 () { age >= 18; } 

não seria bom para mim.

Talvez seja usado com frequência e possa ser sujeito a alterações posteriores:

getPreferredIcecream () { return List ("banana", "choclate", "vanilla", "walnut") }

está bem também. Ao usá-lo várias vezes, você só precisa mudar um único local, se for necessário - talvez chantilly seja possível amanhã.

isXYZ (Foo foo) { foo.x > 15 && foo.y < foo.x * 2 }

não é atômico e deve oferecer uma boa oportunidade de teste.

Se você precisa passar uma função, é claro, passe o que quiser e escreva funções de aparência boba.

Mas, em geral, vejo muito mais funções, que são muito longas, do que funções que são muito curtas.

Uma última palavra: algumas funções parecem apropriadas, porque são escritas muito detalhadas:

function lessThan (a, b) {
  if (a < b) return true else return false; 
}

Se você vê, é o mesmo que

return (a < b); 

você não terá problemas com

localLessThan = (a < b); 

ao invés de

localLessThan = lessThan (a, b); 
Usuário desconhecido
fonte
0

Não há código como nenhum código!

Mantenha-o simples e não complique demais as coisas.

Não é ser preguiçoso, está fazendo o seu trabalho!

RDL
fonte
0

Sim, não há problema em ter uma função de código curto. No caso de métodos como "getters", "setters", "accesors" é muito comum, como as respostas anteriores mencionaram.

Às vezes, essas funções curtas de "accesors" são virtuais, porque quando substituídas nas subclasses, as funções terão mais código.

Se você deseja que sua função não seja tão curta, bem, em muitas funções, sejam elas globais ou métodos, eu geralmente uso uma variável "result" (estilo pascal) em vez de um retorno direto, é muito útil ao usar um depurador.

function int CalculateSomething() {
  int Result = -1;

   // more code, maybe, maybe not

  return Result;
}
umlcat
fonte
0

Curto demais nunca é um problema. Alguns motivos para funções curtas são:

Reutilização

Por exemplo, se você tem uma função, como um método definido, você pode afirmar que tem certeza de que os parâmetros são válidos. Essa verificação deve ser feita em qualquer lugar em que a variável estiver definida.

Manutenção

Você pode usar alguma declaração que acha que pode mudar no futuro. Por exemplo, agora você mostra um símbolo em uma coluna, mas depois isso pode mudar para outra coisa (ou até um sinal sonoro).

Uniformidade

Você está usando, por exemplo, o padrão de fachada e a única coisa que uma função faz é passar exatamente a função para outra sem alterar os argumentos.

Michel Keijzers
fonte
0

Quando você dá um nome a uma seção de código, é essencialmente para dar um nome a ela . Isso pode ser por qualquer um de vários motivos, mas o ponto crucial é se você pode atribuir um nome significativo ao seu programa. Nomes como "addOneToCounter" não adicionariam nada, mas conditionMet()sim.

Se você precisar de uma regra para descobrir se o snippet é muito curto ou muito longo, considere quanto tempo leva para encontrar um nome significativo para o snippet. Se você não puder dentro de um período de tempo razoável, o snippet não será um tamanho adequado.

user1249
fonte
0

Não, mas pode ser muito conciso.

Lembre-se: o código é escrito uma vez, mas é lido muitas vezes.

Não escreva código para o compilador. Escreva para futuros desenvolvedores que precisarão manter seu código.

Jim G.
fonte
-1

Sim querido, a função pode ser cada vez menor e se é bom ou ruim, depende da linguagem / estrutura que você está usando.

Na minha opinião, eu trabalho principalmente em Front End Technologies, as Small Functions são usadas principalmente como funções auxiliares; você provavelmente as usará muito quando estiver trabalhando com filtros pequenos e usando a mesma lógica em seu aplicativo. Se seu aplicativo tiver muita lógica comum, haverá várias funções pequenas.

Porém, em um aplicativo em que você não possui lógica comum, não será obrigado a criar pequenas funções, mas poderá dividir seu código em segmentos em que fica fácil gerenciar e entender.

Em geral, dividir seu código enorme em pequenas funções é uma abordagem muito boa. Em estruturas e linguagens modernas, você será obrigado a fazê-lo, por exemplo,

data => initScroll(data)

é uma função anônima no ES 2017 JavaScript e Typescript

getMarketSegments() {
 this.marketService.getAllSegments(this.project.id)
  .subscribe(data => this.segments = data, error => console.log(error.toString()));
}

no código acima, você pode ver 3 declarações de funções e 2 chamadas de funções. Esta é uma simples chamada de serviço no Angular 4 com texto datilografado. Você pode pensar nisso como seus requisitos

([] 0)
([x] 1)
([x y] 2)

Acima, são 3 funções anônimas na linguagem clojure

(def hello (fn [] "Hello world"))

O acima é uma declaração funcional em clojure

Portanto, sim, as FUNÇÕES podem ser menores, mas se é bom ou ruim, se você tem funções como:

incrementNumber(numb) { return ++numb; }

Bem, não é uma boa prática fazê-lo, mas e se você estiver usando esta função em uma tag HTML, como fazemos no Angular Framework, se não houver suporte para Incremento ou Decremento em Modelos HTML Angulares, essa seria a solução para mim.

Vamos dar outro exemplo

insertInArray(array, newKey) {
 if (!array.includes(newKey)) {
   array.push(newKey);
 }
}

O exemplo acima é essencial ao reproduzir quando matrizes dentro de modelos HTML angulares. Então, às vezes, você terá que criar pequenas funções

Anwaar Ulhaq
fonte
-2

Não concordo com quase a resposta dada neste momento.

Recentemente eu encontrei um colega que escreve todas as turmas da seguinte forma:

 void setProperty(int value){ mValue=value; }
 int getProperty() const { return (mValue); }

Esse poderia ser um bom código em casos esporádicos, mas certamente não se você definir muitas classes com muitas e muitas propriedades. Não quero dizer, com isso, que métodos como os mencionados acima não sejam escritos. Mas, se você acabar escrevendo a maior parte do código como "invólucro" da lógica real, há algo errado.

Provavelmente, o programador perde a lógica geral, teme mudanças futuras e refatora o código.

A definição da interface é porque uma necessidade real; de fato, se você precisar definir e obter uma propriedade simples (sem muita lógica, o que reduz o membro), isso será possível. Mas, se a necessidade real pode ser analisada de uma maneira diferente, por que não definir uma interface mais intuitiva?

Para realmente responder à pergunta, é claro que não, e a razão é muito óbvia: o método / propriedade / o que mais deve ser definido para o que precisa. Mesmo uma função virtual vazia tem um motivo para existir.

Luca
fonte
6
Há um bom motivo para adicionar métodos de acesso / mutador, que você sugere em "medo de refatoração futura ...". Mas você também tem razão em não agregar valor ao código. Nem reduzindo o tamanho (local ou globalmente) ou aumentando a legibilidade. Na minha opinião, isso se refere ao design de linguagem ruim na convenção Java e JavaBeans. Essa é uma área (de muitas) em que o C # melhorou com êxito o idioma para tratar de ambas as preocupações com a sintaxe automática de propriedades . Como programador Java, concordo com seu estilo bruto para classes básicas do tipo estrutura.
Anm
1
As funções getter / setter são boas, mesmo que tudo o que façam agora seja ler ou gravar uma variável. Por uma questão prática, você pode imaginar um cenário em que mais tarde decida imprimir um valor na tela toda vez que o campo for alterado ou verificar se esse valor é válido ou não. (Talvez seja um denominador por uma fração, e você quer verificar para se certificar de que não é zero.)
Rei Miyasaka
2
getters e setters são terríveis, apesar de seu uso válido. Se for necessário usá-los, considero uma falha do idioma.
Carson Myers
@Rei: por que uma classe externa precisaria verificar o valor dos denominadores? Isso deve ser feito pela função divide () da classe Fraction ou a classe Fraction deve fornecer um isDivisible () para verificar se há denominadores nulos. Os getters / setters necessários geralmente são um cheiro de código que sua classe tem alto acoplamento e / ou baixa coesão (ou seja, ruim).
Lie Ryan
@Lie What? Eu nunca disse que uma classe externa deveria ser usada para verificar denominadores. Estou dizendo que uma classe externa pode definir um denominador para 0 por acidente. O objetivo de realizar verificações de validade nos levantadores é incentivar quaisquer bugs no código do consumidor a serem encontrados anteriormente. Fornecer uma função isDivisible () que pode ou não ser chamada também não funciona para esse fim. E como exatamente a necessidade de getters / setters indica que há um acoplamento alto?
Rei Miyasaka