4 ms·
The main culprit to me in Golang seems to be channels, not goroutines. If your workflow essentially is defined by a mesh of channels and goroutines, it's hard t
by _Codemonkeyism 8y ago
The main culprit to me in Golang seems to be channels, not goroutines. If your workflow essentially is defined by a mesh of channels and goroutines, it's hard to reason or understand.
I have no direct practical knowledge of Golang, but working on a large application that used BlockingQueue for concurrent communication and one which extensively used services buses for communication - both were hard to understand and reason about flow.
After some years with Scala Futures I'd say they work well and reason well. They can be seen as normal function calls returning Future instead of another 'container'.
They reflect the black box mentioned in the article, with one way in and one way out (e.g. when a method returns Future[_]).
The point about error handling: We use Option,Seq.empty on read error handling, Validation on create/write and Either on side effects (like sending mail).
(yes, they are still leaky abstractions e.g. when debugging, but work fine most of the time)
- acjohnson55 8y agoI think the article's point is that with Future's you can still pretty easily invoke a Future-returning function and forget to return its value, ending up with what you might call an orphan continuation.
- z0r 8y agoWouldn't the unreferenced Future, once fulfilled, be garbage collected?
- _Codemonkeyism 8y agoYes
- _Codemonkeyism 8y agoIf the future has a side effect I'm not concerned with, like sending a mail, I can't see the problem?
- acjohnson55 8y agoThe problem is much like the author said -- it's easy to have errors disappear into the ether in a way that is much less likely in synchronous logic. Also, if those side-effects matter, it's easy to make faulty assumptions about time ordering. The most obvious situation to me is in the way asynchrony exists in front-end programming and how this affects testability. If you can't actually know when a process (like an animation) ends, you can't accurately test. In general, my experience has been that reification of abstract things often presents benefits in the long run. Reification of functions admits a whole host of techniques. Reification of classes facilitates metaprogramming. Reification of in-flight processes as promises helps with being able to compose and abstract over them. Nurseries seem like reficiation of an finite execution context.
- _Codemonkeyism 8y agoI'm not following, how could an error with Future[Either[A,B]] disappear compared to synchronous logic of Either[A,B]? Our code base is the same for sync and async logic and error handling. One thing that doesn't work is Anders Hejlsbergs method of letting unchecked exceptions bubble up, but exceptions haven't been a good idea for business code anyway.