¿Existe un antipatrón para describir este método de codificación? [cerrado]

26

Tengo una base de código donde el programador tendía a envolver las cosas en áreas que no tienen sentido. Por ejemplo, dado un registro de errores que tenemos, puede iniciar sesión mediante

ErrorLog.Log(ex, "friendly message");

Agregó varios otros medios para lograr exactamente la misma tarea. P.EJ

SomeClass.Log(ex, "friendly message");

Que simplemente da la vuelta y llama al primer método. Esto agrega niveles de complejidad sin beneficio adicional. ¿Hay un antipatrón para describir esto?

P.Brian.Mackey
fuente
36
"Bad coding" lo cubre;)
Oded
12
Depende ¿Es un contenedor para una biblioteca de registro? Si alguna vez hubo la posibilidad de que se pudiera cambiar, esta es una buena práctica ...
Rig
3
@lortabac: El problema con el "código baklava" es que en realidad suena bien y sabroso, y por lo tanto deseable.
FrustratedWithFormsDesigner
10
¿Qué dice este programador cuando los agrega por qué están agregando estos métodos? Comprender su razonamiento debería facilitar su educación.
Keith
3
Suena como un nivel de indirección , que puede ser bueno cuando desea evitar el acoplamiento entre dos clases, como señaló @Rig. Quizás fue solo un codificador que sufría de patternitis , simplemente probando algún patrón para resolver un problema que no está allí, violando KISS.
Fuhrmanator

Respuestas:

54

Solo vale la pena llamar a algún mal hábito de codificación Antipatrón si está bastante extendido.

El resto lo llamamos "código basura" ...


Si tuviera que sugerir un nombre para este mal hábito en particular, sería "Trastorno de abstracción obsesiva" :-)

Stephen C
fuente
99
Siempre he usado "Infierno de Indirección".
Dan Neely
27

No, no es un anti patrón, pero plantearía los siguientes problemas.

Violación del principio de responsabilidad única

SRP dice que una clase debería tener una razón para cambiar. Agregar un método de registrador significa que la clase también tiene que cambiar si se debe cambiar la lógica de registro.

Violación de una is-arelación.

Las clases base no son cajas de herramientas donde puede agregar varios métodos convenientes.

Al hacerlo, se combinan efectivamente todas las clases heredadas con las implementaciones que tiene la clase base.

Compara eso con la composición.

jgauffin
fuente
1
¿"Cuestión de responsabilidad única"? SRP? ¿Quizás quiso escribir el Principio de responsabilidad única? Solo conectando los dos aquí. :)
zxcdw
8

No es que esto lo haga aceptable, pero esto podría ser una refactorización inacabada. Tal vez SomeClass.log () tenía su propia lógica y se implementó primero. Y luego se dieron cuenta de que deberían estar usando ErrorLog.Log (). Entonces, en lugar de cambiar 100 lugares donde se llama SomeClass.Log (), simplemente delegaron en ErrorLog.Log (). Personalmente, cambiaría todas las referencias a ErrorLog.Log () o al menos comentaría SomeClass.log () para decir por qué delega la forma en que lo hace.

Solo algo a tener en cuenta.

Heath Lilley
fuente
7

El término "Código de lasaña" me viene a la mente, aunque aparentemente significa cosas diferentes para diferentes personas . Mi interpretación siempre ha sido "en capas por el bien de las capas".

dasblinkenlight
fuente
3
También escuché "Onion Code" para describir lo mismo.
Justin Niessner
4

No estoy seguro de describir esto como una ofensa al principio de responsabilidad única, porque si hay un cambio en la firma del método ErrorLog (el método que es llamado por SomeClass), cada código de cliente que llame a este método fallará.

Obviamente, hay una manera de usar la herencia (o hacer clases que necesitan un registro implementando una interfaz de registro) allí.


fuente
Todavía es una mala práctica porque: 1) es poco probable que cambie 2) si cambia, simplemente pueden construir una clase de contenedor con el mismo nombre y cambiar las importaciones.
Kevin Cline
2
+1. Y aquí está el "Tío Bob" (Robert Martin) argumentando a favor de centralizar las dependencias en un número limitado de módulos, en lugar de dispersarlos a través del código.
MarkJ
3

