Earlier quoted context omitted.
I'm on exactly that kind of team now. They've been working on a very simple problem for several years now and have an enormous, sophisticated, but still buggy and unstable solution. They're really smart people, and they had to be extremely capable programmers to get this far, but the embarrassing question is, how would a team of mediocre developers have tackled this problem? They would have picked a mediocre language…
I am fairly certain the jury is out on this question: It's always better to write simple, almost dumb code that anyone can understand than to use advanced abstractions from category theory or whatever. Why? Because every single study or anedocte I've ever heard is like yours: adding complex abstractions to code do NOT make it more reliable. But they do make it much harder to modify, understand, and fix. FP tought us…
I write lots of F#, and I find that computation expressions (a fancy version of do-notation) makes my code more "dumb" and "simple", despite being an advanced "FP" feature. This is because it pushes the complexity from my business logic and into library code.
With computation expressions:
async {
let! foos = fetchFoos
for foo in foos do
do! launchFoo foo
do! clearFoos
}
Without computation expressions (this is probably wrong but you get the idea): Async.bind
fetchFoos
(fun foos ->
Async.bind
(
foos
|> Seq.fold (Async.bind (fun foo -> launchFoo foo)) (Async.just ())
)
(fun () -> clearFoos)
)
Notice how my fancy non-blocking code reads like straight-forward blocking code?I could not manage complexity without this feature.