¿Es la legibilidad una razón válida para no usar const en los parámetros (de referencia)?

24

Al escribir algunas funciones, encontré una palabra clave const en parámetros como este:

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
}

a menudo provoca la división de una línea en 2 líneas en IDE o vim, por lo que quiero eliminar todas las palabras clave constantes en los parámetros:

void MyClass::myFunction(MyObject& obj,string& s1,string& s2,string& s3){
} 

¿Es esa una razón válida para no usar const? ¿Es mantenible mantener los objetos de parámetros sin cambios manualmente?

ggrr
fuente
110
"Hey, quiero cambiar funcionalmente mi programa" para hacerlo más legible es una mala, mala razón.
Pieter B
37
De todos modos, el programa ya no es más legible: una vez que ve que se entrega algo, ya constque tiene una fuerte pista de que no necesita molestarse en cómo se puede cambiar en la función.
tofro
43
Una mejor manera de mejorar la legibilidad es reducir el número de argumentos.
5gon12eder
15
'const' podría decirse que mejora la legibilidad. ¡Esta declaración deja en claro que obj no puede cambiar!
Charles
14
Lo que ayudaría a la legibilidad es agregar un espacio después de cada coma.
sam hocevar

Respuestas:

182

La legibilidad es una razón válida para aprender a usar espacios en blanco:

void MyClass::myFunction(
        const MyObject& obj,
        const string& s1,
        const string& s2,
        const string& s3
) {
    return;
}

Ubicados allí, los parámetros no se confundirán con el cuerpo de la función. Al ubicarlos en una línea diferente, no tendrá que reposicionarlos cuando cambie el nombre de myFunctionalgo más descriptivo. No cambiar la posición de los parámetros cuando no han cambiado es algo que los usuarios de la herramienta de control de fuente apreciarán.

constsignifica algo. No lo tires solo porque te quedas sin espacio e ideas. La legibilidad es el rey, pero romper cosas en su nombre es simplemente darse por vencido.

naranja confitada
fuente
66
"no tendrá que reposicionarlos cuando cambie el nombre de myFunction", aunque en este caso parece que se han posicionado para alinearse aproximadamente con la abertura (, y si ese es el caso, entonces podría tener que reposicionar si la longitud del nombre de la clase + función cambia en más de aproximadamente 4 caracteres. Entonces, si no quiere tener que hacer eso, agregue un número fijo de niveles de sangría, no un número que dependa de la longitud del nombre de la función. Recomendaría 1 nivel, esta respuesta usa 6, pero cualquier número fijo logra el objetivo establecido :-)
Steve Jessop
66
@CandiedOrange Me sorprende que no haya usado el "formulario 6" en esta respuesta ... ¡es claramente menos feo!
svidgen
66
Forma 6 para la victoria. Un espacio de pestañas para un nivel de sangría. Simple y efectivo. Problema resuelto :)
Lightness compite con Mónica
2
Ok ok forma 6 es. Esta es la variante que JeffGrigg mencionó en c2.
candied_orange
44
@ random832 Creo que ahora estamos firmemente en territorio de cobertizo para bicicletas. Esta es la forma correcta de resolver eso: busque ejemplos en su base de código, consulte la guía de estilo de su tienda, pregunte a los desarrolladores de su tienda y, si nada de eso arroja una respuesta autorizada, use esto. Resuelva disputas que podrían ir en cualquier dirección con una cuarta parte. Una vez que el trimestre ha hablado, ¡sé consistente!
candied_orange
52

En realidad, el problema de legibilidad definitivamente va en la otra dirección. Primero, puede resolver trivialmente su línea de acceso mediante el uso de espacios en blanco . Pero eliminar constno solo hace que la línea sea más corta, sino que cambia completamente el significado del programa.

Herb Sutter se refiere a la constreferencia constcomo la más importanteconst porque una referencia a constpuede unirse a una temporal y extender su vida útil. Una referencia de valor a no constpuede, necesita una variable separada.

void foo_const(std::string const& );
void foo_nc(std::string& );

std::string some_getter();

foo_const(some_getter());      // OK
foo_const("Hello there"); // OK

foo_nc(some_getter()); // error
foo_nc("Nope");   // error

std::string x = some_getter(); // have to do this
foo_nc(x);                     // ok
std::string msg = "Really??";  // and this
foo_nc(msg);                   // ok

Lo que esto significa para la usabilidad es que tendrá que introducir todas estas variables temporales solo para poder llamar a su función. Eso no es bueno para la legibilidad, ya que estas variables no tienen sentido y existen solo porque su firma es incorrecta.

