Kotlin Code Smell 25 - State as Properties
Avoiding State Pitfalls
Play this article
When an object changes its state, the best solution is to modify the attribute, right?
Problems
Mutability
Attribute Polluting
Setters
Solutions
Use immutable objects
The model states as mathematical set inclusion.
Separate the state from the object as it is accidental.
Examples
- State diagrams
Sample Code
Wrong
sealed class OrderState
data object OrderStatePending : OrderState()
data object OrderStateConfirmed: OrderState()
class Order(private val items: List<Int>) {
private var state: OrderState = OrderStatePending
fun changeState(newState: OrderState) {
state = newState
}
}
Right
sealed class OrderState
data object OrderStatePending : OrderState()
data object OrderStateConfirmed: OrderState()
data class Order(val items: List<Int>, val state: OrderState)
val items = listOf(1, 2, 3)
val pendingOrder = Order(items, OrderStatePending)
val confirmedOrder = pendingOrder.copy(state = OrderStateConfirmed)
Exceptions
Over Design
Performance issues (if a serious benchmark supports it).
Conclusion
This technique is elegant but can lead to overdesign. For example, changing a visual component's color should be a counterexample of this smell.
We should be aware and very cautious as with any other smell.
These are hints and not rigid rules.