What the Dependency Inversion Priciple implies in practice is that in a system, high level components should depend on abstractions of the low level components (instead of on the low level components directly), and the low level components should be defined in terms of these abstractions.

The key point for my question is that the low level components are defined in terms of the abstractions, which is defined in terms of the high level components. Meaning: the high level components 'define the abstraction' in terms of what would be convenient for them, and the low level components have to be defined according to that abstraction (usually an interface).

So if the high level component is a Car, and the low level component is the Engine, and an interface IEngine is defined - it will be defined according to the needs of the Car, and Engine will have to fit these needs. So if it's convenient for the Car to be able to simply start the engine, IEngine would feature a method start() and Engine would have to implement it.

My question is:

When starting programming on a project designed according to the Dependency Inversion Principle - are the high level components usually implemented before the low level ones, ie. "top to bottom" development?

Since the principle implies that the low level components are designed according to what is convenient for the high level components, it makes sense to first start programming the high level components, and only then define the ILowLevelComponent interface, based on what we learned the high level components need when we programmed them.

For example we're implementing a system that simulates a car. Car is the high level component, while Engine and SteeringWheel are the low level components. Engine and SteeringWheel take care of the concrete work of moving the car around, while Car takes care of coordinating everything and creating a functioning system.

If we were designing the system according to DIP, that means that Engine and SteeringWheel are defined in terms of an abstraction, that is defined in terms of what is convenient for Car.

So it would make sense to first implement Car, understand exactly how it's going to work in high level terms and what it needs to work, and only then define the IEngine and ISteeringWheel interfaces, according to what the Car needs. And then ofcourse implement the concrete classes that implement the interfaces.

So what I'm asking is: when working on a project that is designed in the spirit of DIP, is the "top to bottom development" approach common? Is this how work is usually done on project following the Dependency Inversion Principle?

It's usually not written in stone:

  • Sometimes it can be done so. Higher level component needs something, then interface is designed, then a mockup object implementes it so developing of a higher level component doesn't have to wait.

  • Sometimes developing can be done both ways and meet in the middle.

  • Interfaces are not always defined by what the higher component "needs", for example a LightSource interface will not have a getPriceInDollars method even when the higher level component seems to need it. Maybe another interface will have that getprice method and some implementor will implement both interfaces.

  • Sometimes existing components and interfaces are reused in a new project.

  • Sometimes existing classes, from previous projects, can me made to implement new interfaces to be compliant with the new architecture without changing behavior or breaking previous contracts, maybe with the use of structural design patterns (Adapter, Composite, Decorator, etc.)

  • Sometimes the higher level component simply adapts to whatever interface (abstract class or interface ) the lower level component has, like when when you use 3rd party library. The designer of the library ( say a library for creating charts ) thought of a very generic consumer. And that doesn't make such a library less usefull. NOTE: It's still DIP because you are programming to abstractions even though a 3rd party designed said abstractions.

  • In OOD and OOP, higher level components are not always written first and low level components are not always written last. DIP has the added advantage of you not having to develop strictlly in a top-down or bottom-up fashion.

  • Lower level components tend to amalgatate into APIs or libraries which are transversal to projects.

  • You mention a case where the high level components adapt to the low level components, especially when using a 3rd party library. How is this still DIP? I think it contradicts the whole point of DIP. – Aviv Cohn Apr 30 '14 at 20:00
  • @Prog It doesn't. It's just that the people who wrote the library designed the interfaces. As interfaces, they are abstract. So you have yourself programming your higher level components to interfaces you didin't design. It's DIP becasuse you are programming to abstractions (interfaces) and not concrete classes. But I will edit the question to make it more clear. – Tulains Córdova Apr 30 '14 at 20:11
  • @Prog Just edited. – Tulains Córdova Apr 30 '14 at 20:16
  • 1
    Correct me if I'm wrong, but I think that programming to abstractions is a more general concept ('program to interfaces, not concretions'). I think that a major part of DIP is that the high level components 'own' the abstractions, and the low level components must 'obey' that contract. If the low level components (the library) defined the abstraction, and the high level components are programmed against it, than it's 'program to an interface..', but is it DIP? – Aviv Cohn Apr 30 '14 at 20:18
  • 1
    @user61852 Very often, lower level components (say in a 3rd party library) will have such obvious way to abstract that the 'ownership' is irrelevant. But in cases where it does matter, I'd say it actually is pretty frequent for the high-level components to own their abstractions through the adapter pattern/ adding in an extra layer of abstraction. As an example, Microsoft's Entity Framework implements the repository and unit of work patterns, but it's extremely common for people to add their own implementations of these patterns as an extra layer on top – Ben Aaronson Apr 30 '14 at 20:55

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.