Sabotear los estándares de codificación [cerrado]

35

Existen varias normas de codificación aplicadas en las compañías de software que tienen el objetivo de aumentar la confiabilidad, la portabilidad y, lo más importante, la legibilidad del código escrito conjuntamente por diferentes desarrolladores.

Dos ejemplos notables son el MISRA C y el estándar C ++ desarrollado para el proyecto JSF .

Por lo general, están en la siguiente forma, después de especificar cuidadosamente lo que significan las palabras "debe", "deberá", "debería", "podría", etc.

Ejemplo:

Regla 50: Las variables de coma flotante no se evaluarán para determinar la igualdad o desigualdad exactas.

Justificación: Dado que los números de coma flotante están sujetos a errores de redondeo y truncamiento, es posible que no se logre la igualdad exacta, incluso cuando se espera.

Estas normas de codificación imponen restricciones, generalmente en el código que sería legal desde el punto de vista del compilador, pero es peligroso o ilegible y, por lo tanto, "se considera dañino".

¡Ahora abusemos de esto!

Usted es aceptado como miembro de un pequeño comité de estandarización en su empresa, que está diseñado para diseñar los nuevos estándares de codificación que cada desarrollador de la empresa deberá usar. Sin que los demás lo sepan, usted está secretamente al servicio de una organización siniestra y tiene como misión sabotear la empresa. Debe proponer una o más entradas al estándar de codificación que luego obstaculizará a los desarrolladores. Sin embargo, debe tener cuidado de no hacer esto inmediatamente obvio, de lo contrario corre el riesgo de que no sea aceptado en el estándar.

En otras palabras, debe introducir reglas para el estándar de codificación que parezcan legítimas y tengan una buena posibilidad de ser aceptadas por los otros miembros del comité. Después se ponen en marcha los proyectos y un sinnúmero de horas-hombre se invierten en el código, que debe ser capaz de abusar de estas normas (por ejemplo, por un detalle técnico, o por una muyinterpretación literal) para marcar el código normal y de buena calidad como contrario al estándar. Por lo tanto, deben hacer un gran esfuerzo para rediseñarlo, y las reglas los obstaculizarán a partir de este momento, pero como las reglas están activas durante bastante tiempo, el impulso puro mantendrá vivos estos roles, y como hay conflictos significativos de intereses entre los diferentes niveles de gestión, los otros gerentes probablemente mantendrán las reglas vivas (¡serían tontos si admitieran su error!), lo que obstaculizaría la empresa. Mwahahahahaaa!

Tanteo

La respuesta más votada después de aproximadamente 2 semanas desde la primera entrada válida gana. Tengo una idea para una buena respuesta, pero solo la publicaré unos días después, ya que alguien más podría tener la misma idea, y no quiero robarles el placer. Por supuesto, mi propia respuesta no será aceptada por encima de ninguna otra, sin importar el puntaje.

Se alienta a los votantes a calificar las respuestas en función de qué tan bien están ocultas las lagunas y lo frustrantes que serían para los desarrolladores.

Reglas y regulaciones

  • La regla o reglas deben verse escritas profesionalmente, como en el ejemplo anterior
  • Las reglas deben verse genuinas (por lo que no se aceptan cosas como "todas las variables deben contener al menos un guión bajo, una letra mayúscula, una letra minúscula y dos números" . De hecho, obstaculizarían a los desarrolladores, pero probablemente no serían aceptadas por el comité) y si su mérito no es inmediatamente obvio, debe dar una buena justificación.
  • Debería poder encontrar una manera de usar / abusar de sus reglas para sabotear a los desarrolladores más adelante. Puede abusar de cualquier ambigüedad en otras reglas, o puede usar múltiples reglas que son inofensivas por sí mismas, ¡pero diabólicas una vez combinadas!
  • Debe publicar una explicación en las etiquetas de spoiler al final de su publicación sobre cómo podría abusar de las reglas
  • El lenguaje utilizado no debe ser un lenguaje esotérico. Se debe elegir un lenguaje ampliamente utilizado en proyectos reales, por lo que se prefieren los lenguajes con sintaxis tipo C (en lugar de cosas como Golfscript).
