A Few Uncommon Design Smells

We started working on design smells many years earlier than when we started writing our book “Refactoring for Software Design Smells”. I was digging through some of the old documents and remembered that we did not cover many smells, considering them to be “uncommon smells”. By “uncommon smells”, I mean the ones that we (co-authors of the book) hadn’t seen commonly occurring in software projects, and so did not think that they were worth discussing in detail in the book. We toyed with the idea of listing them in an appendix in the book, but dropped that idea because some readers could object the selection of the smells that formed the core of the book; for example, readers may question the choice of smells covered in the book, and may consider some of the smells mentioned as “uncommon smells” as common in their projects!

Given the fact that it’s been a couple of years since the book was published, I thought it would be interesting to see what you think about these smells. So with that, here are some of the smells that did not make it to our book. If this article generates much interest, I can post more smells in future articles!

Excessive Encapsulation

This smell arises when an abstraction has excessive encapsulation, thereby affecting its usability (almost all its members are private, including methods). Also known by names “exceeded method hiding”, “poor interface”, and “too much information hiding”.

Deceptive Modularity

This smell arises when the dependency relationship between class-level abstractions appears like a tree. This is indicative of functionality based decomposition (instead of following “information-hiding” based decomposition). Also known by names “tree-like dependency graphs” and “function class”.

Trespassing Encapsulation

This smell arises when a class-level abstraction directly accesses the implementation details of other abstractions, breaking encapsulation of other abstractions. We have seen instances, for example, when the client code uses the reflection facility (in languages that support reflection, like Java and C#) to access implementation details of other classes. Not just that, the client code also often has code that depends on those implementation details. Of course, the trouble with this smell is when the implementation details change, the client code breaks.

Degraded Hierarchy

This design smell arises when the hierarchy tends to be more concrete towards the root and more abstract towards the leaves. This smell includes the case where the supertype is declared concrete and the subtype is declared abstract.

Aberrant Hierarchy

This smell arises when the base abstractions provide many concrete methods, and derived abstractions do not override those concrete methods. This indicates the use of inheritance primarily for code reuse, deviating from the widely-accepted norm of using inheritance to model IS-A relationships.

Incomplete Hierarchy

This smell arises when one or more leaves of a hierarchy are abstract (indicating that the hierarchy is incomplete). Classes that are declared abstract should have subclasses (that inherit from the abstract class). This design smell could arise when the designer or developer plans to realize some functionality and started with creating the abstractions, but never realized them. However, note that this may not be a smell in case of a framework or a library where the dedicated purpose of some classes is to act as a super class for extensions.