How on earth does dependency injection make sense?


  • Discourse touched me in a no-no place

    @ScholRLEA said:

    There are very, very few places where global state is acceptable, and even in those cases it usually can be avoided.

    Actually, there are lots of places where there is global state. There is global state because that's what the application actually needs. There's one database where the configuration is because that's what makes sense. There's one clipboard that's used for moving data around. There's one entry point into the overall program.

    But this is all quite different from coding that a particular component in all uses has to necessarily work with exactly one global instance of another component, always and forever more.



  • Well, the ideal would be resources that inject themselves into your program.
    But.... how safe is that?

    For example, SQL server is there, a program starts up and needs an SQL server, but the SQL server has already been injected because the software's configuration said it needed it.

    This really just takes it back another level, where something that starts the application acquires the resource.

    The alternative is for the SQL server itself to monitor every program on every networked machine, and inject itself where needed.

    That's getting absurd.

    So obviously you can't take dependency injection too far.

    One thing you could do is think of connections.

    So if a program attempts to connect to a SQL server, the server responds by injecting its interface into the application.

    And now you're getting into the "internet of things" concept.



  • So, I'm thinking of something that tracks available resources.

    Let's call it a contract.

    And a contract server, which must end up being a global service, builds the interfaces to the various resources by consuming the contract. (a config file, a dll, a series of dynamically loaded dlls (the contract being the location to search)).

    Then you establish a connection to the contract server. Which could be another process, another server, or embedded in your application.

    Then you request resources. The server could be informed from each resource whether the resource can have one user, multiple users, requires locking, etc. And then it would restrict access and perform locking for you.

    So each resource would have its own contract describing how it can be used.

    By the time the resource gets to the user, the user knows the resource is free when he goes to use it.


    Any object that is instantiated will then request from the server its resources.

    So that any user of any object does not need to worry about that object's resource acquisition.


    The problem with the above implementations, is that every parent object is acting as the contract server for the objects it creates.

    That's not sustainable.



  • If you overdo something, it goes bad. What's your point?


    Anything can be overdone. Our job is to not do that.



  • No, I'm saying that having each object that instantiates its needed resources also be the contract server providing the new object its resources, is unsustainable form of dependency injection, because it inverts the previous pyramid problem having the main entry point being the provider of all resources.

    Instead having a contract consumer serve resources is a better solution, but that solution is inherently global.

    But that's how resources work.

    Your SQL server is global. It responds to anyone that legally connects to it. You don't have to instantiate it every time you want to query it.

    So, anything following a dependency injection pattern inherently needs a global provider, external or internal.

    So, in this case, global is not bad.

    What's bad is having a global entity that is hard-coded and fixed to the project.

    A dynamically contracted global entity is not a anti-pattern.



  • public static void main(String[] args) {
      Light light = null;
      Planet earth = null;
      light = new Light();
      asserts.isGood(light);
      earth = new Planet() {{
        sky = new Separator<Water, Water>();
        Asserts.isGood(sky);
        sea = sky.getBelow();
        land = this.getDrySurface();
        land.seedWith(new Vegetation());
        Asserts.isGood(land);
        Asserts.isGood(this);
        sky.addAll(light.getHeavenlyBodies());
        Asserts.isGood(this);
        CreatureFactory cf = new CreatureFactory();
        cf.populate(sea);
        cf.populate(sky);
        Asserts.isGood(this);
        cf.populate(land);
        Asserts.isGood(this);
      }};
      if (earth.getInstance(FRUIT_OF_THE_TREE_OF_KNOWLEDGE_OF_GOOD_AND_EVIL) == null) {
        throw new InvalidStateException();
      }
      IneffablePlan.execute();
    }
    

    I guess what I'm saying is: either you're a wizard, or your point about modeling reality is way off.


  • Discourse touched me in a no-no place

    @xaade said:

    But.... how safe is that?

    It depends on the environment that you're operating in. If you're designing your program to run in an environment (e.g., an application server) where certain services are available somehow, you should just rely on them to be there. All you do is focus on using them right. You might also eventually need to configure the program so that it correctly picks up the services it needs form outside its immediate self, but that's not the concern of the majority of the code.

    Not all programs run in such an environment. But many do, and it is a sane way to work.

    You can go further of course, writing programs that both publish components to the environment and consuming them. At that point, you start to have to worry more about lifecycle issues, and the complexity of a framework like Spring makes more sense, but you can in turn gain other things, such as the ability to have tools map the components of the program and how they connect up. (This isn't the same as those godawful UML class diagrams because you're mapping components, higher-level entities that make much more functional sense.) I guess you could have a GUI tool to do the wiring up; at that point, you're getting very close to graphical programming languages and workflow languages.


  • Java Dev

    @Buddy said:

    ```java
    public static void main(String[] args) {
    Light light = null;
    Planet earth = null;
    light = new Light();
    asserts.isGood(light);
    earth = new Planet() {{
    sky = new Separator<Water, Water>();
    Asserts.isGood(sky);
    sea = sky.getBelow();
    land = this.getDrySurface();
    land.seedWith(new Vegetation());
    Asserts.isGood(land);
    Asserts.isGood(this);
    sky.addAll(light.getHeavenlyBodies());
    Asserts.isGood(this);
    CreatureFactory cf = new CreatureFactory();
    cf.populate(sea);
    cf.populate(sky);
    Asserts.isGood(this);
    cf.populate(land);
    Asserts.isGood(this);
    }}
    if (earth.getInstance(FRUIT_OF_THE_TREE_OF_KNOWLEDGE_OF_GOOD_AND_EVIL) == null) {
    throw new InvalidStateException();
    }
    IneffablePlan.execute();
    }

    I guess what I'm saying is: either you're a wizard, or your point about modeling reality is way off.</blockquote>
    
    Isn't it written the earth is barren before the light is created?


  • “without form, and void”


    Filed Under: if it was good enough for Jesus...


  • Java Dev

    @Buddy said:

    “without form, and void”

    Right, of course. Never read it in English.



  • Yeah, I didn't spend too much effort writing that up, but I at least made sure it would stand up to cursory pedantry. Still expecting a lightning bolt for implying god would abuse double brace initializers like that though.


  • Discourse touched me in a no-no place

    Perhaps it is the other way. Perhaps you should use them more, considering that to be a divine commandment.


  • Banned

    @Buddy said:

    ```
    public static void main(String[] args) {
    Light light = null;
    Planet earth = null;
    light = new Light();
    asserts.isGood(light);
    earth = new Planet() {{
    sky = new Separator<Water, Water>();
    Asserts.isGood(sky);
    sea = sky.getBelow();
    land = this.getDrySurface();
    land.seedWith(new Vegetation());
    Asserts.isGood(land);
    Asserts.isGood(this);
    sky.addAll(light.getHeavenlyBodies());
    Asserts.isGood(this);
    CreatureFactory cf = new CreatureFactory();
    cf.populate(sea);
    cf.populate(sky);
    Asserts.isGood(this);
    cf.populate(land);
    Asserts.isGood(this);
    }};
    if (earth.getInstance(FRUIT_OF_THE_TREE_OF_KNOWLEDGE_OF_GOOD_AND_EVIL) == null) {
    throw new InvalidStateException();
    }
    IneffablePlan.execute();
    }

    
    You forgot `Thread.sleep(EVENING + MORNING)` in a few places.


  • I'm wondering if there ought to be a begin { new Word(); } somewhere up near the start as well...



  • @tar said:

    begin { new Word(); }

    class God implements Father, Son, Spirit
    
    interface Son extends Word
    

    @Gaska said:

    You forgot Thread.sleep

    I don't know about that, I thought He didn't rest until the seventh day.


  • Discourse touched me in a no-no place

    @Buddy said:

    class God implements Father, Son, Spirit

    Are you certain that's true at that point? The way I hear it, Son and Spirit were monkey-patched in later.


  • Banned

    Think of it as legacy code adapted to modern environment.



  • Well, the only reference they had was as an instance of Father, so how would we know? They were all about code-to-contract in those days.



  • In the beginning were the Words, and the Words made the world.



  • @riking said:

    In the beginning was WordStar

    FTFY



  • @dkf said:

    Are you certain that's true at that point? The way I hear it, Son and Spirit were monkey-patched in later.

    So, reality was programmed in a weakly-typed language? "Always bet on JavaScript." strikes again.


  • FoxDev

    @riking said:

    In the beginning were the Words

    The first thing Tak did, he wrote himself.

    The second thing Tak did, he wrote the Laws.

    The third thing Tak did, he wrote the World.

    The fourth thing Tak did, he wrote a cave.

    The fifth thing Tak did, he wrote a geode, an egg of stone.

    And in the twilight of the mouth of the cave, the geode hatched, and the Brothers were born.

    The first Brother walked toward the light, and stood under the open sky. Thus he became too tall. He was the first Man. He found no Laws and he was enlightened.

    The second Brother walked toward the darkness, and stood under a roof of stone. Thus he achieved the correct height. He was the first Dwarf. He found the Laws Tak had written, and he was endarkened.

    Then Tak looked upon the stone and it was trying to come alive, and Tak smiled, and wrote All things strive.

    And for the service the stone had given, he fashioned it into the first Troll, and delighted in the life that came unbidden.

    These are the things that Tak wrote!


  • Java Dev

    Creation myths are interesting for what they tell you about the people who tell them. I'm personally fond of the one at the start of the Gospel of John.


Log in to reply