Prática recomendada: ordenação de público / protegido / privado dentro da definição de classe?

92

Estou começando um novo projeto do zero e quero que seja limpo / tenha bons padrões de codificação. Em que ordem os desenvolvedores experientes gostam de definir as coisas em uma classe?

A: 1) métodos públicos 2) métodos privados 3) vars públicos 4) vars privados

B: 1) vars públicos 2) vars privados 3) métodos públicos 4) métodos privados

C: 1) vars públicas 2) métodos públicos 3) métodos privados 4) vars privadas

Eu geralmente gosto de colocar vars estáticos públicos no topo, mas então um método estático público seria listado antes do seu construtor, ou o construtor deveria sempre ser listado primeiro? Esse tipo de coisas...

Eu sei que é mimado, mas eu só me perguntei: quais são as melhores práticas para isso?

PS: não, eu não uso Cc #. Eu sei. Eu sou um idiota.

nome temporário
fonte
9
Não há nada de errado em não usar C #. Nunca escrevi um ponto sobre C # em todos os meus anos como desenvolvedor profissional. Use qualquer linguagem apropriada para a tarefa e diga a qualquer pessoa que diga algo diferente onde eles podem enfiá-la!
Ether
1
Possível duplicata de stackoverflow.com/questions/150479/…
Michael Freidgeim

Respostas:

142

Em Clean Code , Robert C. Martin aconselha os programadores a sempre colocar as variáveis ​​de membro no topo da classe (constantes primeiro, depois membros privados) e os métodos devem ser ordenados de forma que pareçam uma história que não causa o leitor precisa pular muito o código. Esta é uma maneira mais sensata de organizar o código do que por modificador de acesso.

Asaph
fonte
10
Também tive sorte ao adicionar: getters / setters last. Isso ajuda as aulas a parecerem menos pesadas, para mim.
Dean J
5
Construtores na parte superior, logo após as variáveis ​​de membro. Em OOP, a execução começa com a instanciação do objeto.
Asaph
6
Provavelmente, fazer o leitor pular muito pelo código precisa ser balanceado com forçar o leitor a ler todos os detalhes essenciais dos métodos privados. A metáfora do jornal provavelmente é mal compreendida, pois seus métodos públicos devem representar amplamente o que sua classe faz, e seus métodos privados fornecem os detalhes (quase como uma nota de rodapé que você pode consultar se precisar).
Kenny Hung
1
Estou confuso. Você disse: (constantes primeiro, depois membros privados) . ESTÁ BEM. Para onde vão os membros públicos?
Honey
1
@Honey Eles iriam logo atrás das constantes e dos membros privados. Então isso seria na seguinte ordem: Constantes, membros privados, membros públicos.
Pierre Gillet
48

A melhor prática é ser consistente .

Pessoalmente, prefiro colocar public métodos primeiro, seguidos dos protectedmétodos, depois dos privatemétodos. Os dados dos membros devem, em geral, ser sempre privados ou protegidos, a menos que você tenha uma boa razão para não ser.

Minha justificativa para colocar os publicmétodos no topo é que ele define a interface para sua classe, portanto, qualquer pessoa que ler seu arquivo de cabeçalho deve ser capaz de ver essas informações imediatamente.

Em geral, os membros privatee protectedsão menos importantes para a maioria das pessoas que examinam o arquivo de cabeçalho, a menos que estejam considerando modificar as partes internas da classe. Mantê-los "fora do caminho" garante que essas informações sejam mantidas apenas com base na necessidade de conhecimento , um dos aspectos mais importantes do encapsulamento.

LeopardSkinPillBoxHat
fonte
LeopardSkikPBH, concordo totalmente ... isso faz sentido! Eu acho que fiquei confuso se dentro disso, var ou funcs têm precedência. Obrigado!
tempname de
11
Não concordo que a melhor prática seja ser consistente. Há muitas maneiras de escrever código ilegível e não manutenível de maneira consistente.
Jason
3
@Jason é como dizer que não é uma boa prática ficar do seu lado da estrada porque você ainda pode ter acidentes lá.
Rex M
1
@Jason - Talvez eu devesse ter sido mais claro. Neste caso particular, bastante subjetivo (ordenação de métodos), acho que a melhor prática é ser consistente. Todos terão opiniões sobre a melhor maneira de ordenar as coisas, mas se você for consistente por natureza, isso deve ser razoavelmente sustentável. Eu concordo que "ser consistente" nem sempre é a melhor prática para todas as áreas do código, especialmente quando você considera a baixa qualidade do código com a qual geralmente precisa lidar.
LeopardSkinPillBoxHat
4
@Rex M: Não, o que eu disse não tem nada a ver com a sua interpretação. Meu ponto é que simplesmente ser consistente não é um argumento forte neste caso. Para alguns casos, a consistência é adequada (por exemplo, colocação de colchetes). Mas as escolhas aqui realmente afetam a legibilidade do código. Assim, um argumento mais forte do que consistência é necessário.
jason de
8

Acho que tenho uma filosofia diferente sobre isso da maioria. Prefiro agrupar itens relacionados. Eu não suporto ter que pular para trabalhar com uma classe. O código deve fluir e usar uma ordem um tanto artificial com base na acessibilidade (pública, privada, protegida etc.) ou instância versus estática ou membro versus propriedade versus função não ajuda a manter um bom fluxo. Então, se eu tiver um método público Methodque é implementado por métodos auxiliares privados HelperMethodA,HelperMethodB etc, então ao invés de ter estes método muito afastados uns dos outros no arquivo, vou mantê-los próximos uns dos outros. Da mesma forma, se eu tiver um método de instância que é implementado por um método estático, vou agrupá-los também.

Então, minhas aulas costumam ser assim:

class MyClass {
    public string Method(int a) {
        return HelperMethodA(a) + HelperMethodB(this.SomeStringMember);
    }