vsz
fuente
44
Python, Ruby, Haskell, Makefile, XML, etc. son algunos lenguajes utilizados en muchos proyectos reales que no tienen una sintaxis tipo C.
kennytm
77
Esta pregunta parece estar fuera de tema porque no es un concurso de programación.
Peter Taylor
55
@PeterTaylor: la definición incluye "Programación de rompecabezas", lo que no significa que la respuesta deba ser un código de software. En ninguna parte de la definición del sitio se escribe que solo se trata de "concursos de programación". La definición es: "Código de golf / Rompecabezas de programación / Otros concursos o desafíos de programación" "
vsz
77
@PeterTaylor me parece un concurso de programación; en desafíos de policías y ladrones, los ladrones tampoco codifican (y si su argumento es que los ladrones comentan, asegúrese de comentar en la meta publicación que sugiere dividir los desafíos de policías y ladrones en dos preguntas separadas)
John Dvorak
55
Voté para reabrir. Parece que todavía tenemos algunas preguntas en las que no podemos acordar si están en el tema. Esto me recuerda a ese arte relacionado con uno que se cerró y luego se volvió a abrir dos veces. Tengo una idea para una respuesta a esta pregunta y definitivamente está relacionada con la programación. Esta pregunta incluso se ajusta a 2 de las etiquetas en el sitio.
hmatt1

Respuestas:

40

C / C ++

Regla 1: no se utilizarán constantes octales

Justificación: las constantes octales pueden ser causa de confusión. Por ejemplo, una mirada casual sobre la línea const int coefficients[] = {132, 521, 013, 102};
puede pasar por alto el hecho de que uno de los números en la matriz está definido en octal.

Si quieres ser aún más malvado, agrega lo siguiente:

Regla 2: las constantes hexadecimales solo se utilizarán en el contexto de la manipulación de bits.

Justificación: si una constante representa un valor numérico, es más legible si está en decimal. Una constante hexadecimal debería indicar que representa una máscara de bits, no un valor numérico.

Cómo puede ser abusado:

Tome el siguiente programa simple que agregará los primeros 10 elementos de una matriz. Este código no sería conforme a la norma.

sum = 0;
for (i = 0; i < 10; i++) 
{
    sum += array[i];
}

Tenga en cuenta que 0es, por definición, una constante octal. Según la regla 1, es frustrante requerir que se escriba como 0x00 en todo el código. Según la regla 2, aún más frustrante.

vsz
fuente
1
¿Podría vincular a la definición estándar de codificación que dice que 0es una constante octal? Supongo que es porque comienza con el personaje 0. Fortalecería el argumento de su hipotético pedante.
xnor
16

Pitón

Regla 1: Todo el código debe compilarse en bytes utilizando el -OOindicador, que optimiza el código de bytes . ¡Queremos un bytecode optimizado para tamaño y eficiencia!

Regla 2: Las pruebas deben ejecutarse contra el mismo "artefacto" de código que se pondrá en producción. Nuestros auditores requieren esto.

Usar -OOelimina assertdeclaraciones. Combinado con la regla 2, esto prohíbe efectivamente el uso de assertdeclaraciones en las pruebas. ¡Que te diviertas!

ErlVolton
fuente
Esto también elimina las cadenas de documentos, lo que significa que no obtiene nada de help()REPL, y las pruebas REPL informales aún se están probando.
Kevin
No Si escribe un marco de prueba adecuado, utilizará el unittestmódulo o, que implementa sus propias afirmaciones sin depender del __debug__indicador. Doctests silenciosamente no se ejecutará sin embargo. ¡Furtivo!
pppery
15

Esto es para un proyecto Node.JS.

Sección 3 - La velocidad y la eficiencia son esenciales

Regla 3.1: Los archivos deben mantenerse a un máximo de 1 kb. Los archivos más grandes que este tardan demasiado en analizarse.

Regla 3.2: No anidar funciones de más de 3 niveles de profundidad. El motor V8 debe realizar un seguimiento de muchas variables, y los cierres profundos como este hacen que trabaje más duro, ralentizando la interpretación general.

Regla 3.3: Evitar las require()retenciones.

