language-agnostic styles spartan

language agnostic - Programación Spartan



language-agnostic styles (8)

En The Pragmatic Programmer, Hunt y Thomas hablan sobre un estudio que denominan la Ley de Demeter y se centra en el acoplamiento de funciones a módulos distintos a los propios. Al permitir que una función nunca llegue a un tercer nivel en su acoplamiento, se reduce significativamente el número de errores y se aumenta la capacidad de mantenimiento del código.

Asi que:

ObjectA a = getTheUser (session.getState (). GetAccount (). GetAccountNumber ());

Está cerca de un delito porque somos 4 objetos en el agujero de la rata. Eso significa cambiar algo en uno de esos objetos. Tengo que saber que llamaste a toda esta pila aquí en este mismo método. Que dolor.

Mejor:

Account.getUser ();

Tenga en cuenta que esto va en contra de las formas expresivas de programación que ahora son realmente populares con el software de burla. La desventaja es que tienes una interfaz estrechamente acoplada de todos modos, y la sintaxis expresiva simplemente hace que sea más fácil de usar.

Disfruté mucho la publicación de Jeff en Spartan Programming . Estoy de acuerdo en que un código como ese es un placer de leer. Desafortunadamente, no estoy tan seguro de que sea necesariamente un placer trabajar con él.

Durante años, he leído y adherido a la práctica de "una expresión por línea". He peleado la buena batalla y me he mantenido firme cuando muchos libros de programación contrarrestaron este consejo con un código de ejemplo como:

while (bytes = read(...)) { ... } while (GetMessage(...)) { ... }

Recientemente, he defendido una expresión por línea por razones más prácticas: depuración y soporte de producción. Obtener un archivo de registro de producción que reclame una excepción NullPointer en la "línea 65" que dice:

ObjectA a = getTheUser(session.getState().getAccount().getAccountNumber());

es frustrante y completamente evitable. A menos que agarre a un experto con el código que puede elegir el objeto "más probable" que fue nulo ... este es un verdadero dolor práctico.

Una expresión por línea también ayuda bastante al pasar por el código. Practico esto con la suposición de que la mayoría de los compiladores modernos pueden optimizar todos los objetos temporales superfluos que acabo de crear ...

Intento ser ordenado, pero abarrotar mi código con objetos explícitos me hace sentir trabajoso a veces. Por lo general, no hace que el código sea más fácil de navegar, pero realmente me ha sido útil para rastrear cosas en la producción o recorrer el código de mi persona o de otra persona.

¿Qué estilo defiende y puede racionalizarlo en un sentido práctico?


Buena explicación. Creo que esta es la versión de la mentalidad general Divide y Vence .


Creo que la solución ideal es encontrar un equilibrio entre los extremos. No hay forma de escribir una regla que se ajuste a todas las situaciones; viene con experiencia Declarar cada variable intermedia en su propia línea hará que leer el código sea más difícil, lo que también contribuirá a la dificultad en el mantenimiento. Por la misma razón, la depuración es mucho más difícil si alinea los valores intermedios.

El ''punto ideal'' está en algún lugar en el medio.


La capacidad de mantenimiento, y con ella, la legibilidad, es el rey. Por suerte, más corto muy a menudo significa más legible.

Aquí hay algunos consejos que me gusta usar para cortar y cortar el código:

  • Nombres de variables : ¿cómo describirías esta variable a alguien más en tu equipo? No dirías "el entero numberOfLinesSoFar". Diría "numLines" o algo similar, comprensible y breve. No pretenda que el mantenedor no conoce el código en absoluto, pero asegúrese de que usted mismo pueda descubrir cuál es la variable, incluso si olvidó su propio acto de escribirlo. Sí, esto es algo obvio, pero vale más el esfuerzo que veo que muchos codificadores lo incluyan, así que lo incluyo primero.
  • Flujo de control : evite muchas cláusulas de cierre a la vez (una serie de} en C ++). Por lo general, cuando ves esto, hay una manera de evitarlo. Un caso común es algo así como

:

