Em qualquer definição de classe, vi as definições de método ordenadas de várias maneiras: alfabética, cronológica com base no uso mais comum, alfabética agrupada por visibilidade, alfabética com getters e setters agrupados etc. Quando eu começo a escrever uma nova classe, Costumo digitar tudo e depois reordenar quando terminar de escrever a turma inteira. Nessa nota, tenho três perguntas:
- A ordem importa?
- Existe uma "melhor" ordem?
- Suponho que não, então quais são os prós e os contras das diferentes estratégias de pedidos?
code-quality
Johntron
fonte
fonte
Respostas:
Em algumas linguagens de programação, a ordem importa porque você não pode utilizar as coisas até que elas tenham sido declaradas. Mas, exceto para a maioria dos idiomas, isso não importa para o compilador. Então, você fica com isso importando para os humanos.
Minha citação favorita de Martin Fowler é:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
Então, eu diria que a ordem de sua classe deve depender do que facilita a compreensão pelos seres humanos.Pessoalmente, prefiro o tratamento que Bob Martin dá em seu
Clean Code
livro. Variáveis de membro na parte superior da classe, construtores e todos os outros métodos. E você ordena que os métodos sejam próximos da maneira como são usados na classe (em vez de colocar arbitrariamente todo público, depois privado e depois protegido). Ele chama isso de minimizar a "distância vertical" ou algo assim (não tenho o livro comigo no momento).Editar:
A idéia básica da "distância vertical" é que você deseja evitar que as pessoas pulem ao redor do seu código-fonte apenas para entendê-lo. Se as coisas estiverem relacionadas, elas devem estar mais próximas. Coisas não relacionadas podem estar mais afastadas.
O Capítulo 5 do Código Limpo (ótimo livro, btw) entra em vários detalhes sobre como o Sr. Martin sugere o pedido de código. Ele sugere que a leitura do código funcione como a leitura de um artigo de jornal: os detalhes de alto nível vêm primeiro (na parte superior) e você obtém mais detalhes à medida que lê. Ele diz: "Se uma função chama outra, elas devem estar verticalmente próximas e o chamador deve estar acima do chamado, se possível". Além disso, os conceitos relacionados devem estar próximos.
Então, aqui está um exemplo artificial que é ruim de várias maneiras (design pobre de OO; nunca use
double
por dinheiro), mas ilustra a idéia:Os métodos são ordenados para que sejam próximos aos que os chamam, descendo de cima para baixo. Se tivéssemos colocado todos os
private
métodos abaixopublic
desses, você teria que fazer mais pulos para seguir o fluxo do programa.getFirstName
egetLastName
são conceitualmente relacionados (egetEmployeeId
provavelmente também), por isso estão próximos. Poderíamos movê-los todos para o fundo, mas não gostaríamos de ver degetFirstName
cima e degetLastName
baixo.Espero que isso lhe dê a idéia básica. Se você está interessado nesse tipo de coisa, recomendo fortemente a leitura
Clean Code
.fonte
calculateBonus()
vir antesisFullTimeEmployee()
edidCompleteBonusObjectives()
?isFullTimeEmployee
edidCompleteBonusObjectives
são usados porisEligibleForBonus
forma que deveria ser verticalmente perto dele. Mas você pode se movercalculateBonus
para aproximar-se de onde é chamado. Infelizmente, como você tem funções que chamam funções, você acaba com problemas (como uma função compartilhada chamada por várias outras) em que não há uma ordem perfeita. Então fica a seu critério. Eu recomendo manter classes e funções pequenas para atenuar esses problemas.Geralmente, ordeno meus métodos por relação e ordem de uso.
Faça uma aula de rede, eu vou agrupar todos os métodos TCP juntos, depois todos os métodos UDP. No TCP interno, eu teria o método de instalação como o primeiro, talvez envie uma determinada mensagem em segundo e feche o soquete TCP como terceiro.
Obviamente, nem todas as classes se encaixam nesse padrão, mas esse é o meu fluxo de trabalho geral.
Faço isso dessa maneira para depurar mais do que qualquer outra coisa, quando tenho um problema e quero pular para o método, não penso como está escrito, acho o que é responsável e vou para essa seção.
Dessa forma, em particular, faz sentido para terceiros visualizar / usar seu código como agrupado e seguirá a ordem em que está sendo usado; portanto, o código que eles escreverão com sua classe seguirá a mesma estrutura que a classe.
No que diz respeito isso importa?
para legibilidade, definitivamente.
diferente disso não, apenas nos casos em que determinados idiomas você não pode chamar o método, a menos que seja definido acima onde é chamado etc.
fonte
Idealmente, suas aulas são tão pequenas que não importam. Se você possui apenas uma dúzia de métodos e seu editor ou IDE suporta dobragem, não há problema, porque a lista inteira de métodos se encaixa em 12 linhas.
Caso contrário, a distinção de nível superior deve ser pública versus privada. Liste os métodos públicos primeiro: estes são o que as pessoas mais procurarão, porque definem a maneira como sua classe interage com o restante da base de código.
Então, dentro de cada uma delas, faz mais sentido agrupar métodos por funcionalidade: construtores e destruidores em um bloco, getters / setters em outro, sobrecargas de operadores, métodos estáticos e o resto do grupo. No C ++, eu gosto de me manter
operator=
próximo dos construtores, porque está intimamente relacionado ao construtor de cópias e também porque quero poder identificar rapidamente se todos (ou nenhum) do padrão ctor, copy ctor, operator = e dtor existir.fonte
tl; dr
Somente se o idioma em que você estiver trabalhando exigir uma ordem específica. Fora isso, a encomenda é sua. Escolha um sistema que seja consistente e faça sentido e tente segui-lo o máximo possível.
Somente se o idioma em que você estiver trabalhando precisar ter uma função definida anteriormente no arquivo, onde não é chamada, como neste exemplo:
você receberá um erro porque telefonou
funcB()
antes de usá-lo. Eu acho que esse é um problema no PL / SQL e possivelmente também no C, mas você pode ter declarações avançadas como:Essa é a única situação em que consigo pensar onde, se a ordem estiver "errada", você nem será capaz de compilar.
Caso contrário, você sempre poderá reordená-los da maneira que desejar. Você provavelmente poderia até escrever uma ferramenta para fazer isso por você (se não conseguir encontrar uma por aí).
Se o idioma / ambiente não tiver requisitos para pedidos, o "melhor" é o que melhor funciona para você . Para mim, eu gosto de ter todos os getters / setters juntos, geralmente no início da classe (mas depois de construtores / inicializadores estáticos) e, em seguida, os métodos private, depois protegidos e depois públicos. Em cada grupo com base no escopo, geralmente não há pedidos, embora os métodos sobrecarregados que eu tento manter juntos, na ordem do número de parâmetros. Também tento manter métodos com funcionalidade relacionada juntos, embora às vezes precise interromper minha ordem com base no escopo; e, às vezes, tentar manter a ordem com base no escopo interrompe o grupo por funcionalidade. E meu IDE pode me fornecer uma visualização de estrutura de tópicos alfabética, o que também é bom. ;)
Alguns idiomas, como o C #, têm a capacidade de agrupar códigos em "regiões" que não têm efeito na compilação, mas podem facilitar a manutenção de funções relacionadas e, em seguida, ocultar / exibi-las com o IDE. Como MainMa apontou , há quem considere isso uma má prática. Vi bons e maus exemplos de regiões sendo usadas dessa maneira; portanto, se você for por esse caminho, tenha cuidado.
fonte