Regla 3.3.1: Cualquier módulo require()d no debe tener require()una profundidad de más de 3. Las require()cadenas profundas son caras tanto en términos de uso de memoria como de velocidad.

Regla 3.3.2: Los módulos principales cuentan como un solo require(), sin importar cuántas veces lo require()hagan internamente.

Regla 3.3.3: Los módulos externos cuentan como un máximo de 2 require()s. No podemos permitirnos la misma indulgencia que con los módulos principales, pero podemos suponer que los autores de los módulos están escribiendo un código eficiente.

Regla 3.4: Evite llamadas síncronas a toda costa. Estos a menudo tardan mucho tiempo y bloquean la continuación de todo el ciclo de eventos.

Cómo puede ser abusado:

Las reglas 3.1 y 3.3 no funcionan bien juntas. Al mantener un máximo de 1kb y 3 require()s en la cadena, será difícil tener éxito.
Las reglas 3.2 y 3.4 son casi incompatibles. 3.4 prohíbe las llamadas síncronas; 3.2 dificulta el trabajo asincrónico avanzado al limitar el número de devoluciones de llamada.
La regla 3.4 es, con toda honestidad, una regla que es bueno seguir de verdad. 3.1, 3.2 y 3.3 son completamente falsos.

Scimonster
fuente
11

JavaScript (ECMAScript)

7.3.2: Literales de expresión regular

No se deben usar literales de expresiones regulares. Específicamente, el código fuente no debe contener ninguna subcadena que coincida con el no terminal RegularExpression definido a continuación.

RegularExpression     :: '/' RegularExpressionBody '/'
RegularExpressionBody :: [empty]
                         RegularExpressionBody [any-but-'/']

[empty] coincide con la cadena vacía y [any-but - '/'] coincide con cualquier cadena de un solo carácter, excepto la que contiene '/' (barra inclinada, U+002F).

Razón fundamental

Las expresiones regulares a menudo se desaconsejan por razones de legibilidad. A menudo es más fácil entender el código con operaciones de cadena tradicionales en lugar de recurrir a expresiones regulares. Sin embargo, lo que es más importante, muchos motores de expresión regular ofrecen un rendimiento inferior. Las expresiones regulares también se han asociado con problemas de seguridad en el contexto de JavaScript.

Sin embargo, la Organización ™ reconoce que las expresiones regulares de vez en cuando es la mejor herramienta para el trabajo. Por lo tanto, el RegExpobjeto en sí no está prohibido.

(La sintaxis del extracto de gramática en sí [no la que define] corresponde a la de la especificación ECMAScript. Por supuesto, esto se definiría de manera más rigurosa en otro punto de la especificación hipotética).

El truco

El siguiente programa no es conforme:

// sgn(x) is -1 if x < 0, +1 if x > 0, and 0 if x = 0.
function sgn(x) {
  return x > 0?  +1
       : x < 0?  -1
       :          0
}

Las producciones para el terminal no regular RegularExpressionBody que se muestran arriba muestran una forma común de expresar listas en BNF confiando en la recursividad explícita. El truco aquí es que "accidentalmente" permito la cadena vacía como RegularExpressionBody , de modo que la cadena //está prohibida en el código fuente. Pero, ¿quién necesita comentarios de una sola línea de todos modos? C89 y CSS parecen funcionar bien y solo permiten /* */bloquear comentarios.

Luciérnaga
fuente
15
En realidad, es aún más malvado que eso: el código tampoco puede contener comentarios de bloque, ni más de un operador de división por archivo.
Chromatix
Oh sí, tienes razón. Ni siquiera pensé en eso. : P
FireFly
5

DO#

12.1 Los métodos estáticos que afectan el estado del programa están prohibidos

Esto se debe a que es difícil probar de manera confiable los resultados de un método estático, especialmente uno que cambia algún estado.

12.2 Los métodos estáticos deben ser deterministas

Si el método estático toma una entrada y da una salida, el resultado debe ser el mismo cada vez que se llama al método estático con la misma entrada.

Por qué

