Category
Object-Orientation Abusers
Smells where object-oriented features are missing or misapplied, such as type switches, half-used fields and inheritance that does not fit.
- Also known as
- OO Abusers
What these smells share
These smells come from using classes without using what classes offer. Code branches on a type tag instead of letting each type answer for itself. Fields exist for only one code path. Subclasses inherit methods they refuse to support. Two classes do the same job behind different method names.
The cost is fragility. Adding a variant means finding every switch. Calling a method on a subclass may throw. Swapping one implementation for another means rewriting callers.
Members
- Switch Statements: the same
switchorif/elsechain over a type code is repeated in several places. - Temporary Field: a field is set and read only during one operation and is empty or meaningless the rest of the time.
- Refused Bequest: a subclass ignores, overrides with no-ops, or throws on methods it inherits.
- Alternative Classes with Different Interfaces: two classes do the same thing but expose different method names and signatures.
How to choose within this category
- If the problem is a conditional on a kind or status, it is Switch Statements. One switch is fine; the same switch in three places is the smell.
- If the problem is a field that is often
nullor unset, it is Temporary Field. Look for the one method that uses it. - If the problem is inheritance that does not hold, such as overridden methods that throw
NotSupported, it is Refused Bequest. - If the problem is two types that could be swapped but cannot because their APIs differ, it is Alternative Classes with Different Interfaces.
Typical treatments
- Replace Conditional with Polymorphism and Replace Type Code with State/Strategy for type switches.
- Extract Class and Introduce Null Object for temporary fields.
- Replace Inheritance with Delegation and Push Down Method for refused bequests.
- Rename Method, Extract Superclass and Extract Interface for mismatched interfaces.
For agents
- Polymorphism is not always the answer. In languages with sum types and exhaustive pattern matching (TypeScript discriminated unions, Rust, Kotlin sealed classes, Swift enums), one exhaustive
switchchecked by the compiler is often clearer than a class hierarchy. - Prefer composition when fixing inheritance problems. Do not add a deeper hierarchy to fix a shallow one.
See also
- BloatersSmells where methods, classes and parameter lists grow too large to read, test or change safely, usually one small addition at a time.
- Change PreventersSmells where one change forces edits in many places, or one class changes for many unrelated reasons, making every edit slow and risky.
- Replace Conditional with PolymorphismReplace a switch on an object's type or kind with one class per case that overrides a shared method, so new cases add code instead of editing it.
- Replace Inheritance with DelegationTurn a subclass that uses only part of its superclass into a class that holds an instance of it and forwards just the calls it needs.
Original writing and examples. Topic coverage follows Refactoring.Guru, which explains this topic with its own illustrations.