Barry
fuente
66
Su segundo párrafo me da dolores de cabeza tratando de averiguar si constestá refiriendo a consto al otro consty lo que constes de hecho el más importanteconst
Mindwin
3
@Mindwin Creo que la ironía es que mi segundo párrafo es claro y sin ambigüedades, y no tengo idea de lo que estás hablando.
Barry
2
@Barry Ciertamente no es ambiguo, pero me tomó algunas lecturas de ese párrafo tratar de entender qué significaba. Creo que parte del problema es que se puede analizar "Herb Sutter se refiere a la constante (en referencia a const) como la constante más importante ..." o "Herb Sutter se refiere a constante en (referencia a constante) const importante ... "Creo que esta última es la única agrupación válida de las palabras, pero toma un poco procesarla. ¿Quizás haya una manera de utilizar comillas para eliminar la ambigüedad?
Cort Ammon - Restablece a Monica el
1
Creo que algunos compuestos con guiones aclararían esto.
shawnt00
2
o usar específicamente en const&lugar de referencia constcomo un sustantivo (frase) allí
Caleth
21

La respuesta simple es "no".

La respuesta larga es que la constpalabra clave es parte del contrato que ofrece la función; le dice que el argumento no se modificará. En el momento en que elimina la constgarantía, esa garantía desaparece. Recuerde que usted no puede sostener la constness (o cualquier otra propiedad) de algo utilizando documentación, convenciones, directrices o - si el constness no se hace cumplir por el compilador, alguien va a pensar que pueden hacer su trabajo más fácil si jugar con el parámetro "solo un poquito". Considerar:

// parameter "foo" is not modified
void fna(Foo& foo);

void fnb(const Foo& foo);

Además del hecho de que la última versión es más concisa, también proporciona un contrato más sólido y permite que el compilador lo ayude a mantener sus intenciones. El primero no hace nada para evitar que la fna(Foo&)función modifique el parámetro que le pasa.

Como en la respuesta @CandiedOrange, puede usar espacios en blanco para diseñar el código y mejorar la legibilidad.

Mael
fuente
14

La eliminación de la constpalabra clave elimina la legibilidad porque constcomunica información al lector y al compilador.
Reducir la longitud horizontal del código es bueno (a nadie le gusta desplazarse hacia los lados), pero hay más constque texto. Podrías reescribirlo:

typedef string str;
typedef MyObject MObj;
void MyClass::myFunction(const MObj& o,const str& s1,const str& s2,const str& s3)

Lo cual no cambia el contrato pero satisface la necesidad de reducir la longitud de la línea. Verdaderamente , consideraría que el fragmento anterior es menos legible y optaría por usar más espacios en blanco como ya se mencionó en la respuesta de CandiedOrange.

constes una funcionalidad del código en sí. No haría que la función no sea miembro para eliminar la MyClass::sección de la declaración, así que no elimine elconst

Erdrik Ironrose
fuente
44
Estoy de acuerdo en que el fragmento que proporcione es menos legible. Obliga al lector a averiguar qué MObjy qué strson, y ciertamente levanta las cejas. Es especialmente extraño para este tipo de cuyos nombres ya tiene control sobre: Por ejemplo, ¿por qué no acaba de nombrar MyObjectcomo MObjpara empezar?
Jason C
3

¿Es la legibilidad una razón válida para no usar const en los parámetros?

No. Omitir constpuede cambiar la funcionalidad, perder las protecciones que constofrece y potencialmente puede crear código menos eficiente.

¿Es mantenible mantener los objetos de parámetros sin cambios manualmente?

En lugar de perder tiempo formateando código manualmente

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
  //
}

Use herramientas de formateo automático . Escriba la función según sus requisitos funcionales y deje que el formateo automático se encargue de la presentación. Ajustar el formato manualmente no es tan eficiente como usar el formateo automático y usar el tiempo ahorrado para mejorar otros aspectos del código.

void MyClass::myFunction(const MyObject& obj, const string& s1, const string& s2, 
    const string& s3) {
  // 
}
chux - Restablece a Monica
fuente
-1

Mientras sea posible, es mejor mantener visible la constante. Mejora mucho el mantenimiento del código (no hay conjeturas para ver si este método cambia mis argumentos).

Si veo muchos argumentos en un método, me obliga a considerar la creación de jaron basado en proyectos (Matriz, Empleado, Rectángulo, Cuenta) que sería mucho más corto, más fácil de entender (elimina una larga lista de argumentos para los métodos).

lápiz negro
fuente
Convenido. Dudaba en señalarlo. Por lo tanto, "caso extremo".
blackpen
@cmaster Dicho esto, a veces en ciertos contextos, con ciertos programadores, podría seguir siendo legible. Por ejemplo, en el caso muy específico de un programa hasta la cintura en llamadas API de Windows, con un lector que está acostumbrado a ese entorno, cosas como, por ejemplo , typedef Point * LPPOINTy typedef const Point * LPCPOINT, aunque es muy desagradable, todavía tiene un significado implícito, porque es coherente con las expectativas inmediatas en contexto. Pero nunca en el caso general; Es solo una extraña excepción en la que puedo pensar.
Jason C
1
Sí, cuando vi la pregunta, "const unsigned long long int" me vino a la mente, pero no es un buen candidato para obtener beneficios de ser "const" o "referencia". Typedef resuelve el problema general de acortar nombres; pero no parece un buen diseño ocultar el propósito mismo de las construcciones del lenguaje (como "const") detrás de él.
blackpen