El punto de entrada para un programa C # es el método estático privado 'main'. Según la primera regla, esto ahora está prohibido porque la regla olvida indicar que solo los métodos públicos, protegidos o internos deben seguir esta regla. Si la prueba es realmente la preocupación, solo los métodos públicos deben seguir la regla 1. Main también puede romper la regla 2 ya que el programa dará un código de error si el programa falla, esto puede ocurrir independientemente de los parámetros de entrada. Por ejemplo, el programa podría no encontrar un archivo o tener dependencias de otros sistemas que no están configurados correctamente.

sydan
fuente
4

JAVA / PRIMAVERA

4.2 Uso de la reflexión en el código de producción

Debido a que Reflection se puede utilizar para acceder a partes restringidas de nuestro código fuente, el uso de la reflexión en el Código de producción está estrictamente prohibido.

El truco

Spring utiliza técnicamente la reflexión para crear instancias y administrar los objetos que admite. Al hacer cumplir esta regla, toda la utilidad Spring debería eliminarse.

tfitzger
fuente
3

Codificación del sitio web

666.13 UTF-8 no debe usarse y debe ser reemplazado por UTF-7
Justificación: UTF-7 es más eficiente que UTF-8, especialmente cuando se dirige a usuarios de países árabes que hacemos.

Cómo puede ser abusado:

HTML5 específicamente no permite UTF-7. Eso significa que los navegadores modernos no lo admitirán. Si todas las pruebas se realizan en un navegador como IE 11, nadie lo notará hasta que sea demasiado tarde.

Stefnotch
fuente
2

Operadores a nivel de bits de JavaScript

1.9 No debe usar multiplicación o división o piso a menos que sean considerablemente más rápidos que sus contrapartes bit a bit. Serán reemplazados por los operadores bit a bit <<, >> y ~~ respectivamente.
Justificación: los operadores bit a bit son más eficientes.

Cómo puede ser abusado:

Usar << o >> en lugar de multiplicación o división causará problemas al manejar números grandes. Además, ignoran la precedencia de la operación y los puntos decimales. La doble tilde devolverá diferentes valores cuando le des un número negativo.

Stefnotch
fuente
2
Creo que ya es obvio que x = (x<<10) + (x<<8) + (x<<5) + (x<<4) + (x<<3) + (x)es inferior en todos los sentidos (posiblemente incluso la velocidad) x *= 1337y que reemplazar la división por un no poder de dos con sumas de cambios de bits es aún peor.
lirtosiast
@Thomas Kwa Edité mi respuesta apropiadamente. Gracias por señalar esto. Soy nuevo en operadores bit a bit.
Stefnotch
1

JavaScript (ECMAScript)

7.3.1: Convenciones de identificación

Se aplican restricciones a los identificadores según el tipo de identificador que sea. Los identificadores se dividen en los tipos Variable , Constante , Función y Constructor ; ver 5.3. Las restricciones se dan a continuación.

  • Variable: el primer carácter debe ser una letra minúscula. Camel-case (ver 1.3) debe usarse para separar palabras dentro de un identificador.

  • Constante: el identificador debe constar solo de letras mayúsculas y guiones bajos ('_', U+005F). Los guiones bajos deben usarse para separar palabras dentro de un identificador.

  • Función: las funciones deben seguir las mismas reglas que el tipo de identificador .

  • Constructor: el primer carácter debe ser una letra mayúscula. Camel-case (ver 1.3) debe usarse para separar palabras dentro de un identificador.

Razón fundamental

Los nombres de identificadores legibles son muy importantes para la mantenibilidad. Restringir los identificadores a convenciones bien conocidas también facilita la transición entre diferentes bases de código. Estas convenciones particulares se modelan a partir de las convenciones estándar para el lenguaje de programación Java ™ [1] .

El truco

Lamento informar al equipo de jQuery que el nombre más común para su "objeto jQuery global" choca con esta convención de nombres. Afortunadamente, ya han pensado en eso y proporcionan ambos $y jQuerynombres globales que se refieren al mismo objeto. Sin embargo, me imagino que la base de usuarios podría no ser tan entusiasta como para cambiar $a jQuerytodas partes.

Luciérnaga
fuente
2
»Las funciones deben seguir las mismas reglas que el tipo de identificador .« - ¿te refieres a »como el tipo de variable «?
Paŭlo Ebermann