News for hackers. Stuff that matters.
Re:Pitfalls of Callback-Based APIs by groby_b on Tuesday December 23, 2014 @09:06PM (#8791224)
Except that this is not a callback issue. It's an issue of circular dependencies - callbacks are merely the chosen dependency injection vehicle for this particular item.

The message pumping example the author gives has the exact same issue. The core here is that two items (database & logger) are mutually dependant. That will always be an issue. It doesn't matter if your promises are circularly dependant, your context objects, your callbacks, or your globals.

Static analysis won't help - fully resolving circular dependencies is equivalent to solving the halting problem, IIRC.

And so the only way to prevent those dependencies is to constrain the design in a way that prevents circular dependencies. That's where the ad-hoc rules mentioned in the article stem from. They artificially restrain the problem space to prevent (classes of) circular dependencies.

Re:Pitfalls of Callback-Based APIs by rian on Tuesday December 23, 2014 @09:09PM (#8791231)
Yes, the core issue in the database logger example is that it's a circular dependency.

The point of the article is that callback-based APIs like this obscure the actual problems (like circular dependencies).

You're right that constrained designs prevents issues like these but callback-based APIs aren't inherently constrained. They allow anything to happen, which is why they conversely encourage errors like these (and are subject to pitfalls).

Re:Pitfalls of Callback-Based APIs by groby_b on Tuesday December 23, 2014 @09:42PM (#8791317)
What would be an inherently constrained API, then? I've successfully managed to create circular dependencies in quite a few different styles, so I'd love to find one that saves me from myself ;)
Re:Pitfalls of Callback-Based APIs by rian on Tuesday December 23, 2014 @10:05PM (#8791372)
Maybe inherently was the wrong word. Though you can imagine a logger API that was like this:

    typedef enum {
        CONSOLE_LOGGER,
        DATABASE_LOGGER,
        /* etc. */
    } LoggerType;

    void add_logger(LoggerType);
In this API you're constrained by what loggers you can add. It's not the totally unchecked free-for-all that a callback-based API provides. The user is strictly unable to shoot themselves in the foot.

But this limits the expressive power that callbacks provide. Sorry I don't have any other API recommendations. The only way I can think of to stay expressive while safeguarding against unintended abuse is to include code analysis.

Re:Pitfalls of Callback-Based APIs by markuz on Tuesday December 23, 2014 @11:35PM (#8791553)
I was thinking the same thing. It has nothing to do with callbacks.

> fully resolving circular dependencies is equivalent to solving the halting problem, IIRC.

I don't think so. Any good dependency injection framework would detect this kind of circular dependency.

Re:Pitfalls of Callback-Based APIs by groby_b on Wednesday December 24, 2014 @01:16PM (#8793847)
Of logger and DB, certainly. The coupling introduced via locks is harder to detect. But most importantly, circular dependency between components might be OK in a path-dependent way - that's what I meant by fully resolving it.

Just analyzing the dependency graph of injected components is indeed just a topological sort.