32

(Disclaimer: I understand this question as "applying the Dependency Inversion Principle by injecting objects through interfaces into other object's methods", a.k.a "Dependency Injection", in short, DI.) Programs were written in the past with no Dependency Injection or DIP at all, so the literal answer to your question is obviously "...


17

Am I misunderstanding the concept of "code to an interface and do not use inheritance"? Yes you are misunderstanding that, because you seem to be conflating two different principles. On the one hand, there is the principle of "code to an interface" and it is very unfortunate that languages like C# and Java have an interface keyword, because that is not ...


14

It seems to me that most 'new' things in software architecture are old ideas refurbished and combined with new technologies or other ideas. Often these are incremental. In this case, the change that I think matters is the database is no longer the center of the design. This is not an minor change; it's pretty fundamental. So is the "onion architecture" ...


14

I fail to see how dependency inversion is useful at all. That's because you've failed to use it for anything yet. You're bemoaning the fact that DIP is work, adds complexity, and does nothing for you. All of which are true at the moment. What you're failing to understand is that DIP isn't about now. It's about change. You're predicting that using DIP will ...


14

At its core DI means streamlining your dependencies. Rather than making A, B and C aware of each other (to know each other's type) you introduce another thing D. You then make A. B and C know D but not each other. This kind of decoupling gives you more flexibility. You can easily rework A, B or C without the need to revisit any of the others. But it comes at ...


11

First, lets clarify what we mean when we say "interface is owned by client". It means that interface is defined by what client of the interface needs and not by what implementer provides. If we were to create a modules of the trio of client, interface and implementer, then first module would be client and interface and second would be implementer, with ...


11

There are two main ways to deal with circular dependencies: Hide it with interfaces Add an intermediary object In this particular case I would recommend the second option. Your module would have something like this: /package_name /client.py /request.py /response.py The new Client object would actually run the request. This moves Request.run ...


10

There is a great article on Martin Fowler's site that has a chapter specifically about the difference between DIP, DI and IoC. The gist of it (as copied from that site) is DI is about how one object acquires a dependency. When a dependency is provided externally, then the system is using DI. IoC is about who initiates the call. If your code initiates ...


8

A common way of writing OO code is to to have code such as: void SomeMethod() { SomeClass x = new SomeClass(params...); ... } or code such as: void SomeMethod() { SomeClass x = SomeStaticLocator.GetSomeClass(); ... } In both cases, the code is obtaining other parts of the system by "asking" for them. With dependency injection/dependency ...


8

Thinking of an untyped code, if the Response gets the Request object injected, but doesn't create one on it's own, it doesn't depend on the Request class. It depends just on it's interface (which may not have any specific representation in code, but nevertheless definitely exists). So in that case the class dependency is not really circular. To capture that ...


7

Main goal of Dependency Inversion Principle is change direction of dependency. In your example UI layer depend on Presentation layer and Presentation layer depend on Business logic layer. So if you make a change in Business logic you need to recompile all layers, because they have dependency on lower level layer. why can't we just modify the ...


7

DI is not an end in itself, it is a means to an end. I have my doubts about the usefulness of applying DI to this binary tree with something else than the "canonical" binary node, or even a necessity to write unit tests for this kind of tree with "mock nodes". So I don't see any sensible application of DI in this example. However, if you just want to try ...


6

This is an area where the type system of a language doesn't give you many safeguards. Without making the class a package level case in the case of Java, or an internal class in the case of C#, you can't control who creates instances of this class. A public class with a public constructor can be instantiated by anyone. Even if you make it internal/package-...


6

Is there a name for this pattern? Let's start with this question as the its name gives a succinct answer to your more general question. This is known as the Bastard Injection (Anti) Pattern. Unhelpfully, the term "poor man's DI" is also sometimes used to describe it, despite that term also commonly being used to describe pure/vanilla DI. Unsurprisingly, ...


6

Applying SOLID is not always appropriate. Dependency inversion implies some indirection, and that typically means overhead. This kind of overhead is unlikely to be appropriate in memory-constrained devices. But not all is lost: we can implement relevant OOP functionality in C, but we might also find that using the preprocessor provides enough flexibility. A ...


5

You are definitely in the right here. This is pretty basic defensive programming and there are no real arguments against it. Now for the arguments : The coupling to IoC and fail-fast issue is just like you said. As for the third argument, just because this one class has argument null check doesn't mean you have to go back and change all other classes. It ...


5

The DIP requires your classes to depend on abstractions. Because you can always provide different implementations of these abstract dependencies, they create natural extension points that allow you to modify the behavior of the class without changing the class itself. This, of course, is exactly what the OCP requires. For example, imagine you have a ...


5

The solution below allows compiling the python code while avoiding to create a third module which reduces readability IMO. Python type hinting request.IRequest enabled code completion on IDEs (source). This feature might be very specific to Python, but it has all the advantages mentioned in other answers but without creating a third module or class (e.g. ...


5

The DIP is not an end in itself, it is a means to an end. Let us, for example, assume you use the DIP for unit testing. If you want to be able to test Gripper in isolation, without the "real" GripperItemLocator, then you need a way to replace the latter by a mock. The canonical way of doing this is by using an interface, or in C++ an abstract virtual base ...


5

You've got the basic pattern. Define interfaces for the classes that communicate with out-of-process resources, like databases and file systems. Then have the "real" class implement the interface. Expose a constructor that takes an object by that interface as an argument, and redefine the type for that field or property to be the interface rather than the ...


5

IoC container advertise themselves with code snippets like: container.Register<IEmail,Gmail>() which suggest you always need an interface and that its a 1 to 1 relationship. But this is not true. The following methods can also be used: container.Register<Gmail>() //no interface container.Register<IEmail, Gmail>(name = "gmail") // ...


5

You apply DIP when crossing a significant boundary. What's on either side doesn't matter. What matters is having a good reason to keep what's on one side from having a source code dependency on the other side. The magical thing DIP does is let you enforce that source code dependency rule while allowing flow of control to go in and out of that boundary ...


4

Who is going to determine what classes (that implement SwitchableDevice) need to be called? Who tells Button what devices he need to turn on/off? How do you tell an object that uses something abstract which concrete things it needs to use? (Please correct me if this question is completely wrong) The term often used is "wiring", which refers to the ...


4

To add to the other good answers: We should not automatically create class hierarchy, especially in cases when a single class will do. Many things are better modeled thru attributes in the general case rather than as offerings of specializations (subclasses). Obviously, in your example, UniqueSedanMethod and CalcAdditionalSeatsAdded are contrived. ...


4

If you are using c#, you can use this "friend" approach: Add another (possibly parameterless) constructor to the class solely for your test project. "Hide" the constructor from other developers by making it internal. You can then make the constructor visible to your test project by using the InternalsVisibleToAttribute. [assembly:InternalsVisibleTo("...


4

If you inject a "ServiceFactory", which contains all the dependencies for all parts of your code, into all parts of your code, then you are using dependency injection, but not dependency inversion. Dependency inversion follows the rules of "tell, don't ask". It inverts the normal "I have a dependency, so I'll go looking for it" into "you have a dependency, ...


4

Let's lay out two things. The first is that it's good to hide implementation details from the user of your code, but it's not necessary to abstract them away entirely. In other words, it's fine to use new in your implementation of your BinaryTree, so long as your user doesn't need to see it. That being said, it is possible to make things more generic. ...


4

if you return an object of MyType, I (personally) would expect it to be a new object I guess it's because I would expect to modify the parameter by using a ref call. Also it would look weird: var obj = new MyType(); var modifiedobj = EditSomething(obj); If i see this code, i do not expect obj and modifiedObj to be the same, that's just confusing.


4

The entry point of the application (the UI project) must setup the DI container, providing implementations of all the dependencies. That's why it must have direct connection (reference) to all the other projects. What is important is that the UI classes have dependencies only on BLL classes. The additional references are only for setting up DI.


4

Well, well, let's get something that is bothering me out of the way first... if (Company == 1) { //This is how code should NEVER look like } OK, now that I took it out of me it, let's get to the point! Short Answer The short answer to your question is yes, it does make sense to make entities depend on abstractions in some occasions. Once you ...


Only top voted, non community-wiki answers of a minimum length are eligible