Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

We use dependency injection to match State names to parameters of Behavior functions—the State numberOfStates gets injected into any Behavior function that lists is as a parameter, like function(numberOfStates).

We need to have a talk. First, this isn't dependency injection - you're passing in data. These "Behavior" functions may depend on the data, but that doesn't make this a dependency.

Oh, I can understand how you're confused. You see Angular doing it and reverse-engineered the term. But notice how in Angular it is used to pass services into controllers, services that the controller has a dependency on.

Also, notice how this "feature" is broken in production. Any website worth its salt will minify the assets, which changes function parameter names. You did notice that, right, that your clever little hack works great in your development environment but totally breaks when you minify your code? You are testing things minified, right?

Why would you spend any time at all working on a feature that is fundamentally broken in production? Kill your darlings.



> Any website worth its salt will minify the assets

In Angular you'd assign a property called $inject to make "DI" still work even with minification, so it's not really an issue.Or you can explicitly pass a array with dependency names when a service is registered.

So there is no issue here.

Now I don't know how Famous works and i'm not interested in using that 2M dollars vaporware. I'm just saying.


Many build tools will allow you to simply annotate functions that are meant to have their dependencies injected so you can avoid explicitly typing out the verbose array syntax. (e.g. https://github.com/olov/ng-annotate)


> 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.


Wait, are they seriously trying to say that "function(numberOfStates)" is dependency injection?


In angular that's basically how it works. The framework actually calls toString on the functions which actually allow you to parse out the arguments names so the callers know which arguments (dependencies) need to be passed.


I have to reply because I can't edit.

To the down voters:

Function(numberOfStates) is a function call with data being passed in.

Function(stateMachineFactory) is dependency injection.




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

Search: