"Fácil de razonar", ¿qué significa eso? [cerrado]

49

He escuchado muchas veces cuando otros desarrolladores usan esa frase para "anunciar" algunos patrones o desarrollar mejores prácticas. La mayoría de las veces esta frase se usa cuando se habla de los beneficios de la programación funcional.

La frase "Fácil de razonar" se ha utilizado tal cual, sin ninguna explicación o muestra de código. Entonces, para mí, se convierte en la próxima palabra "zumbido", que los desarrolladores más "experimentados" usan en sus conversaciones.

Pregunta: ¿Puede proporcionar algunos ejemplos de "No es fácil razonar sobre", de modo que pueda compararse con los ejemplos de "Fácil razonar sobre"?

Fabio
fuente
44
@MartinMaat: una frase más precisa que se usa ampliamente es el razonamiento equitativo, sugeriría que esto podría ser lo que Fabio
busca
3
Me gusta usar la frase "carga cognitiva" para este tipo de cosas.
Baldrickk
16
¿Sabes lo que significa razonar sobre los programas ?
Bergi
55
En el sentido no formal, utilizo esto para significar que una solución es lo suficientemente simple como para comprender (en general) cuáles serán los resultados para cualquier entrada dada sin probarla. Significa que para cualquier conjunto de entradas, los resultados no serán sorprendentes. Las soluciones que tienen casos de esquina no obvios, por ejemplo, son difíciles de razonar. Principalmente uso esto en referencia a la robustez.
JimmyJames
77
Soy muy culpable de usar "más fácil de razonar" con frecuencia; Sin embargo, observo que trato de tener cuidado al decir que el comparativo es más fácil que el absoluto fácil . Hubo un día en mi vida en el que no podía razonar sobre ningún software, por lo que no fue fácil ese día; se hizo fácil solo gastando una gran cantidad de tiempo y esfuerzo. Decir que cualquier problema de programación es fácil es adoptar una postura peyorativa hacia cualquiera que no (todavía) lo encuentre fácil. Decir que un modelo es más fácil que otro es decir que hay menos conceptos involucrados, menos partes móviles, etc.
Eric Lippert

Respuestas:

58

En mi opinión, la frase "fácil de razonar", se refiere al código que es fácil de "ejecutar en su cabeza".

Cuando se mira un fragmento de código, si es breve, claramente escrito, con buenos nombres y una mínima mutación de valores, trabajar mentalmente en lo que hace el código es una tarea (relativamente) fácil.

Un código largo con nombres pobres, variables que cambian constantemente de valor y ramificaciones enrevesadas normalmente requerirán, por ejemplo, un bolígrafo y una hoja de papel para ayudar a realizar un seguimiento del estado actual. Por lo tanto, dicho código no se puede resolver fácilmente en su cabeza, por lo que no es fácil razonar sobre ese código.

David Arno
fuente
29
Con una leve advertencia de que no importa qué tan bien nombre sus variables, un programa que intenta refutar la conjetura de Goldbach es intrínsecamente difícil de "ejecutar", en su cabeza o en otro lugar. Pero aún puede ser fácil razonar, en el sentido de que es fácil convencerse de que si dice haber encontrado un contraejemplo, entonces está diciendo la verdad ;-)
Steve Jessop
44
Yo no quiero para ejecutar código en mi cabeza. Eso, para mí, sería el último espectáculo de "no es fácil razonar". Me gustaría poder hacer declaraciones predictivas sobre lo que haría la computadora sin ejecutarla. El código que es "fácil de razonar" es un código que no tiene que ejecutarse en su cabeza, sino que puede razonarse.
Cort Ammon
1
¿Cómo se puede responder una pregunta sobre el razonamiento sobre el código sin siquiera mencionar la verificación formal ? Esta respuesta sugiere que el razonamiento sobre el código es informal y ad-hoc. no, generalmente se hace con mucho cuidado y enfoques matemáticos. Hay ciertas propiedades matemáticas que hacen que el código sea "fácil de razonar" en un sentido objetivo (funciones puras, por poner un ejemplo muy fácil). Los nombres de las variables no tienen nada que ver con lo fácil que es "razonar" sobre el código, al menos en ningún sentido formal.
Polygnome
3
@Polygnome El razonamiento sobre el código generalmente no se realiza con mucho cuidado y enfoques matemáticos. Mientras escribo esto, las personas que razonan sobre el código de manera informal superan en número a los acercadores matemáticos en millones a uno, al menos, o eso creo.
Kaz
2
@Polygnome "Code easy to reason about" almost exclusively alludes to its mathematical properties and formal verification: eso suena más o menos como una respuesta a la pregunta. Es posible que desee publicar eso como una respuesta en lugar de estar en desacuerdo sobre cuál es la respuesta (subjetiva) en los comentarios.
Dukeling
47

Es fácil razonar sobre un mecanismo o parte de código cuando necesita tener en cuenta algunas cosas para predecir lo que hará, y las cosas que debe tener en cuenta están fácilmente disponibles.

Las funciones verdaderas sin efectos secundarios y sin estado son fáciles de razonar porque la salida está completamente determinada por la entrada, que está justo allí en los parámetros.

Por el contrario, un objeto con estado es mucho más difícil de razonar, porque debe tener en cuenta en qué estado se encuentra el objeto cuando se llama a un método, lo que significa que tiene que pensar qué otras situaciones podrían llevar al objeto a estar en un estado estado particular.

Peor aún son las variables globales: para razonar sobre el código que lee una variable global, debe comprender en qué parte de su código se puede establecer esa variable y por qué, y puede que ni siquiera sea fácil encontrar todos esos lugares.

Lo más difícil de razonar es la programación multiproceso con estado compartido, porque no solo tiene estado, tiene múltiples hilos que lo cambian al mismo tiempo, por lo que razonar sobre lo que hace un fragmento de código cuando lo ejecuta un solo hilo. tiene que permitir la posibilidad de que en cada punto de ejecución, algún otro hilo (¡o varios de ellos!) podría estar ejecutando casi cualquier otra parte del código y cambiar los datos que está operando bajo sus ojos. En teoría, eso se puede gestionar con mutexes / monitores / secciones críticas / como se llame, pero en la práctica ningún ser humano es capaz de hacerlo de manera confiable a menos que reduzcan drásticamente el estado compartido y / o el paralelismo a muy pequeño secciones del código.

Michael Borgwardt
fuente
99
Estoy de acuerdo con esta respuesta, pero incluso con funciones puras, los enfoques declarativos (como CSS, o XSLT, makeo incluso la especialización de plantillas C ++ y la sobrecarga de funciones) pueden ponerlo nuevamente en la posición de considerar todo el programa. Incluso una vez que crees que has encontrado la definición de algo, el lenguaje permite una declaración más específica en cualquier parte del programa para anularlo. Su IDE podría ayudar con esto.
Steve Jessop
44
Agregaría que en el escenario multiproceso también debe tener una comprensión razonablemente profunda de las instrucciones de nivel inferior a las que se desvía su código: una operación que parece de origen atómico podría tener puntos de interrupción inesperados en la ejecución real.
Jared Smith
66
@SteveJessop: De hecho, este punto a menudo se pasa por alto. Hay una razón por la cual C # te hace decir cuándo quieres que un método sea reemplazable en lugar de hacer que la sobreescritura sea el valor predeterminado; deseamos agitar una bandera que diga "la corrección de su programa puede depender del código que no puede encontrar en el momento de la compilación" en este momento. (Dicho esto, también desearía que "sellado" fuera el valor predeterminado para las clases en C #.)
Eric Lippert
@EricLippert ¿Cuáles fueron las razones finales para sealedno ser el predeterminado?
Zev Spitz
@ZevSpitz: Esa decisión fue tomada mucho antes de mi tiempo; No lo sé.
Eric Lippert
9

En el caso de la programación funcional, el significado de "Fácil de razonar" es principalmente que es determinista. Con eso, quise decir que una entrada dada siempre conducirá a la misma salida. Puede hacer lo que quiera con el programa, siempre que no toque ese código, no se romperá.

Por otro lado, OO es típicamente más difícil de razonar porque la "salida" producida depende del estado interno de cada objeto involucrado. La forma típica en que se manifiesta son efectos secundarios inesperados : al cambiar una parte del código, se rompe una parte aparentemente no relacionada.

... la desventaja de la programación funcional es, por supuesto, que en la práctica, mucho de lo que quiere hacer es IO y estado de gestión.

Sin embargo, hay muchas otras cosas que son más difíciles de razonar, y estoy de acuerdo con @Kilian en que la concurrencia es un buen ejemplo. Sistemas distribuidos también.

dagnelies
fuente
5

Evitar una discusión más amplia y abordar la pregunta específica:

¿Puede proporcionar algunos ejemplos de "No es fácil razonar sobre", para que pueda compararse con los ejemplos de "Fácil razonar sobre"?

