Existe algo como ter muitas funções / métodos privados?

61

Eu entendo a importância de um código bem documentado. Mas também entendo a importância do código auto-documentável . Quanto mais fácil for ler visualmente uma função específica, mais rápido poderemos avançar durante a manutenção do software.

Com isso dito, gosto de separar as funções big em outras menores. Mas eu faço isso a um ponto em que uma classe pode ter mais de cinco deles apenas para servir um método público. Agora multiplique cinco métodos privados por cinco públicos, e você terá em torno de vinte e cinco métodos ocultos que provavelmente serão chamados apenas uma vez por esses públicos.

Claro, agora é mais fácil ler esses métodos públicos, mas não posso deixar de pensar que ter muitas funções é uma prática ruim.

[Editar]

As pessoas têm me perguntado porque eu acho que ter muitas funções é uma prática ruim.

A resposta simples: é um pressentimento.

Minha crença não é, por um lado, apoiada por qualquer hora de experiência em engenharia de software. É apenas uma incerteza que me deu um "bloqueio de escritor", mas para um programador.

No passado, eu só estava programando projetos pessoais. Apenas recentemente eu mudei para projetos baseados em equipes. Agora, quero garantir que outras pessoas possam ler e entender meu código.

Eu não sabia o que melhoraria a legibilidade. Por um lado, eu estava pensando em separar uma grande função em outra grande com nomes inteligíveis. Mas havia outro lado meu dizendo que é apenas redundante.

Então, estou pedindo para que eu me ilumine para escolher o caminho correto.

[Editar]

Abaixo, incluí duas versões de como eu poderia resolver meu problema. O primeiro resolve por não separar grandes pedaços de código. O segundo faz separar as coisas.

Primeira versão:

public static int Main()
{
    // Displays the menu.
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

Segunda versão:

public static int Main()
{
    DisplayMenu();
}

private static void DisplayMenu()
{
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

Nos exemplos acima, o último chama uma função que será usada apenas uma vez durante todo o tempo de execução do programa.

Observação: o código acima é generalizado, mas é da mesma natureza do meu problema.

Agora, aqui está a minha pergunta: qual deles? Eu escolho o primeiro ou o segundo?

    
por skizeey 14.02.2011 / 00:26
fonte

10 respostas

32

Now multiply five private methods by five public ones, and you get around twenty-five hidden methods that are probably going to be called only once by those public ones.

Isso é conhecido como Encapsulation , que cria um Controle Abstração no nível superior. Isso é bom.

Isso significa que qualquer pessoa que leia seu código, quando chegar ao método startTheEngine() em seu código, poderá ignorar todos os detalhes de nível inferior, como openIgnitionModule() , turnDistributorMotor() , sendSparksToSparkPlugs() , injectFuelIntoCylinders() , activateStarterSolenoid() e todas as outras funções complexas e pequenas que devem ser executadas para facilitar a função muito maior e mais abstrata de startTheEngine() .

A menos que o problema com o qual você está lidando em seu código lide diretamente com um desses componentes, os mantenedores de código podem seguir em frente, ignorando a funcionalidade encapsulada em área restrita.

Isso também tem a vantagem de tornar seu código mais fácil de testar. . Por exemplo, posso escrever um caso de teste para turnAlternatorMotor(int revolutionRate) e testar sua funcionalidade completamente independente dos outros sistemas. Se houver um problema com essa função e a saída não for o que eu esperava, então sei qual é o problema.

Código que não está dividido em componentes é muito mais difícil de testar. De repente, seus mantenedores estão apenas olhando para a abstração em vez de serem capazes de se aprofundar em componentes mensuráveis.

Meu conselho é continuar fazendo o que você está fazendo, pois seu código será dimensionado, será de fácil manutenção e poderá ser usado e atualizado nos próximos anos.

    
por 14.02.2011 / 05:10
fonte
21

Sim e não. O princípio fundamental é: um método deve fazer uma coisa e apenas uma coisa

É correto "dividir" seu método em métodos menores. Então, novamente, esses métodos devem otimamente ser genéricos o bastante para não servirem somente àquele método "grande", mas serem reutilizáveis em outros lugares. Em alguns casos, um método seguirá uma estrutura de árvore simples, como um Initialize Method que chama InitializePlugins, InitializeInterface, etc.

Se você tem um método / classe realmente grande, geralmente é um sinal de que está fazendo muito e precisa refatorar para quebrar o "blob". Perphaps escondem alguma complexidade em outra classe sob uma abstração, e usam a injeção de dependência

    
por 14.02.2011 / 00:40
fonte
16

Eu acho que, em geral, é melhor errar do lado de muitas funções do que de poucas. As duas exceções a essa regra que vi na prática são para o DRY e YAGNI Se você tem muitas funções quase idênticas, você deve combiná-las e usar parâmetros para evitar se repetir. Você também pode ter muitas funções se você as criou "apenas no caso" e elas não estão sendo usadas. Não vejo absolutamente nada de errado em ter uma função que é usada apenas uma vez se adicionar legibilidade e facilidade de manutenção.

    
por 14.02.2011 / 04:16
fonte
10

A ótima resposta do jmort253 me inspirou a seguir com uma resposta "sim, mas" ...

Ter muitos pequenos métodos privados não é uma coisa ruim, mas preste atenção ao sentimento de que você está fazendo uma pergunta aqui :). Se você chegar a um ponto em que está escrevendo testes que são focados apenas em métodos privados (seja chamando-os diretamente ou configurando um cenário de tal forma que um seja chamado de certa maneira apenas para que você possa testar o resultado), você deveria dar um passo atrás.

O que você pode ter é uma nova classe com sua própria interface pública mais focada tentando escapar. Nesse ponto, talvez você queira pensar em extrair uma classe para encapsular essa parte da funcionalidade de classes existente que está atualmente no método privado. Agora sua classe original pode usar sua nova classe como uma dependência, e você pode escrever testes mais focados diretamente contra essa classe.

    
por 14.02.2011 / 09:14
fonte
8

Quase todos os projetos OO que eu já participei sofreram muito com classes que eram muito grandes e métodos que eram muito longos.

Quando sinto a necessidade de um comentário explicando a próxima seção do código, extraio essa seção em um método separado. No longo prazo, isso torna o código mais curto. Esses pequenos métodos são reutilizados mais do que você esperaria inicialmente. Você começa a ver oportunidades de coletar um monte deles em uma aula separada. Logo você está pensando sobre o seu problema em um nível mais alto, e todo o esforço vai muito mais rápido. Novos recursos são mais fáceis de escrever, porque você pode construir sobre as pequenas classes que você criou a partir desses pequenos métodos.

    
por 15.02.2011 / 00:09
fonte
7

Uma turma com 5 métodos públicos e 25 métodos privados não parece tão grande para mim. Apenas certifique-se de que suas turmas tenham responsabilidades bem definidas e não se preocupe muito com o número de métodos.

Dito isso, esses métodos privados devem se concentrar em um aspecto específico de toda a tarefa, mas não em uma maneira "doSomethingPart1", "doSomethingPart2". Você não ganha nada se esses métodos privados forem apenas pedaços de uma longa história arbitrariamente dividida, cada um deles sem sentido fora do contexto todo.

    
por 14.02.2011 / 10:15
fonte
4

Trecho do código limpo de R. Martin (p. 176):

Even concepts as fundamental as elimination of duplication, code expressiveness, and the SRP can be taken too far. In an effort to make our classes and methods small, we might create too many tiny classes and methods. So this rule [minimize the number of classes and methods] suggests that we also keep our function and class counts low. High class and method counts are sometimes the result of pointless dogmatism.

    
por 02.09.2016 / 18:26
fonte
3

Algumas opções:

  1. Tudo bem. Apenas nomeie os métodos privados e nomeie seus métodos públicos. E nomeie bem seus métodos públicos.

  2. Resolva alguns desses métodos auxiliares em classes auxiliares ou módulos auxiliares. E certifique-se de que essas classes / módulos auxiliares sejam bem nomeadas e sejam abstrações sólidas em si mesmas.

por 14.02.2011 / 00:31
fonte
1

Eu não acho que há sempre um problema de "muitos métodos privados" se ele se sente assim provavelmente é um sintoma de arquitetura de código pobre.

Aqui está como eu penso sobre isso ... Se a arquitetura é bem projetada, geralmente é óbvio onde o código que faz o X deve estar. É aceitável se houver algumas exceções a isso - mas elas precisam ser verdadeiramente excepcionais. Caso contrário, refatore a arquitetura para tratá-las como padrão.

Se o problema é que, ao abrir sua classe, ela está repleta de métodos privados que estão dividindo blocos maiores em partes menores de código, talvez isso seja um sintoma de falta de arquitetura. Em vez de classes e arquitetura, essa área de código foi implementada de maneira processual dentro de uma classe.

Encontrar um saldo aqui depende do projeto e de seus requisitos. O contra-argumento para isso é a afirmação de que um programador júnior pode derrubar a solução em 50 linhas de código que leva 50 classes a um arquiteto.

    
por 02.09.2016 / 21:13
fonte
0

Is there such a thing as having too many private functions/methods?

Sim.

No Python, o conceito de "privado" (como usado por C ++, Java e C #) não existe realmente.

Existe uma convenção de nomenclatura "privada", mas é só isso.

O modo privado pode levar a códigos difíceis de testar. Ele também pode quebrar o "Princípio Aberto-Fechado" ao tornar o código simplesmente fechado.

Consequentemente, para pessoas que usaram Python, as funções privadas não têm valor. Basta tornar tudo público e acabar com isso.

    
por 14.02.2011 / 12:10
fonte