if (things_are_ok) { // Do a lot of stuff. return true; } else { ExpressDismay(error_str); return false; }

puede ser reemplazado por

if (!things_are_ok) return ExpressDismay(error_str); // Do a lot of stuff. return true;

si podemos obtener ExpressDismay (o un envoltorio del mismo) para que devuelva falso.

Otro caso es:

  • Iteraciones de bucle : cuanto más estándar, mejor. Para bucles más cortos, es bueno usar iteradores de un carácter cuando la variable nunca se usa, excepto como un índice en un solo objeto.

El caso particular que discutiría aquí está en contra de la forma "correcta" de usar un contenedor STL:

for (vector<string>::iterator a_str = my_vec.begin(); a_str != my_vec.end(); ++a_str)

es mucho más prolijo y requiere operadores de puntero sobrecargados * a_str o a_str-> size () en el ciclo. Para los contenedores que tienen acceso aleatorio rápido, el siguiente es mucho más fácil de leer:

for (int i = 0; i < my_vec.size(); ++i)

con referencias a my_vec [i] en el cuerpo del bucle, que no confundirá a nadie.

Finalmente, a menudo veo a los codificadores sentirse orgullosos de los números de sus líneas. ¡Pero no son los números de línea los que cuentan! No estoy seguro de la mejor manera de implementar esto, pero si tiene alguna influencia sobre su cultura de codificación, trataría de cambiar la recompensa hacia aquellos con clases compactas :)


Normalmente estoy en el campamento "más corto es mejor". Tu ejemplo es bueno:

ObjectA a = getTheUser(session.getState().getAccount().getAccountNumber());

Me avergonzaría si vi más de cuatro líneas en lugar de una, no creo que sea más fácil de leer o entender. Tal como lo presentaste aquí, está claro que estás buscando un solo objeto. Esto no es mejor:

obja State = session.getState(); objb Account = State.getAccount(); objc AccountNumber = Account.getAccountNumber(); ObjectA a = getTheUser(AccountNumber);

Esto es un compromiso:

objb Account = session.getState().getAccount(); ObjectA a = getTheUser(Account.getAccountNumber());

pero aún prefiero la expresión de una sola línea. Aquí hay una razón anecdótica: es difícil para mí releer y verificar errores en el 4-line en este momento para tontos tontos; la única línea no tiene este problema porque simplemente hay menos caracteres.


Tiendo a equivocarme por el lado de la legibilidad, no necesariamente por la depuración. Los ejemplos que dices definitivamente deben evitarse, pero creo que el uso juicioso de expresiones múltiples puede hacer que el código sea más conciso y comprensible.


Una expresión por línea

No hay razón para ofuscar su código. El tiempo adicional que toma escribiendo los términos adicionales, ahorra tiempo de depuración.


ObjectA a = getTheUser(session.getState().getAccount().getAccountNumber());

Este es un mal ejemplo, probablemente porque acabas de escribir algo desde la parte superior de tu cabeza. Está asignando, a la variable llamada a de tipo ObjectA , el valor de retorno de una función llamada getTheUser .
Asumamos que usted escribió esto en su lugar:

User u = getTheUser(session.getState().getAccount().getAccountNumber());

Rompería esta expresión así:

Account acc = session.getState().getAccount(); User user = getTheUser( acc.getAccountNumber() );

Mi razonamiento es: ¿cómo podría pensar sobre lo que estoy haciendo con este código?
Probablemente pensaría: "primero necesito obtener la cuenta de la sesión y luego obtengo el usuario usando el número de esa cuenta".

El código debe leer la forma en que piensas. Las variables deben referirse a las principales entidades involucradas; no tanto a sus propiedades (así que no almacenaría el número de cuenta en una variable).

Un segundo factor a tener en cuenta es: ¿alguna vez tendré que volver a referirme a esta entidad en este contexto?
Si, por ejemplo, estoy sacando más cosas del estado de la sesión, introduciría el SessionState state = session.getState() .

Todo esto parece obvio, pero me temo que tengo alguna dificultad para poner en palabras por qué tiene sentido, no ser un hablante nativo de inglés y todo eso.