'Tis a design and technical code-wise question, so during some refactoring I was doing on a random project to bring it up to date, I encountered the following part, an infix function on a sealed class that was doing some sort of validation:
infix fun TaskState.allowsOperation(operation: TaskOperation): Boolean {
return when (this) {
TaskState.Scheduled -> {
when (operation) {
TaskOperation.Start -> true
TaskOperation.Stop -> false
TaskOperation.Pause -> false
TaskOperation.Resume -> false
}
}
TaskState.Running -> {
when (operation) {
TaskOperation.Start -> false
TaskOperation.Stop -> true
TaskOperation.Pause -> true
TaskOperation.Resume -> false
}
}
TaskState.Stopped -> {
when (operation) {
TaskOperation.Start -> false
TaskOperation.Stop -> false
TaskOperation.Pause -> false
TaskOperation.Resume -> false
}
}
TaskState.Suspended -> {
when (operation) {
TaskOperation.Start -> false
TaskOperation.Stop -> true
TaskOperation.Pause -> false
TaskOperation.Resume -> true
}
}
TaskState.Terminated -> {
when (operation) {
TaskOperation.Start -> true
TaskOperation.Stop -> false
TaskOperation.Pause -> false
TaskOperation.Resume -> false
}
}
TaskState.Created -> {
when (operation) {
TaskOperation.Start -> true
TaskOperation.Stop -> false
TaskOperation.Pause -> false
TaskOperation.Resume -> false
}
}
}
}
So basically, what's happening there was a sugar syntax addition that allowed code to be called like this in other parts:
if (task.state allowsOperation operation) doSomething()
However, I find that particular bunch of code to look ugly, and I could not come up with a reasonable another way of doing it, but at the same time to not produce too many changes.
The TaskState and TaskOperation are just some sealed classes:
sealed class TaskState {
object Created : TaskState()
object Scheduled : TaskState()
object Running : TaskState()
object Stopped : TaskState()
object Terminated : TaskState()
}
sealed class TaskOperation {
object Start : TaskOperation()
object Stop : TaskOperation()
object Pause : TaskOperation()
object Resume : TaskOperation()
}
Do you have any suggestions on how to refactor this type of thingy?