Note on implementation:
As of now createStatement can return one of 3 possible options:
success (so statement is created)
no session (in case one wants to create a statement for non existing session) - before a nasty 500 was thrown
statement shall not be created as session is "completed"
To model a function/method which can return one of these 3 options (with each of them having complete different shape) i see/know following approaches:
using multiple exceptions: i do not like this approach as it is controlling a flow with exceptions. Beside, these 3 cases are not exceptions, they are just regular sunny/rainy-day outputs.
using one common, super set class which can host all data of these 3 options: code is very nasty with if/else (as at some point i need to figure out what option is actually retuned and act accordingly), super-set class is often very low-coherent
using algebraic data types with pattern matching- it is IMHO the best approach, but it is not available out-of box in "old" java
I decided to go for option 3 but as we are in old java, without kotlin/scala the implementation is pretty exotic as it is based on visitor pattern, ie I return StatementCreationResult which can be visited with StatementCreationResultMapper. Both are abstractions and the overall solution provides:
exhaustive type checking (by using visitor), so in case code needs to be extended i will provide a new implementation of StatementCreationResult which would force me to update StatementCreationResultMapper.
StatementCreationResultMapper separates logic from "delivery-mechanism" being micronaut here. So high level policy does not depend on low level policy...
If it were new java/kotlin the code would be much simpler, sth like:
sealed interface StatementCreationResult
class StatementCreated(statement: Statement) : StatementCreationResult
object NoSessionExists : StatementCreationResult
class SessionInInvalidState(invalidState: ApplicationState) : StatementCreationResult
and in controller
val result = sessionService.createStatement(id, statement)
when(result) {
is NoSessionExists -> HttpResponse.notFound()
is SessionInInvalidState -> HttpResponse.badRequest("invalid session state " + invalidState);
is StatementCreated -> HttpResponse.created(statement);
}
Compiler will force me to handle all possible options in when statement and the code will be more straightforward
Fixing https://github.com/exacaster/lighter/issues/709
Note on implementation: As of now
createStatement
can return one of 3 possible options:To model a function/method which can return one of these 3 options (with each of them having complete different shape) i see/know following approaches:
I decided to go for option 3 but as we are in old java, without kotlin/scala the implementation is pretty exotic as it is based on visitor pattern, ie I return
StatementCreationResult
which can be visited withStatementCreationResultMapper
. Both are abstractions and the overall solution provides:StatementCreationResult
which would force me to updateStatementCreationResultMapper
.StatementCreationResultMapper
separates logic from "delivery-mechanism" being micronaut here. So high level policy does not depend on low level policy...If it were new java/kotlin the code would be much simpler, sth like:
and in controller
Compiler will force me to handle all possible options in when statement and the code will be more straightforward