Last Revision — April 19, 2022
2 Min Read
---
Bloaters
Responsibility
Within a Class
- Conditional Complexity (family)
- Parallel Inheritance Hierarchies (family)
William C. Wake in book (2004): "Refactoring Workbook"
The Combinatorial Explosion occurs when a lot of code does almost the same thing - here, the word "almost" is crucial. The number of cases needed to cover every possible path is massive, as is the number of methods. You can grasp a solid intuition of this smell by thinking about code blocks that differ from each other only by the quantities of data or objects used in them. Wake specifies that "(...) this is a relative of Parallel Inheritance Hierarchies Code Smell, but everything has been folded into one hierarchy." [1].
Instead, what should be an independent decision, gets implemented via a hierarchy. Let us suppose that someone organized the code so that it queries an API by a specific method with specific set-in conditions and data. Sooner or later, there are just so many of these methods as the need for different queries increases in demand.
Introducing new functionality requires multiple versions to be introduced in various places.
Class is not closed for modification if it "prompts" the developer to add another elif
.
class Minion:
name: str
state: 'ready'
def action(self):
if self.state == 'ready':
self.animate('standing')
elif self.state == 'fighting':
self.animate('fighting')
elif self.state == 'resting':
self.animate('resting')
def next_state(self):
if self.state == 'ready':
return 'fighting'
elif self.state == 'fighting':
return 'resting'
elif self.state == 'resting':
return 'ready'
def animate(self, animation: str):
print(f"{self.name} is {animation}!")
class State(ABC):
@abstractmethod
def next() -> State:
""" Return next State """
@abstractmethod
def animate() -> str:
""" Returns a text-based animation """
class Ready(State):
def next():
return States.FIGHT
def animate():
return 'standing'
class Fight(State):
def next():
return States.REST
def animate():
return 'fighting'
class Rest(State):
def next():
return States.READY
def animate():
return 'resting'
class States(Enum):
READY: State = Ready
FIGHT: State = Fight
REST: State = Rest
class Minion:
name: str
state: State = States.Ready
def action(self):
self.state.animate()
def next_state(self):
self.state = self.state.next()
def animate(self, animation: str):
print(f"{self.name} is {self.state.animate()}!")