Práctica recomendada: ¿ordenar público / protegido / privado dentro de la definición de clase?

92

Estoy comenzando un nuevo proyecto desde cero y quiero que esté limpio / tenga buenos estándares de codificación. ¿En qué orden a los desarrolladores experimentados de aquí les gusta diseñar las cosas dentro de una clase?

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

B: 1) vars públicas 2) vars privadas 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

Por lo general, me gusta colocar variables estáticas públicas en la parte superior, pero ¿se enumeraría un método estático público antes de su constructor, o el constructor siempre debería aparecer primero? Esa clase de cosas...

Sé que es delicado, pero me preguntaba: ¿cuáles son las mejores prácticas para esto?

PD: no, no uso Cc #. Lo sé. Soy ludita.

tempname
fuente
9
No hay nada de malo en no usar C #. Nunca he escrito una puntada de C # en todos mis años como desarrollador profesional. Use el lenguaje que sea apropiado para la tarea y dígale a cualquiera que diga algo diferente dónde puede ir.
Ether
1
Posible duplicado de stackoverflow.com/questions/150479/…
Michael Freidgeim

Respuestas:

143

En Código limpio , Robert C. Martin aconseja a los programadores que coloquen siempre las variables miembro en la parte superior de la clase (las constantes primero, luego los miembros privados) y los métodos deben ordenarse de tal manera que se lean como una historia que no causa que el lector tenga que saltar demasiado el código. Esta es una forma más sensata de organizar el código que mediante el modificador de acceso.

Asaf
fuente
10
También he tenido buena suerte añadiendo: getters / setters last. Me ayuda a que las clases se sientan menos voluminosas.
Dean J
5
Constructores en la parte superior, justo después de las variables miembro. En OOP, la ejecución comienza con la instanciación de objetos.
Asaph
6
Hacer que el lector salte demasiado el código probablemente deba equilibrarse con obligar al lector a leer todos los detalles esenciales de los métodos privados. La metáfora del periódico probablemente se malinterpreta en el sentido de que sus métodos públicos deben representar ampliamente lo que hace su clase y sus métodos privados proporcionan los detalles (casi como una nota a pie de página a la que puede consultar si es necesario).
Kenny Hung
1
Estoy confundido. Dijiste: (constantes primero, luego miembros privados) . OKAY. ¿A dónde van entonces los miembros del público?
Miel
1
@Honey Iban directamente tras las constantes y los miembros privados. Entonces eso estaría en el siguiente orden: constantes, miembros privados, miembros públicos.
Pierre Gillet
48

La mejor práctica es ser coherente .

Personalmente, prefiero poner los publicmétodos primero, seguidos de los protectedmétodos, seguidos de los privatemétodos. En general, los datos de los miembros siempre deben ser privados o estar protegidos, a menos que tenga una buena razón para que no sea así.

Mi razón para poner los publicmétodos en la parte superior es que define la interfaz para su clase, por lo que cualquier persona que lea detenidamente su archivo de encabezado debería poder ver esta información de inmediato.

En general, los miembros privatey protectedson menos importantes para la mayoría de las personas que miran el archivo de encabezado, a menos que estén considerando modificar los aspectos internos de la clase. Mantenerlos "fuera del camino" asegura que esta información se mantenga solo cuando sea necesario , uno de los aspectos más importantes de la encapsulación.

Leopardopielpíldoracajasombrero
fuente
LeopardSkikPBH, estoy totalmente de acuerdo ... ¡eso tiene sentido! Supongo que he estado confundido en cuanto a si dentro de eso, var o funcs tienen prioridad. ¡Gracias!
tempname
11
No estoy de acuerdo con que la mejor práctica sea ser coherente. Hay muchas formas de escribir código ilegible e inmaterial de forma coherente.
Jason
3
@Jason es como decir que no es una buena práctica permanecer en su lado de la carretera porque aún puede tener accidentes allí.
Rex M
1
@Jason - Quizás debería haber sido más claro. En este caso particular, bastante subjetivo (ordenamiento de métodos), creo que la mejor práctica es ser coherente. Todos tendrán opiniones sobre la mejor manera de ordenar las cosas, pero si eres consistente por naturaleza, debería ser bastante fácil de mantener. Estoy de acuerdo en que "ser coherente" no siempre es la mejor práctica para todas las áreas del código, especialmente cuando se considera la mala calidad del código con la que a menudo se tiene que lidiar.
LeopardSkinPillBoxHat
4
@Rex M: No, lo que dije no se parece en nada a tu interpretación. Mi punto es que el mero hecho de ser coherente no es un argumento sólido en este caso. En algunos casos, la consistencia está bien (p. Ej., Colocación de aparatos ortopédicos). Pero las opciones aquí realmente afectan la legibilidad del código. Por tanto, se necesita un argumento más fuerte que la coherencia.
Jason
8

Creo que tengo una filosofía diferente a la de la mayoría. Prefiero agrupar elementos relacionados. No soporto tener que saltar para trabajar con una clase. El código debería fluir y usar un orden bastante artificial basado en la accesibilidad (pública, privada, protegida, etc.) o instancia versus estática o miembro versus propiedad versus función no ayuda a mantener un buen flujo. Entonces, si tengo un método público Methodimplementado por métodos auxiliares privados HelperMethodA, HelperMethodBetc. , entonces, en lugar de tener estos métodos muy separados entre sí en el archivo, los mantendré cerca uno del otro. De manera similar, si tengo un método de instancia que se implementa mediante un método estático, los agruparé también.

Entonces, mis clases a menudo se ven así:

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
fuente
8

Personalmente me gusta tener público arriba, protegido y luego privado. La razón de esto es que cuando alguien abre el encabezado, primero ve a lo que puede acceder, luego más detalles a medida que se desplaza hacia abajo.

Uno no debería tener que mirar los detalles de implementación de una clase para poder usarla, entonces el diseño de la clase no está bien hecho.

AndersK
fuente
3

Solía ​​preocuparme mucho. En los últimos años, usando IDE modernos, prácticamente todo está a solo 1 o 2 pulsaciones de teclas, he dejado que mis estándares se relajen sustancialmente. Ahora, empiezo con estática, variables miembro, luego constructores, después de eso no me preocupo mucho por eso.

En C #, dejo que Resharper organice las cosas automáticamente.

ScottS
fuente
Estoy de acuerdo. Mi modo normal de navegar por los miembros en un archivo es usar una herramienta integrada en cualquier IDE o editor que esté usando. La agrupación real de los miembros pasa a ser secundaria. Sin embargo, estoy de acuerdo en que los miembros deben agruparse para evitar un orden aleatorio puro, y utilizo resharper para agrupar y ordenar automáticamente.
Phillip Ngan
2

Este sería mi pedido

  1. Variables estáticas
  2. Métodos estáticos
  3. Variables públicas
  4. Variables protegidas
  5. Variables privadas
  6. Constructores
  7. Métodos públicos
  8. Métodos protegidos
  9. Métodos privados

Utilizo las siguientes reglas:

  • estático antes que nada
  • variables antes que constructores antes que métodos (considero que los constructores están en la categoría de métodos)
  • público antes que protegido antes que privado

La idea es que defina el objeto (los datos), antes que los comportamientos (métodos). Las estáticas deben separarse porque en realidad no forman parte del objeto ni de su comportamiento.

barkmadley
fuente
gracias barkmadley ... eso es interesante! que pondrías 4 y 5 antes del constructor. Definitivamente pensaré en eso
temporal
Me gusta este orden, aunque es interesante tener métodos estáticos cerca de la parte superior. Trabajé con un desarrollador que puso variables privadas en la parte inferior, pude ver la idea pero no me sentía bien
Carlton
2

En general, estoy de acuerdo con el orden público, protegido y privado, así como con el orden de datos estáticos, datos de miembros y funciones de miembros.

Aunque a veces agrupo miembros similares (captadores y establecedores), generalmente prefiero enumerar a los miembros dentro de un grupo ALFABÉTICAMENTE para que puedan ubicarse más fácilmente.

También me gusta alinear los datos / funciones verticalmente. Hago tabulación / espacio hacia la derecha lo suficiente para que todos los nombres estén alineados en la misma columna.

AlanKley
fuente
1
¡Oye, un 'espaciador de pestañas' según mi propio corazón! :-) No soy obsesivo compulsivo. ¡Honestamente no lo soy!
tempname
1

Para cada uno lo suyo, y como dice Elzo, los IDE modernos han facilitado la búsqueda de miembros y sus modificadores de una manera fácil con íconos de colores en menús desplegables y demás.

Mi opinión es que es más importante para el programador saber para qué fue diseñada la clase y cómo se puede esperar que se comporte.

Entonces, si es un Singleton, primero pongo la semántica (clase estática getInstance ()).

Si es una fábrica de hormigón, primero coloco la función getNew () y las funciones registrar / inicializar.

... y así. Cuando digo primero, me refiero poco después de c'tors y d'tor, ya que son la forma predeterminada de instanciar cualquier clase.

Las funciones que siguen están entonces en:

  1. orden lógico de llamadas (por ejemplo, initialize (), preProcess (), process (), postProcess ()), o
  2. funciones relacionadas juntas (como accesores, utilidades, manipuladores, etc.),

dependiendo de si la clase estaba destinada principalmente a ser un almacén de datos con algunas funciones o un proveedor de funciones con algunos miembros de datos.

zorro
fuente
0

Algunos editores, como Eclipse y sus descendientes, le permiten reordenar en la vista de esquema las vars y los métodos, alfabéticamente o como en la página.

Elzo Valugi
fuente
0

La secuencia de público seguido de protegido y privado es más legible para mí. Es mejor describir la lógica de la clase en los comentarios en la parte superior del archivo de encabezado de manera simple y las órdenes de llamada de función para comprender qué dosis de clase y algoritmos se usan en el interior.

Estoy usando Qt c ++ por un tiempo y veo un nuevo tipo de palabras clave como signaly slotprefiero seguir ordenando como arriba y compartir mi idea con ustedes aquí.

#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
fuente