Me refiero a "La historia de Mel, un verdadero programador" , una pieza de folklore de programadores que data de 1983 y, por lo tanto, cuenta como "leyenda" para nuestra profesión.

Cuenta la historia de un programador que escribe código que prefiere técnicas arcanas siempre que sea posible, incluido el código autorreferencial y auto modificable, y la explotación deliberada de errores de máquina:

De hecho, un bucle infinito aparente había sido codificado de tal manera que aprovechara un error de desbordamiento de arrastre. Agregar 1 a una instrucción que decodificó como "Cargar desde la dirección x" normalmente produjo "Cargar desde la dirección x + 1". Pero cuando x ya era la dirección más alta posible, no solo la dirección se ajustaba a cero, sino que se llevaba un 1 a los bits desde los cuales se leería el código operativo, cambiando el código operativo de "cargar de" a "saltar a". que la instrucción completa cambió de "cargar desde la última dirección" a "saltar a la dirección cero".

Este es un ejemplo de código que es 'difícil de razonar'.

Por supuesto, Mel no estaría de acuerdo ...

AakashM
fuente
1
+1 por hacer referencia a la historia de Mel, uno de mis favoritos perennes.
John Bollinger
3
Lea La historia de Mel aquí, ya que el artículo de Wikipedia no se vincula a ella.
TRiG
@TRiG nota 3 en la página, ¿no?
AakashM
@AakashM De alguna manera logró perderse eso.
TRiG
5

Puedo proporcionar un ejemplo, y uno muy común.

Considere el siguiente código C #.

// items is List<Item>
var names = new List<string>();
for (var i = 0; i < items.Count; i++)
{
    var item = items[i];
    var mangled = MyMangleFunction(item.Name);
    if (mangled.StartsWith("foo"))
    {
        names.Add(mangled);
    }
}

Ahora considere esta alternativa.

// items is List<Item>
var names = items
    .Select(item => MyMangleFunction(item.Name))
    .Where(s => s.StartsWith("foo"))
    .ToList();

En el segundo ejemplo, sé exactamente lo que está haciendo este código de un vistazo. Cuando veo Select, sé que una lista de elementos se está convirtiendo en una lista de otra cosa. Cuando veo Where, sé que ciertos elementos se están filtrando. De un vistazo, puedo entender lo que nameses y hacer un uso efectivo de él.

Cuando veo un forbucle, no tengo idea de lo que está sucediendo hasta que realmente leo el código. Y a veces tengo que rastrearlo para asegurarme de haber tenido en cuenta todos los efectos secundarios. Tengo que hacer un poco de trabajo para incluso comprender qué nombres son (más allá de la definición de tipo) y cómo usarlos de manera efectiva. Por lo tanto, el primer ejemplo es más difícil de razonar que el segundo.

En última instancia, ser fácil de razonar aquí también depende de comprender los métodos Selecty LINQ Where. Si no los conoce, el segundo código es más difícil de razonar inicialmente. Pero solo paga el costo para comprenderlos una vez. Usted paga el costo de comprender un forciclo cada vez que usa uno y nuevamente cada vez que cambia. A veces vale la pena pagar el costo, pero generalmente es "más fácil razonar" es mucho más importante.

Kasey Speakman
fuente
2

Una frase relacionada es (parafraseo),

No es suficiente que el código no tenga " errores obvios ": en su lugar, debería tener " obviamente ningún error ".

Un ejemplo de relativamente "fácil de razonar" podría ser RAII .

Otro ejemplo podría ser evitar el abrazo mortal : si puede mantener un bloqueo y adquirir otro bloqueo, y hay muchos bloqueos, es difícil asegurarse de que no haya un escenario en el que pueda ocurrir un abrazo mortal. Agregar una regla como "solo hay un bloqueo (global)" o "no se le permite adquirir un segundo bloqueo mientras mantiene un primer bloqueo" hace que el sistema sea relativamente fácil de razonar.

