Hacker News new | past | comments | ask | show | jobs | submit login

> These "Behavior" functions may depend on the data, but that doesn't make this a dependency.

Would you mind clarifying this distinction as you see it?

As far as I can see, x depends on y if and only if y is a dependency of x. This would make the States that Behaviors depend on a 'dependency,' based on your statement above that 'functions ... depend on the data [States].'

These State dependencies (if we can agree on the term) are injected dynamically based on the names of the parameters in the Behavior functions. I'm not one to bike-shed on terminology, but I do think it's fair to say that we have dependencies that we're dynamically injecting. If it looks like a duck and quacks like a duck, it's probably a duck.

Perhaps the distinction you're flagging on vs Angular is that Angular injects a reference to the dependency, whereas Famous injects the value of the dependency?




Because state is data. You operate on data, not depend on it. My repository depends on a database connection (be it mock or real). It does not depend on what state the tables may be in.

If your function operates on data, it's "passing in data" and not "dependency injection". Hell, otherwise, every function call would involve dependency injection!


Would you accept that a Haskell function could depend on the streams that are bound into it? Not an individual datum, but the stream itself. I'd argue 'yes', in the same sense that you could depend on some model or factory in OO land. The leap is in the paradigm, functional vs OO.

Behaviors in BEST are a functional programming construct—they project streams of data into a return value. Note that Behaviors are automatically re-evaluated every time one of their dependent States change, which introduces this 'stream' functionality.

I'd argue that these streams are dependencies and that they're being injected into these functions (hence DI,) but honestly, at this point we're just bike-shedding about terminology :-).

I do want to make sure, though, that this functionality is properly communicated, as the State-Behavior relationship is the crux of our framework's design.


Nope, that's still just passing in data, from the point of view of the function receiving the data. Passing data to a function is just a regular old function call.

However, you could consider that the caller of the function could have had the stream injected, depending on the perspective of the rest of the application.

For instance in pseudocode:

    useData = (data) ->
        munge(data) + calculate(data)

    setupPipeline = (input, output) ->
        input
            .pipe cleanup
            .pipe useData
            .pipe format
            .pipe output

    application = ->
        setupPipeline stdin, stdout

    test = ->
        setupPipeline mockInput, mockOutput
Notice how I've included the test case to illustrate how the dependency injection enables testability, which is critical to understanding the concept. Without DI, the setupPipeline method would take no parameters and explicitly hook to stdin/stdout.

Contrast this example with the standard case of regular-old-data-passing:

    useData = (data) ->
        munge(data) + calculate(data)

    application = ->
        useData stdin.getInt()

    test = ->
        assert.equal -1, useData 42
        assert.equal 0, useData 100
        assert.equal 1, useData 99
Note how inversion of control is not necessary to unit test this function, which is the indication that there is no dependency injection going on there.

If you were using dependency injection for the behaviors, it would imply that the injection is not strictly necessary, and you could instead write the function with a hard dependency. Since the behavior just takes data that whole idea is nonsensical. What would it bind to? Nothing. It's just taking data.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: