¿Cuáles son los peores antipatrones que has encontrado en tu carrera como programador?
Estoy principalmente involucrado en Java, aunque probablemente sea independiente del idioma.
Creo que lo peor es lo que llamo el antipatrón principal . Significa un programa que consiste en una sola clase extremadamente grande (a veces acompañada con un par de clases pequeñas) que contiene toda la lógica. Por lo general, con un gran bucle en el que está contenida toda la lógica empresarial, a veces con decenas de miles de líneas de código.
language-agnostic
anti-patterns
стривігор
fuente
fuente
Golpearé otro obvio con "copy-pasta". Copiando código que es casi idéntico a lo que desea, luego cambiando algunas cosas (en lugar de extraerlo en un método).
Esto es especialmente frecuente en algunos códigos de prueba funcionales y API de finales de los 90: literalmente cientos (o incluso miles) de casos de prueba casi idénticos que podrían haberse dividido en algunas funciones que toman 3 o 4 parámetros, o incluso mejor , algo basado en datos. Mi primer trabajo fuera de la universidad fue, literalmente, 8 meses de reescritura y refactorización de miles de líneas de pasta de copia que usaban métodos obsoletos. Cuando terminé, los archivos de prueba tenían menos de una décima parte de su tamaño original y mucho más fáciles de mantener (¡y legibles!).
fuente
Creo que puedo escribir mucho sobre Pattern Mania y las soluciones que podrían resolverse con mucho menos esfuerzo, pero prefiero señalar un excelente artículo que he leído recientemente con un fantástico ejemplo de cómo una solución simple puede complicarse demasiado .
Cómo (no) escribir Factorial en Java o eso ponemos una fábrica en su algoritmo
fuente
Martillo de oro
fuente
Regiones
En C # puede definir una región de código que se puede contraer en el IDE, ocultándola a menos que desee lidiar con ese código. He estado en (actualmente estoy en) un proyecto en el que las regiones abarcaban cientos de líneas (ojalá estuviera exagerando) y había varias regiones en una función de mil líneas (nuevamente deseo estar bromeando).
Por el lado positivo, el desarrollador que hizo la región hizo un muy buen trabajo al identificar funciones específicas dentro de una región. Tanto es así que pude hacer un método de extracción en la región y seguir adelante.
Las regiones alientan a los desarrolladores a "ocultar" su basura a simple vista.
fuente
DoNotUseRegions
.#region SQL Update
hace plegable, por lo que se requiere menos desplazamiento.Para mí, el peor patrón es Copiar / Pegar .
fuente
No sobrecargar los métodos:
Muestra claramente que el programador no entendió la sobrecarga.
fuente
Secuencias de cambio de bucle
http://en.wikipedia.org/wiki/Loop-switch_sequence
Me molestan hasta el infinito y realmente muestran cuán inexperto era el desarrollador
fuente
Codificación suave , es decir, cuando los programadores hacen todo lo posible para evitar la codificación dura y terminan en el otro lado de la escala: dependencias "codificadas".
fuente
Mantener el estado en el cliente.
Una vez trabajado con una aplicación web donde todo el estado se mantuvo en el navegador. (Para garantizar una escalabilidad sin problemas, se ignoraron todas las excepciones).
fuente
Registros masivos
Odio cuando veo que un desarrollador no ha hecho un check-in en más de una semana. Significa que está atascado y no ha buscado ayuda, o está agrupando un montón de características en un gran check-in. (Dejé el peor de los casos, él simplemente no está haciendo nada. Eso es fácil de resolver ... dos palabras suenan como si estuvieras contratado).
Si realiza un gran check-in, pierde muchos beneficios de SCM, como poder vincular un conjunto de cambios a una característica específica. Además, es probable que tenga que fusionarse mucho y eso no es necesariamente fácil de hacer.
fuente
Actualmente, estoy trabajando con un código heredado y me encanta la forma en que el codificador anterior obtiene el primer elemento de una lista:
Pero lo peor que he visto en este código es definir páginas JSP en línea de clases, escribir todo el HTML, CSS y Javascript usando scriptlet y out.println :-(
fuente
Uno de los peores patrones contra el comportamiento que he visto fue una tienda que solo permitía que el código se registrara en el control de versiones después de que estaba en producción. Junto con los pagos exclusivos en VSS, esto condujo a un proceso complicado de deshacer los pagos si un defecto de producción necesita ser corregido antes de la próxima versión, y mucho menos que una persona necesite cambiar un archivo dado para la próxima versión.
El hecho de que se tratara de una política departamental lo hizo aún peor que el caso de un solo desarrollador que se comportara de esta manera.
fuente
Bloqueo en un literal de cadena
Nombres de clase muy largos. (en el JRE)
Mala estructura de herencia
Una excepción que no lo es.
Manejo de errores sin sentido y críptico
Creación innecesaria de objetos.
Lanzar una excepción para otros fines
Uso de objetos de instancia para métodos estáticos.
Sincronización en un campo no final
Copia sin sentido de una cadena constante
Llamada inútil a String.toString ()
Llamadas a System.gc () para liberar algo de memoria
Establecer la variable local en nulo para liberar algo de memoria
Usar ++ i en lugar de i ++ por razones de rendimiento (o cualquier otra micro-micro-optimización)
fuente
Código rociado con:
o
sin información adicional
fuente
Iterador para tontos:
Singletono-Factory:
desarrollo impulsado por if-else (también llamado principio de cierre cerrado - abierto para modificación cierre para comprensión)
StringPattern (también llamado StringObject):
fuente
else if
embargo, esa es a menudo la única forma de hacer las cosas. Estoy pensando en cuerdas; No puedo usar un interruptor. Las condiciones deben ser iguales para que sea útil.getInstance
devuelve la misma instancia. Tal suposición rompería la encapsulación y, de hecho, es uno de los antipatrones más comunes.No es tanto un patrón de codificación sino un patrón de comportamiento, aunque es bastante malo: modificar algo en el código (digamos que los requisitos cambiaron), luego ajustar todas las pruebas unitarias hasta que el código lo apruebe. Ajustar o simplemente eliminar todo el código de prueba del método de prueba, pero dejar el método allí.
Sin embargo, esto está vinculado a uno más genérico, el patrón That'll Do , aquí hay una línea de código representativa para ello:
Funciona, después de todo.
fuente
Desprecio absolutamente la inversión de abstracción o la reinvención de primitivas de bajo nivel además de las primitivas de alto nivel. A veces, sin embargo, esto es causado por diseñadores de lenguaje malos, no por malos programadores. Ejemplos:
Usar una sola clase de método sin variables miembro y una interfaz correspondiente (implementada en términos de tablas de punteros de función), en lugar de un puntero de función. Tenga en cuenta que en lenguajes como Java, es posible que no tenga otra opción.
En MATLAB y R, la insistencia en que todo es un vector / matriz en lugar de un primitivo.
Mientras atacamos MATLAB, ¿qué tal el hecho de que no tiene enteros, por lo que cuando necesita un entero tiene que usar un doble?
Lenguajes puramente funcionales donde tienes que usar llamadas de función para escribir un bucle.
fuente
Definitivamente sería copiar / pegar, he visto una gran cantidad de código incorrecto debido a eso, eso y la codificación de vaquero y todo lo que se deriva de eso. (Clases de Dios, métodos extra grandes, algoritmos mal pensados, etc.)
Y si se permiten patrones de diseño, yo diría: Hacer un proyecto como un conjunto de acciones de un plan, sin hacer ningún diseño o análisis de dominio.
fuente
Frijol Java multiuso -
Un bean Java con muchas variables, utilizado en algunos tipos diferentes de operaciones. Cada operación utiliza un subconjunto arbitrario de las variables de bean e ignora las demás. Algunas variables para el estado de la interfaz gráfica de usuario, algunas variables para pasar entre los componentes, algunas que probablemente ya ni siquiera se usan. Los mejores ejemplos no tienen documentación, lo que dificultaría la apreciación del patrón.
Además, no puedo olvidar a la amada
fuente
Un antiguo compañero de trabajo tenía la costumbre de reutilizar objetos sobrescribiendo sus propiedades, en lugar de simplemente crear otras nuevas. Nunca podría haber imaginado la cantidad de problemas que esto ha causado al implementar nuevas funciones.
fuente
Algo que me ha causado mucho dolor es el patrón "Gran mapa en el cielo". Lanzar un mapa en lugar de usar los objetos adecuados. No tiene idea de qué "variables" contiene sin depurar, y no sabe qué podría contener sin rastrear el código hacia atrás. Por lo general, asigna cadenas a objetos o cadenas a cadenas, que se supone que debe analizar en primitivas.
fuente
Uno de mis anti patrones de desarrollo favoritos es el uso de un "diseño" de base de datos que requiere la adición continua de columnas adicionales a una o más tablas mediante programación . Este es un primo del "diseño" que crea una nueva tabla para cada instancia de una entidad. Ambos inevitablemente golpean las limitaciones del servidor de la base de datos, pero generalmente no hasta que el sistema ha estado en producción durante bastante tiempo.
fuente
Creo que uno de los peores antipatrones que he visto implica el uso de una tabla de base de datos como almacenamiento temporal en lugar de usar la memoria de la computadora.
El dominio del problema es propietario, lo que me impide explicarlo, pero no es necesario comprender el problema básico. Esta fue una aplicación GUI escrita en Java con una base de datos de back-end. Era tomar ciertos datos de entrada, manipularlos y luego confirmar los datos procesados en la base de datos.
Nuestro proyecto tiene un algoritmo bastante complicado que guarda valores intermedios para su procesamiento posterior. En lugar de encapsular los objetos temporales en ... objetos, se creó una tabla de base de datos como "t_object". Cada vez que se calculaba un valor, se agregaba a esta tabla. Una vez que el algoritmo haya terminado su trabajo, seleccionaría todos los valores intermedios y los procesaría todos en un objeto Map grande. Una vez finalizado todo el procesamiento, los valores restantes que se marcaron como guardados se agregarán al esquema de la base de datos real y las entradas temporales en la tabla "t_object" se descartarán.
La tabla también se usó como una lista única, los datos solo podían existir una vez. Esta podría haber sido una característica decente del diseño si hubiéramos implementado Restricciones en la tabla, pero terminamos iterando en toda la tabla para ver si los datos existían o no. (No, ni siquiera usamos consultas que usaban cláusulas where con CONTAINS)
Algunos de los problemas que encontramos debido a este diseño fueron específicamente la depuración. La aplicación se creó para canalizar datos, por lo que habría múltiples interfaces gráficas de usuario que procesarían los datos antes de llegar a este algoritmo. El proceso de depuración consistió en procesar un caso de prueba y luego hacer una pausa justo después de terminar la sección anterior. Luego consultaríamos la base de datos para ver qué datos estaban contenidos en esta tabla.
Otro problema que descubrimos fue que los datos no se eliminaban correctamente de esta tabla temporal, lo que interferiría con la ejecución en el futuro. Descubrimos que esto se debía a que las Excepciones no se manejaban correctamente y, por lo tanto, la aplicación no salía correctamente y no borraba los datos de la tabla que controlaba.
Si hubiéramos utilizado el diseño orientado a objetos básicos y guardado todo en la memoria, estos problemas anteriores nunca hubieran ocurrido. Primero, la depuración habría sido simple, ya que podríamos configurar fácilmente puntos de interrupción en la aplicación y luego inspeccionar la memoria en la pila y el montón. En segundo lugar, al salir anormalmente de la aplicación, la memoria de Java se habría limpiado naturalmente sin tener que preocuparse por eliminarla de la base de datos.
NOTA: No digo que este patrón sea intrínsecamente malo, pero en este ejemplo me pareció innecesario cuando los principios básicos de OO hubieran sido suficientes.
No estoy seguro de un nombre para este antipatrón, ya que es la primera vez que veo algo así. ¿Algún buen nombre que ustedes puedan pensar para este patrón?
fuente
Cart-Before-The-Horse - también conocido como YouMightNeedIt
Por ejemplo:
fuente
En mi opinión, el peor antipatrón que he visto es el antipatrón "No necesitamos ningún patrón apestoso": la idea de que los patrones de diseño son una pérdida de tiempo y que puedes escribir código más rápido simplemente mezclándolo y copiando / pegar según sea necesario.
Mención de honor va a tener código que carga un objeto de la base de datos usando el viejo estilo VB6 de:
no es realmente un antipatrón, per se, pero muestra una falta de aprovechamiento de la arquitectura adecuada y la separación de preocupaciones.
Además, cosas como esta:
fuente