2010-01-23 19 views
5

Hace años solían ser un concurso para ver quién podía producir el código C más ofuscado, y algunos de los resultados eran increíblemente ilegibles. C era así. Realmente podrías arruinar las cosas con el preprocesador en particular.Código de C# ofuscado

Sin embargo, muchas de las características más nuevas de C# ofrecen una oportunidad increíble para ofuscar el código. Me preguntaba si alguien tenía una opinión sobre cómo encontrar el equilibrio correcto entre concisión y claridad en el código. Permítanme ofrecer un ejemplo para la discusión, la tarea de llenar elementos en un ListView. (Sí sé que puedes hacerlo con el enlace de datos, pero vaya conmigo aquí.)

El control es de dos columnas para ser llenado con una serie de persona struct { nombre de la cadena pública; dirección de cadena pública; };

Una forma, clara y sencilla es la siguiente:

private void Fill(Person[] people) 
{ 
    foreach(Person person in people) 
    { 
     string[] columns = new string[2]; 
     columns[0] = person.name; 
     columns[1] = person.address;    
     ListViewItem item = new ListViewItem(columns); 
     listView1.items.Add(item); 
    } 
} 

clara y fácil de entender.

También podría escribir así:

private void Fill(Person[] people) 
{ 
    foreach(Person person in people) 
    { 
     string[] columns = new string[] { person.name, person.address }; 
     ListViewItem item = new ListViewItem(columns); 
     listView1.items.Add(item); 
    } 
} 

o incluso:

private void Fill(Person[] people) 
{ 
    foreach(var person in people) // Note use implicit typing here 
    { 
     listView1.items.Add(new ListViewItem(
     new string[] { person.name, person.address })); 
    } 
} 

Por último, también podría escribir así:

private void Fill(Person[] people) 
{ 
    Array.ForEach(people, item => 
    listView1.items.Add(new ListViewItem(
    new string[] { person.name, person.address})); 
} 

Cada uno utiliza algunos de los nuevos características del lenguaje en mayor o menor medida. ¿Cómo se encuentra el equilibrio entre la concisión y la claridad? ¿Deberíamos tener un concurso anual C ofuscado?

+1

No, pero si quieres tener un concurso de perl ofuscado, puede ser divertido. –

+0

y las etiquetas de "mejores prácticas" de "programación funcional" son para? –

+10

lo siento, no puedo ver ninguna ofuscación en eso, tal vez estoy demasiado acostumbrado al lenguaje – flq

Respuesta

24

¿Sabes lo que es difícil? Escribir código que otros puedan leer y mantener. Cualquier idiota puede escribir código que compila y es imposible de mantener.

Siempre favor mantenimiento: así es como se encuentra el equilibrio.

Editar:

". Cualquier tonto puede escribir código que un ordenador puede entender buenos programadores escriben código que los humanos pueden entender"

  • Martin Fowler, Refactoring: mejorar el diseño de código existente

Gracias a roygbiv para encontrar la cita anterior. Disculpas a Fowler por asesinar su cita; Sabía que lo había leído antes, simplemente no podía recordar dónde.

+1

+1, amén de eso. – Paolo

+0

+1 Buena respuesta. Muy diferente al mío ... pero buena respuesta. –

+0

Entonces, ¿es mejor escribir un código que solo un niño recién llegado de la universidad podría entender? Después de todo, él podría ser el que mantiene tu código. –

1

Al menos con respecto al ejemplo que proporciona aquí, realmente no creo que aumente la ofuscación a medida que avanza hasta llegar a la última. Incluso allí, la única razón para cualquier ambigüedad es la presencia de la Lambda y eso solo requiere un poco de tiempo para acostumbrarse. Por lo tanto, un novato podría tener problemas con el anterior, pero no debería encontrar los otros ilegibles en la forma en que las antiguas entradas de la competencia de C salvajes eran ilegibles.

La diferencia es que estos ejemplos de C# están todos en el mismo nivel de abstracción; los ejemplos más concisos solo eliminan "pelusa". En C, tiene la oportunidad de ambigüedad debido a A) constructos arbitrariamente renombrados/alias y B) varios niveles de acceso a la memoria agrupados en una declaración.

En general, puede codificar en cualquier idioma, pero no creo que C# sea propenso a C y, de hecho, creo que es un lenguaje más claro que muchos, incluso cuando se usa de los constructos más avanzados.

+0

En realidad, no estoy de acuerdo. La diferencia es que en los ejemplos anteriores los intermedios se nombran e identifican. Por ejemplo, en el primer ejemplo, tenemos una variable llamada columnas que le dice qué representa la matriz de cadenas. Luego tiene un elemento intermedio que (junto con su tipo) le dice lo que representa. Y luego, al final, está insertando el artículo. Lo que quiere decir que los ejemplos anteriores lo dividen en pasos más pequeños, mientras que el último ejemplo combina todos los pasos en uno solo. ¿Es mejor tener muchas piezas simples o una pieza más complicada? –

+0

Eso puede ser cierto en composiciones más grandes, pero aquí, cada elemento intermedio es trivial; es decir, "un elemento de la lista con el nombre y la dirección". Tener eso unido al nombre "artículo" realmente no agrega mucho valor. – mquander

+0

Tengo que estar de acuerdo con mquander: llega un punto en el que los productos intermedios son tan triviales que es casi más difícil recorrer todos los nombres. Desea agregar a todas las personas a una lista ... ¿realmente necesita cuatro y cinco líneas de declaraciones intermedias y asignaciones solo para hacer eso? No en mi libro. Gracias por comentar que ... –

6

Rellenar todo en una línea no lo "ofusca", simplemente hace que se desplace mucho innecesariamente. Todavía sería trivial que cualquiera que conozca C# comprenda alguno de los ejemplos que usted presentó, y si usó linebreaks, ninguno sería mucho mejor o peor que los demás.

+2

Sí, la muestra proporcionada por el PO apenas puede llamarse ofuscación. –

1

Los idiomas C# y VB.NET fueron diseñados para mayor claridad porque operan en un nivel más alto que C. C está programando cerca del metal por así decirlo. No es posible mediante el diseño para escribir ofuscado C# como la de C.

"Cualquier tonto puede escribir código que un ordenador puede entender. Los buenos programadores escriben código que los humanos pueden entender."

  • Martin Fowler, Refactoring: mejorar el diseño de código existente
2

Código para la máxima legibilidad, pero:

  1. Recuerde que la verbosidad superfluo y el ruido sintáctica daño legibilidad Más concisión puede coincidir con una legibilidad mejorada si la notación más concisa le permite expresar su intención de manera más directa. Por ejemplo, compare funciones lambda reales para simularlas con interfaces de método único.

  2. Asuma que otras personas que leen su código son programadores decentes y conocen el idioma en el que está trabajando. No asuma el nivel de conocimiento de un abogado de idiomas, pero asuma un buen conocimiento práctico. No codifique con el mínimo común denominador porque, si bien puede hacer que su código sea más fácil de mantener por los monos de código, molestará tanto a usted como a los programadores de mantenimiento que realmente saben lo que están haciendo.

Más específicamente, el ejemplo 1 tiene demasiado ruido sintáctico para algo tan simple. El ejemplo 4 es muy difícil de analizar por un humano. Yo diría 2 y 3 son ambos bastante bueno, aunque en el caso del ejemplo 3 Me formatear un poco, sólo para que sea más fácil para un ser humano para analizar toda la anidación llamada de función:

private void Fill(Person[] people) 
{ 
    foreach(var person in people) 
    { 
     listView1.items.Add(
      new ListViewItem(
       new string[] { person.name, person.address } 
      ) 
     ); 
    } 
} 

Ahora tiene lo mejor de ambos mundos: puede ser analizado fácilmente por humanos y no tiene variables temporales superfluas, innecesariamente verbosas.

Editar: También creo que el uso de tipado variable implícito, es decir, var está bien la mayor parte del tiempo. Las personas escriben código perfectamente legible en lenguajes dinámicos donde la tipificación implícita es el único tipo de tipeo, y la mayoría de las veces los tipos formales de sus variables son detalles de bajo nivel que tienen poco que ver con la intención de alto nivel de su código.

0

No encuentro el ejemplo ofuscado.

En primer lugar, la intención es tan dolorosamente clara, que un novato es más probable de aprender lo que hace una lambda que no entender el código. Cuál es el lugar perfecto para usar las técnicas más "avanzadas", donde incluso alguien que no tiene ni idea de lo que hace entiende lo que "debería" hacer.

En segundo lugar, todo lo anterior no solo no está ofuscado, son perfectamente idiomáticos C#. El último podría decirse que no tanto por el uso no tan extenso de Array.ForEach, que la mayoría de las personas (con las que he trabajado) utilizarían LINQ.

Cuestiones relacionadas