Pregunta

(Dejando de lado la pregunta en caso de tenerlos).

Siempre he preferido usar solo la sobrecarga de funciones para darle el mismo nombre tanto para el getter como para el configurador.

int rate() { return _rate; }      
void rate(int value) { _rate = value; }

// instead of     
int getRate() { return _rate; }      
void setRate(int value) { _rate = value; }

// mainly because it allows me to write the much cleaner     
total( period() * rate() );    
// instead of      
setTotal( getPeriod() * getRate() );

Naturalmente, estoy en lo cierto, pero me pregunto si los escritores de la biblioteca tuvieron alguna buena razón.

¿Fue útil?

Solución

Preferiría las versiones get / set porque es más claro en cuanto a lo que está sucediendo. Si vi rate () y rate (10), ¿cómo puedo saber que rate (10) no está simplemente usando 10 en el cálculo para devolver la tasa? No lo hago, así que ahora tengo que empezar a buscar para averiguar qué está pasando. Un solo nombre de función debe hacer una cosa, no dos cosas opuestas.

También, como otros han señalado, algunos prefieren omitir el 'get' y dejar el 'set', es decir,

int Rate( );
void SetRate( int value );

Esa convención también está bastante clara, no tendría ningún problema en leer eso.

Otros consejos

Siempre he preferido omitir el 'get' en mis getters, como lo hace usted, con rate () en lugar de getRate () . Pero la sobrecarga para el colocador no me parece una muy buena idea, ya que el nombre rate no indica que el objeto esté siendo mutado. Considera:

total(period() * rate()); // awesome, very clear

rate(20); // Looks like it computes a rate, using '20'...but for what?  And why ignore the return value?

¿Qué hay de int rate (); y void setRate (int value); ? Esto tiene la virtud de no tener dos funciones del mismo nombre haciendo cosas diferentes, y todavía permite period () * rate () .

Hace unos años, habría estado completamente de acuerdo. Más recientemente, una duda comenzó a abrirse camino, porque eso hace que tomar la dirección de un captador o setter sea ambiguo. Con herramientas como tr1 :: bind, esto es realmente molesto.

Por ejemplo:

struct A
{
   void Foo(int);
   int Foo()const;
};

std::vector<A> v = ....;
std::vector<int> foos;
// Extract Foo
std::transform(
   v.begin(), v.end(), 
   std::back_inserter(foos), 
   //Ambiguous
   // std::tr1::bind(&A::Foo)
   //must write this instead. Yuck!
   std::tr1::bind(static_cast<int(Foo::*)()>(&A::Foo));
);

Dejando de lado la pregunta de si los tiene ;-)

Seguiré adelante y mencionaré que esto debería ser una pregunta de la comunidad wiki.

Cuando comencé a aprender C ++ busqué guías de estilo, y Google fue bueno en algunos puntos:

  • Métodos en mayúsculas (es más bonito).
  • getters llanamente y en minúsculas ( rate ).
  • definidores explícitamente y en minúsculas ( setRate ).

Ser conciso es importante, pero no a costa de ser incompleto o engañoso. Por esa razón, prefiero GetFoo () y SetFoo () a Foo () y Foo (int foo).

Hay varios niveles para " Obtener " y " Configuración "

  • Uso Get and Set para " rápido " operaciones.
  • Si algo demora más tiempo en ejecutarse, a menudo será un Calc, ya que estos nombres implican que se debe hacer algún trabajo para recuperar el resultado.
  • Para operaciones más largas, comienza a usar prefijos como Cargar / Guardar, Consulta / Almacenar, Leer / Escribir, Buscar / Buscar, etc.

Por lo tanto, a Get / Set se le puede asignar un significado útil, y ser parte de una estrategia de nomenclatura más amplia y consistente.

Si bien el comentario de Ed es cierto, prefiero las propiedades reales sobre el antipattern setter / getter. Cuando la tercera parte de los métodos en tu gráfica de dominio son métodos ficticios generados por eclipse, hay algo incorrecto.

Sin propiedades de primera clase, sin embargo, creo que el antipatrón tiene más sentido.

Además, facilita la finalización del código.

obj.set (control shift espacio) para los configuradores
obj.get (control shift espacio) para captadores

Personalmente, creo que los getters y setters que se encuentran en pares son un olor de código transmitido desde " visual " idiomas y sus " propiedades " ;. En un " bueno " En la clase, los miembros de los datos son de solo escritura o solo lectura pero no de lectura / escritura.

Creo que la causa más común de los captadores y definidores no es llevar el modelo de objetos lo suficientemente profundo. En su ejemplo, ¿por qué se pasa el período y la tasa total? ¿No son ellos miembros de la clase? Por lo tanto, solo debe establecer el período y la tasa y solo debe obtener un total.

Probablemente hay excepciones, pero simplemente odio mirar una clase y encontrar "getX / setX, getY / setY, etc., etc." Parece que no se pensó lo suficiente en cómo se DEBERÍA usar la clase y, más bien, el autor hizo que la clase fuera FÁCIL de obtener los datos para que no tuviera que considerar cómo debería usarse la clase.

Naturalmente estoy en lo correcto.

Otro problema que nadie más ha mencionado es el caso de la sobrecarga de funciones. Toma este ejemplo (ideado e incompleto):

class Employee {
    virtual int salary() { return salary_; }
    virtual void salary(int newSalary) { salary_ = newSalary; }
};

class Contractor : public Employee {
    virtual void salary(int newSalary) {
        validateSalaryCap(newSalary);
        Employee::salary(newSalary);
    }
    using Employee::salary; // Most developers will forget this
};

Sin ese uso de la cláusula , los usuarios de Contratista no pueden consultar el salario debido a la sobrecarga. Recientemente agregué -Woverloaded-virtual al conjunto de advertencias de un proyecto en el que trabajo, y he aquí que esto apareció en todo el lugar.

Aplico la convención en la que un método siempre debe ser un verbo y una clase siempre debe ser un sustantivo (excepto por los funtores, por razones obvias). En cuyo caso, se debe usar un prefijo get / set para mantener la coherencia. Dicho esto, también estoy totalmente de acuerdo con Ed Swangren. Esto me parece que usar esos prefijos es una obviedad.

Prefiero evitar las etiquetas de obtener y establecer, la información no es necesaria para que el compilador haga su trabajo en la mayoría de estas propiedades simples.

puedes tener problemas:

class Stuff {
  void widget( int something ); // 'special' setter
  const Widget& widget( int somethingelse ) const; // getter
}
Stuff a; 
a.widget(1); // compiler won't know which widget you mean, not enough info

Si su captador es simplemente rate () , su compilador se quejaría de que es una redefinición de su otro símbolo de rate , siempre que le haya dado a su campo un buen nombre significativo como ese. En ese caso, debe hacer algo tonto como nombrar a su miembro _rate o algún otro enfoque similar. Personalmente, odio ver / escribir esos guiones bajos, así que tiendo a ir con el enfoque getRate () .

Esto es obviamente subjetivo y esta es mi preferencia personal.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top