Skip to main content
21 events
when toggle format what by license comment
Nov 2, 2017 at 14:36 comment added candied_orange @JacobBrown Without knowing what you're using that is making main() unworkable that will be difficult. However, Mark Seemann has identified where common alternative Composition Roots are. You're looking for your programs entry point. That's as far up the call stack as you can go. I can also point you to some example code that moves composition into it's own class. Which is fine. The point is to separate construction and behavior.
Nov 2, 2017 at 13:51 comment added Jacob Brown @CandiedOrange Can you give an example of introducing them outside of "Main" ?
Nov 2, 2017 at 13:06 history edited candied_orange CC BY-SA 3.0
added 324 characters in body
Nov 2, 2017 at 2:02 comment added Derek Elkins left SE @JacobBrown The object capability model gives a formal interpretation of "introduction". Introduction, while not the only method of sharing is by far the most common. Object capability languages such as E, Joe-E, and NewSpeak actually require some degree of dependency injection. Authority (such as access to the file system) is usually provided in some "main function" and all other objects have access to it only by being created with it by "main" or being passed it by "main" or (recursively) by some other object with access to it.
Nov 1, 2017 at 21:51 comment added candied_orange No, I'm saying the polite way to share data is by first being introduced so that you don't throw a tantrum when your best friend is replaced. The rude way is to make anything you want static and global and grab it whenever you like. That works. But it's not easy to maintain. Main is the ideal place to be introduced. Those you meet here will live as long as you do. If separating construction code and behavior code can be achieved at this level then you don't have to hunt for where something is created. If you can't do that there then do it as high up the call stack as you can.
Nov 1, 2017 at 21:39 comment added Jacob Brown Are you saying that the only way to have to objects share data is to introduce them, and the only way to do that is to introduce them in the "composition root"? In the example you give, "main()" has to know about both ClassC and Class A, and that they want to share data. In the problems I've seen, the specific classes/objects aren't known about in the composition root because the object graphs are much deeper.
Nov 1, 2017 at 21:00 comment added candied_orange Mediator will help if you think A and C are too closely coupled (to much going on between them) or you need some fancy logic to decide if C is really is what A should depend on.
Nov 1, 2017 at 20:47 comment added Robert Harvey @JacobBrown: en.wikipedia.org/wiki/Mediator_pattern
Nov 1, 2017 at 20:16 comment added candied_orange Half the reason my answer is hard to understand is because these names give no hint to their purpose. I'm not "outside the dependency injection". Objects that want to talk to other objects need to be introduced to them. We do that by passing references around. Dependency Injection is just a fancy word for it. We're trying to build an object graph. No cycles required. If you can't do it in main find the highest place in the call stack that you can. That's your composition root. When done correctly main is many lines of construction followed only one call that starts the whole graph ticking.
Nov 1, 2017 at 20:02 comment added Jacob Brown The other suggestion I see is to have one of the objects depend on the other object. That won't work because the injector will create new objects for it, so it won't have the correct state. Also, there's a chance it could create circular dependencies.
Nov 1, 2017 at 20:02 comment added Jacob Brown At first I struggled to understand how this answer solves the problem that I'm having... until I got near the end. You suggest that I solve the problem of sharing data between the objects by doing it outside of dependency injection. That's cool, but I'm trying to find a way to do it inside of dependency injection. The objects that are trying to share data, aren't always objections from "main()" or the lowest part of the callstack where the dependency injector has created objects.
Nov 1, 2017 at 19:58 history edited candied_orange CC BY-SA 3.0
added 21 characters in body
Nov 1, 2017 at 19:45 history edited candied_orange CC BY-SA 3.0
deleted 1 character in body
Nov 1, 2017 at 17:47 history edited candied_orange CC BY-SA 3.0
added 262 characters in body
Nov 1, 2017 at 17:17 comment added psr Good answer, but Tell, Don't Ask would mean class C would call B.DoTheThingIWasGoingToDoWithNeededThing() instead of getting the needed thing at all. Your example is of dependency injection, which would be Require In Order To Even Exist, Don't Ask, or something like that.
Nov 1, 2017 at 15:19 comment added candied_orange @RobertHarvey There certainly are DI libraries/frameworks that hype other reflection-esq features but mostly this is it. They might also tempt you to move your composition into another language like xml or pollute you with proprietary @ thingies but yeah. Dependency Injection is just good old fashioned reference passing with a fancy name.
Nov 1, 2017 at 15:15 history edited candied_orange CC BY-SA 3.0
added 515 characters in body
Nov 1, 2017 at 15:14 comment added Robert Harvey So basically what you're saying is that the DI container merely fulfills each class's dependencies, and it is up to the programmer to implement communication in the usual mundane ways like composition?
Nov 1, 2017 at 15:10 history edited candied_orange CC BY-SA 3.0
added 515 characters in body
Nov 1, 2017 at 15:06 history edited candied_orange CC BY-SA 3.0
added 515 characters in body
Nov 1, 2017 at 14:51 history answered candied_orange CC BY-SA 3.0