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?
design-patterns
anti-patterns
P.Brian.Mackey
fuente
fuente
Respuestas:
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" :-)
fuente
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-a
relació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.
fuente
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.
fuente
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".
fuente
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
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:
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.
fuente
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.
fuente
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.
fuente
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
fuente
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.
fuente
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.
fuente
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 ".
fuente