ChrisW
fuente
1
Hmm No estoy seguro de que RAII sea tan fácil de razonar. Claro, es fácil de entender conceptualmente , pero se hace más difícil razonar sobre (es decir, predecir) el comportamiento del código que hace un uso extensivo de RAII. Quiero decir, es básicamente llamadas a funciones invisibles a nivel de alcance. El hecho de que mucha gente tenga problemas para razonar sobre esto es muy claro si alguna vez has hecho alguna programación COM .
Cody Gray
Quise decir relativamente fácil (C ++ en comparación con C): por ejemplo, la existencia de un constructor compatible con el lenguaje significa que los programadores no pueden crear / tener / usar un objeto que olvidan inicializar, etc.
ChrisW
Ese ejemplo basado en COM es problemático porque combina estilos, es decir, puntero inteligente de estilo C ++ ( CComPtr<>) con función de estilo C ( CoUninitialize()). También me parece un ejemplo extraño, hasta donde recuerdo que invocas CoInitialize / CoUninitialize en el alcance del módulo y durante toda la vida útil del módulo, por ejemplo, dentro maino fuera DllMain, y no en un pequeño alcance de función local de corta duración como se muestra en el ejemplo .
ChrisW
Es un ejemplo demasiado simplificado para fines ilustrativos. Tiene toda la razón en que COM se inicializa en el ámbito del módulo, pero imagine el ejemplo de Raymond (como el ejemplo de Larry) como la mainfunción de punto de entrada ( ) para una aplicación. Inicializa COM al inicio y luego lo desinicializa justo antes de salir. Excepto que tiene objetos globales, como punteros inteligentes COM, que utilizan el paradigma RAII. Con respecto a los estilos de mezcla: un objeto global que inicializó COM en su ctor y no inicializado en su dtor es viable, y lo que Raymond sugiere, pero es sutil y no es fácil razonar.
Cody Gray
Yo diría que, en muchos sentidos, la programación COM es más fácil de razonar en C, porque todo es una llamada de función explícita. No pasa nada oculto o invisible a tus espaldas. Es un poco más de trabajo (es decir, más tedioso), porque tiene que escribir manualmente todas esas llamadas de función y volver y verificar su trabajo para ver que lo ha hecho correctamente, pero todo está al descubierto, que es la clave para que sea fácil razonar sobre ello. En otras palabras, "a veces los punteros inteligentes son demasiado inteligentes" .
Cody Gray
2

El quid de la programación es el análisis de casos. Alan Perlis comentó sobre esto en el Epigrama # 32: los programadores no deben ser medidos por su ingenio y su lógica, sino por la integridad de su análisis de casos.

Es fácil razonar sobre una situación si el análisis de casos es fácil. Esto significa que hay pocos casos a considerar o, en su defecto, pocos casos especiales ; puede haber algunos espacios grandes de casos, pero que colapsan debido a algunas regularidades, o sucumben a una técnica de razonamiento como la inducción.

Una versión recursiva de un algoritmo, por ejemplo, suele ser más fácil de razonar que una versión imperativa, porque no aporta casos superfluos que surgen de la mutación de variables de estado de soporte que no aparecen en la versión recursiva. Además, la estructura de la recursión es tal que se ajusta a un patrón matemático de prueba por inducción. No tenemos que considerar complejidades como las variantes de bucle y las precondiciones estrictas más débiles y demás.

Otro aspecto de esto es la estructura del espacio del caso. Es más fácil razonar sobre una situación que tiene una división plana o mayormente plana en casos en comparación con una situación jerárquica de casos: casos con sub-casos y sub-sub casos, etc.

Una propiedad de los sistemas que simplifica el razonamiento es la ortogonalidad : esta es la propiedad de que los casos que gobiernan los subsistemas permanecen independientes cuando esos subsistemas se combinan. Ninguna combinación da lugar a "casos especiales". Si un elemento de cuatro casos se combina con un elemento de tres casos ortogonalmente, hay doce casos, pero idealmentecada caso es una combinación de dos casos que permanecen independientes. En cierto sentido, en realidad no hay doce casos; las combinaciones son simplemente "fenómenos emergentes similares a casos" de los que no tenemos que preocuparnos. Lo que esto significa es que todavía tenemos cuatro casos en los que podemos pensar sin considerar los otros tres en el otro subsistema, y ​​viceversa. Si algunas de las combinaciones tienen que ser especialmente identificadas y dotadas de lógica adicional, entonces el razonamiento es más difícil. En el peor de los casos, cada combinación tiene un manejo especial, y luego hay doce casos nuevos, que se suman a los cuatro y tres originales.

Kaz
fuente
0

Seguro. Tomar concurrencia:

Secciones críticas impuestas por mutexes: fácil de entender porque solo hay un principio (dos hilos de ejecución no pueden entrar en la sección crítica simultáneamente), pero son propensos tanto a la ineficiencia como al punto muerto.

Modelos alternativos, por ejemplo, programación sin bloqueo o actores: potencialmente mucho más elegantes y potentes, pero terriblemente difíciles de entender, porque ya no puede confiar en conceptos (aparentemente) fundamentales como "ahora escriba este valor en ese lugar".

