|
|
|
|
|
by lmm
4703 days ago
|
|
Straight exceptions are also goto-like, but there's the slight improvement that they allow you to (automatically) refactor out the middle of a function without changing the behaviour. The solution I prefer is a monad with some light notation (Haskell do, scala for/yield). So it looks like: def doSomething(): Validation[Whatever] =
for {
result1 <- callThatCanFail()
result2 <- callThatCanFail2(result1, 4)
intermediate = callThatCantFail()
result3 <- anotherCallThatCanFail(result2 + 4, "Hello", intermediate)
} yield result3 + result1
The <- syntax clues you in that this computation is going on in some kind of "context" - if you're working with futures it might happen on a different thread, if you're working with collections you're iterating over the elements. Here we're working with a validation, and our computations only happen if the previous one succeeds.Is this goto-like? You could argue so - once one computation fails, the rest turn into noops and we pass immediately to the end. But to my mind this is like replacing an if/else with polymorphism - our validation context is an object with certain behaviours, and we're calling methods on it with our functions as parameters, which will behave differently depending on which subtype our context instance is. |
|