    string HelperMethodA(int a) { // returns some string }

    string HelperMethodB(string s) { // returns some string }

    public bool Equals(MyClass other) { return MyClass.Equals(this, other); }

    public static bool Equals(MyClass left, MyClass right) { // return some bool }

    public double SomeCalculation(double x, double y) {
        if(x < 0) throw new ArgumentOutOfRangeException("x");
        return DoSomeCalculation(x, y); 
    }

    const double aConstant;
    const double anotherConstant;
    double DoSomeCalculation(double x, double y) {
        return Math.Pow(aConstant, x) * Math.Sin(y) 
            + this.SomeDoubleMember * anotherConstant;
    }       
}
Jason
fonte
8

Pessoalmente gosto de ter público no topo, protegido e depois privado. A razão para isso é que quando alguém abre o cabeçalho, ele vê o que pode acessar primeiro, depois mais detalhes conforme rola para baixo.

Não se deve ter que olhar os detalhes de implementação de uma classe para usá-la, então o design da classe não é bem feito.

AndersK
fonte
3

Eu costumava me importar muito. Nos últimos anos, usando IDEs modernos, praticamente tudo está a apenas 1 ou 2 toques de tecla, eu deixei meus padrões relaxarem substancialmente. Agora, eu começo com estática, variáveis ​​de membro e, em seguida, construtores, depois disso, não me preocupo muito com isso.

Em C #, eu deixo o Resharper organizar as coisas automaticamente.

ScottS
fonte
Concordo. Meu modo normal de navegar pelos membros em um arquivo é usar uma ferramenta embutida em qualquer IDE ou editor que estou usando. O agrupamento real dos membros torna-se secundário. No entanto, concordo que os membros devem ser agrupados para evitar a ordenação puramente aleatória e uso o resharper para fazer o agrupamento e a ordenação automaticamente.
Phillip Ngan
2

Este seria o meu pedido

  1. Variáveis ​​Estáticas
  2. Métodos estáticos
  3. Variáveis ​​Públicas
  4. Variáveis ​​Protegidas
  5. Variáveis ​​Privadas
  6. Construtores
  7. Métodos Públicos
  8. Métodos Protegidos
  9. Métodos Privados

Eu uso as seguintes regras:

  • estático antes de qualquer coisa
  • variáveis ​​antes dos construtores antes dos métodos (considero que os construtores estão na categoria dos métodos)
  • público antes protegido antes de privado

A ideia é que você defina o objeto (os dados), antes dos comportamentos (métodos). A estática precisa ser separada porque não faz parte do objeto, nem de seu comportamento.

Barkmadley
fonte
obrigado barkmadley ... isso é interessante! que você colocaria 4 e 5 antes do construtor. Com certeza vou pensar sobre isso
tempname
Como essa ordem, embora ter métodos estáticos próximos ao topo seja interessante. Trabalhei com um desenvolvedor que colocava variáveis ​​privadas na parte inferior, pude ver a ideia, mas não parecia certo
Carlton
2

Eu geralmente concordo com a ordem pública, protegida e privada, bem como com os dados estáticos, dados de membro, ordem de funções de membro.

Embora às vezes eu agrupe como membros (getters e setters), geralmente prefiro listar membros dentro de um grupo ALFABETICAMENTE para que eles possam ser localizados mais facilmente.

Também gosto de alinhar os dados / funções verticalmente. Eu tabulo / espaço para a direita o suficiente para que todos os nomes sejam alinhados na mesma coluna.

AlanKley
fonte
1
Ei - um 'tab-espaçador' segundo o meu próprio coração! :-) Não sou obsessivo-compulsivo. Sinceramente, não!
tempname de
1

Cada um com o seu, e como diz Elzo, IDEs modernos tornaram mais fácil encontrar membros e seus modificadores com ícones coloridos em menus suspensos e outros.

Minha opinião é que é mais importante para o programador saber para que a classe foi projetada e como se espera que ela se comporte.

Portanto, se for um Singleton, coloco a semântica (classe getInstance () estática) primeiro.

Se for uma fábrica concreta, coloco a função getNew () e as funções de registro / inicialização primeiro.

... e assim por diante. Quando digo primeiro, quero dizer logo depois dos c'tors e d'tor - uma vez que são a forma padrão de instanciar qualquer classe.

As funções a seguir estão em:

  1. ordem de chamada lógica (por exemplo, initialize (), preProcess (), process (), postProcess ()), ou
  2. funções relacionadas juntas (como acessadores, utilitários, manipuladores etc),

dependendo se a classe se destina principalmente a ser um armazenamento de dados com algumas funções ou provedor de função com alguns membros de dados.

Raposa
fonte
0

Alguns editores, como o Eclipse e seus descendentes, permitem que você reordene na visão geral os vars e os métodos, em ordem alfabética ou na página.

Elzo Valugi
fonte
0

A sequência de public seguido por protected e private é mais legível para mim. É melhor descrever a lógica da classe em comentários no topo do arquivo de cabeçalho de forma simples e ordens de chamada de função para entender o que uma dose de classe e algoritmos usados ​​dentro.

Estou usando Qt c ++ por um tempo e vejo alguns novos tipos de palavras-chave como signale slotprefiro continuar ordenando como acima e compartilhar minha ideia com você aqui.

#ifndef TEMPLATE_H
#define TEMPLATE_H


class ClassName
{
    Q_OBJECT
    Q_PROPERTY(qreal startValue READ startValue WRITE setStartValue)
    Q_ENUMS(MyEnum)

public:

    enum MyEnum {
        Hello = 0x0,
        World = 0x1
    };

    // constructors

    explicit ClassName(QObject *parent = Q_NULLPTR);
    ~ClassName();

    // getter and setters of member variables

    // public functions (normal & virtual) -> orderby logic

public slots:

signals:

protected:

    // protected functions it's rule followed like public functions


private slots:

private:

    // methods

    // members

};

#endif // TEMPLATE_H
Saeed
fonte