Ser fácil de razonar es un aspecto de un método. Pero elegir qué método usar requiere considerar todos los aspectos en combinación.

Kilian Foth
fuente
13
-1: muy, muy mal ejemplo que me hace pensar que no entiendes lo que la frase significa para ti. Las "secciones críticas impuestas por mutexes" son, de hecho, una de las cosas más difíciles de razonar: casi todos los que las usan presentan condiciones de carrera o puntos muertos. Te daré una programación sin bloqueo, pero el maldito punto del modelo de actor es que es mucho, mucho más fácil razonar.
Michael Borgwardt
1
El problema es que la concurrencia es en sí misma un tema muy difícil para los programadores, por lo que no es un muy buen ejemplo. Tiene toda la razón en que las secciones críticas impuestas por mutexes son una forma relativamente simple de implementar la concurrencia, en comparación con la programación sin bloqueo, pero la mayoría de los programadores son como Michael, y sus ojos se nublan cuando comienza a hablar de secciones críticas y mutexes, así que esto ciertamente no parece una cosa fácil de entender. Sin mencionar todos los errores.
Cody Gray
0

Limitemos la tarea al razonamiento formal. Porque el razonamiento humorístico, inventivo o poético tiene leyes diferentes.

Aun así, la expresión está débilmente definida y no se puede establecer de manera estricta. Pero eso no significa que deba permanecer tan oscuro para nosotros. Imaginemos que una estructura está pasando una prueba y obteniendo calificaciones para diferentes puntos. Las buenas notas para CADA punto significan que la estructura es conveniente en todos los aspectos y, por lo tanto, "Fácil de razonar".

La estructura "Fácil de razonar" debería obtener buenas notas para lo siguiente:

  • Los términos internos tienen nombres razonables, fáciles de distinguir y definir. Si los elementos tienen alguna jerarquía, la diferencia entre los nombres primarios y secundarios debe ser diferente de la diferencia entre los nombres de hermanos.
  • El número de tipos de elementos estructurales es bajo.
  • Los tipos usados ​​de elementos estructurales son cosas fáciles a las que estamos acostumbrados.
  • Los elementos apenas comprensibles (recursiones, metapasos, geometría de 4 o más dimensiones ...) están aislados, no combinados directamente entre sí. (por ejemplo, si intenta pensar en un cambio de regla recurrente para los cubos dimensionales 1,2,3,4..n.., será muy complicado. Pero si transfiere cada una de estas reglas a alguna fórmula dependiendo de n, tendrá por separado una fórmula para cada n-cubo y por separado una regla de recursión para dicha fórmula. Y que dos estructuras por separado se pueden pensar fácilmente)
  • Los tipos de elementos estructurales son obviamente diferentes (por ejemplo, no se utilizan matrices mixtas a partir de 0 y de 1)

¿Es subjetiva la prueba? Sí, naturalmente lo es. Pero la expresión en sí es subjetiva también. Lo que es fácil para una persona, no es fácil para otra. Por lo tanto, las pruebas deben ser diferentes para los diferentes dominios.

Gangnus
fuente
0

La idea de que es posible razonar sobre lenguajes funcionales proviene de su historia, específicamente ML, que se desarrolló como un lenguaje de programación análogo a las construcciones que la lógica para funciones computables utilizó para razonar. La mayoría de los lenguajes funcionales están más cerca de los cálculos formales de programación que los imperativos, por lo que la traducción del código a la entrada de un sistema de sistema de razonamiento es menos onerosa.

Para un ejemplo de un sistema de razonamiento, en el cálculo pi, cada ubicación de memoria mutable en un lenguaje imperativo debe representarse como un proceso paralelo separado, mientras que una secuencia de operaciones funcionales es un proceso único. Cuarenta años después de la prueba del teorema de LFC, estamos trabajando con GB de RAM, por lo que tener cientos de procesos es menos problemático: he usado el cálculo pi para eliminar posibles puntos muertos de unos cientos de líneas de C ++, a pesar de que la representación tiene cientos de procesa el razonador si agota el espacio de estado en alrededor de 3 GB y cura un error intermitente. Esto habría sido imposible en los años 70 o habría requerido una supercomputadora a principios de los 90, mientras que el espacio de estado de un programa de lenguaje funcional de tamaño similar era lo suficientemente pequeño como para razonar en ese momento.