O podríamos ver esto como un "momento de enseñanza" :)

Su desarrollador puede estar a medio camino de una buena idea. Suponga que desea tener el requisito de que todos sus objetos comerciales sean capaces de realizar un registro inteligente. Puedes definir:

   public interface IBusinessObjectLogger
   {
       void Log(Exception ex, string logMessage)
   }

Ahora interno a sus objetos, puede usar el objeto ErrorLog para hacer el registro mientras que el código SomeClass agrega un valor específico del objeto al mensaje de registro. Luego, puede ampliar aún más sus API de registro para implementar la funcionalidad de registro basada en archivos, db o mensajes sin tocar sus objetos comerciales.

cdkMoose
fuente
3

No estoy seguro de que esto sea automáticamente malo.

Si está llamando a SomeClass. Log ciertamente es malo, pero si Log solo se usa desde WITHIN SomeClass, está cortando el acoplamiento y lo llamaría aceptable.

Loren Pechtel
fuente
2

En realidad, esto es bastante común en ciertos estilos de codificación, y los conceptos básicos de la línea de pensamiento no son, en sí mismos, un antipatrón.

Es muy probable que sea el resultado de que alguien codifique por necesidad sin conocimiento de la base de código más amplia: "OK, este código necesita registrar un error, pero esa función no es el propósito principal del código. Por lo tanto, necesito un método / clase que lo haga para mi". Esa es una buena forma de pensar; pero, sin saber que existía ErrorLog, crearon SomeClass. Luego encontraron ErrorLog en algún momento posterior, y en lugar de reemplazar todos los usos del método que habían introducido, hicieron que su método se llamara ErrorLog. Ahí es donde esto se convierte en un problema.

KeithS
fuente
2

La complejidad accidental es la complejidad que surge en los programas de computadora o su proceso de desarrollo que no es esencial para el problema a resolver. Si bien la complejidad esencial es inherente e inevitable, la complejidad accidental es causada por el enfoque elegido para resolver el problema.

http://en.wikipedia.org/wiki/Accidental_complexity

JoelFan
fuente
1

Puede ser un abuso / malentendido del patrón de fachada . He visto cosas similares en una base de código con la que he trabajado. Los desarrolladores pasaron por una fase cuando estaban locos por los patrones de diseño sin comprender los principios generales del diseño OO.

Un mal uso del patrón de Fachada da como resultado un desenfoque de los niveles de abstracción en las capas de la aplicación.

Kazark
fuente
1

Lo que está haciendo este programador es envolver algo de código, de modo que no tenga una dependencia directa en el módulo de registro. Sin información más específica, no es posible dar un patrón más específico. (Que estos envoltorios no son útiles es su opinión, que es imposible estar de acuerdo o en desacuerdo sin mucha más información).

Los patrones a los que se puede aplicar son Proxy , Delegado , Decorador , Compuesto o algunos que tienen que ver con envolver, ocultar o distribuir llamadas. Puede una de esas cosas en un estado incompleto de desarrollo.

Kaz
fuente
0

Me imagino que es una diferencia cultural. Quizás haya una buena razón para tener una funcionalidad duplicada en esta base de código en particular. Podría imaginar la facilidad de escritura para ser una razón. El programador de Python en mí aún diría que es malo, ya que " Debería haber una, y preferiblemente solo una, forma obvia de hacerlo ", pero algunos chicos de Perl podrían estar acostumbrados al hecho de que " hay más de uno forma de hacerlo ".

Bengt
fuente
1
La facilidad de la escritura inicial no es una buena razón para la duplicación. El código incorrecto puede ser más fácil de escribir la primera vez, pero eso no hace que sea más fácil escribir código a largo plazo. ¿Qué hace el nuevo chico que viene con la funcionalidad duplicada? ¿A qué método llama? Pierde el tiempo buscándolos y leyéndolos, solo para descubrir que hacen lo mismo.
Kazark
Tal vez este código se pensó originalmente como un prototipo que luego se usó (ab) como un incremento. En ese caso, creo que la optimización para la escritura inicial habría sido válida.
Bengt