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 of the smells considering them to be “uncommon smells”. By “uncommon smells”, I mean the ones that we (co-authors of the book) haven’t seen commonly occurring in software projects (and we could be wrong), so did not think that they are 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 (e.g., readers may question the choice of smells covered in the book and may consider some of the smells mentioned as “uncommon smells” are indeed common in their projects!).
Given the fact that its been a couple of years since the book has got 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 such smells as future articles!
This smell arises when an abstraction has excessive encapsulation thereby aﬀecting its usability (almost all its members are private, including methods). Also known by names “exceeded method hiding”, “poor interface”, and “too much information hiding”.
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”.
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 reflection facility (in languages that does 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 stands broken.
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.
This smell arises when the base abstractions provide many concrete methods and derived abstractions do not override those concrete methods. This indicates use of inheritance primarily for code reuse deviating from the widely-accepted norm of using inheritance to model IS-A relationships.
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 when the design is from a framework or a library where the dedicated purpose of some classes is to act as a super class for extensions.
What do you think:
- Are they really “uncommon smells” or were we wrong?
- Is it worth discussing or exploring such design smells?
- What are some of the uncommon design smells YOU have seen in your experience in projects?
[The DZone version of the article is available here].