De las otras respuestas, la frase se está convirtiendo en una frase de moda aunque la ley de Moore erosiona gran parte de la dificultad que dificultaba razonar sobre los idiomas imperativos.

Pete Kirkham
fuente
-2

Es fácil razonar sobre un término culturalmente específico, por lo que es tan difícil encontrar ejemplos concretos. Es un término que está anclado a las personas que deben razonar.

"Fácil de razonar" es en realidad una frase muy descriptiva. Si uno está mirando el código y quiere razonar lo que hace, es fácil =)

Está bien, descomponiéndolo. Si está buscando código, generalmente quiere que haga algo. Debes asegurarte de que haga lo que crees que debería hacer. Entonces, desarrollas teorías sobre lo que debería hacer el código, y luego razonas al respecto para tratar de discutir por qué el código realmente funciona. Intenta pensar en el código como un humano (en lugar de como una computadora) e intenta racionalizar los argumentos sobre lo que puede hacer el código.

El peor caso para "fácil de razonar" es cuando la única forma de dar sentido a lo que hace el código es ir línea por línea a través del código como una máquina de Turing para todas las entradas. En este caso, la única forma de razonar algo sobre el código es convertirte en una computadora y ejecutarlo en tu cabeza. Estos peores ejemplos se ven fácilmente en concursos de programación obscurecidos, como estas 3 líneas de PERL que descifran RSA:

#!/bin/perl -sp0777i<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<j]dsj
$/=unpack('H*',$_);$_=`echo 16dio\U$k"SK$/SM$n\EsN0p[lN*1
lK[d2%Sa2/d0$^Ixp"|dc`;s/\W//g;$_=pack('H*',/((..)*)$/)

En cuanto a lo fácil de razonar, nuevamente, el término es altamente cultural. Tienes que considerar:

  • ¿Qué habilidades tiene el razonador? Cuanta experiencia
  • ¿Qué tipo de preguntas podría tener el razonador sobre el código?
  • ¿Qué tan seguro debe ser el razonador?

Cada uno de estos afecta "fácil de razonar" de manera diferente. Tome las habilidades del razonador como ejemplo. Cuando comencé en mi empresa, se recomendó que desarrollara mis scripts en MATLAB porque es "fácil razonar". ¿Por qué? Bueno, todos en la compañía conocían a MATLAB. Si escogiera un idioma diferente, sería más difícil que alguien me entendiera. No importa que la legibilidad de MATLAB sea atroz para algunas tareas, simplemente porque no fue diseñada para ellas. Más tarde, a medida que avanzaba mi carrera, Python se hizo cada vez más popular. De repente, el código MATLAB se volvió "difícil de razonar" y Python era el lenguaje de preferencia para escribir código sobre el cual era fácil razonar.

También considere qué idoms puede tener el lector. Si puede confiar en que su lector reconocerá una FFT en una sintaxis particular, es "más fácil razonar" sobre el código si se adhiere a esa sintaxis. Les permite ver el archivo de texto como un lienzo en el que pintaste un FFT, en lugar de tener que entrar en los detalles esenciales. Si usa C ++, descubra cuánto se sienten cómodos sus lectores con la stdbiblioteca. ¿Cuánto les gusta la programación funcional? Algunos de los modismos que salen de las bibliotecas de contenedores dependen mucho del estilo idomático que prefiera.

También es importante entender qué tipo de preguntas puede interesarle al lector responder. ¿Están sus lectores preocupados principalmente por la comprensión superficial del código, o están buscando errores en las entrañas?

Qué tan seguro debe ser el lector es realmente interesante. En muchos casos, el razonamiento confuso es suficiente para sacar el producto por la puerta. En otros casos, como el software de vuelo FAA, el lector querrá tener un razonamiento irresistible. Me encontré con un caso en el que defendía el uso de RAII para una tarea en particular, porque "puedes configurarlo y olvidarte de él ... hará lo correcto". Me dijeron que estaba equivocado sobre eso. Los que iban a razonar sobre este código no eran el tipo de personas que "solo quieren olvidarse de los detalles". Para ellos, RAII era más como un chad colgante, obligándolos a pensar en todas las cosas que pueden suceder cuando dejas el alcance.

Cort Ammon
fuente
12
El código Perl es difícil de leer ; No hay razón para eso. Si tuviera algún interés en tener que entenderlo, desubifcaría el código. El código que es realmente difícil de razonar es el que aún es difícil de razonar cuando está bien formateado con identificadores claros para todo, y sin trucos de golf de código.
Kaz