English 中文(简体)
Abstractions should not depend upon details. Details should depend upon abstractions?
原标题:

In past couple of days, I have read about quite a lot about dependency injection/inversion of control/inversion of dependency. I think that, now my understanding of the concept is much better. But I still don t get the following from wikipedia:

A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend upon details. Details should depend upon abstractions.

I understand the part of High-level modules should not depend on low-level modules. But, I am confused about abstractions and details.Can someone please simplify them for me. Thanks.

最佳回答

It means that if the details change they should not affect the abstraction. The abstraction is the way clients view an object. Exactly what goes on inside the object is not important. Lets take a car for example, the pedals and steering wheel and gear lever are abstractions of what happens inside the engine. They do not depend on the details though because if someone changes my old engine for a new one I should still be able to drive the car without knowing that the engine changed.

The details on the other hand MUST conform to what the abstraction says. I would not want to implement an engine that suddenly causes the brakes to double the speed of the car. I can re-implement brakes any way I want as long as externally they behave the same way.

问题回答

An interesting case where an abstraction depends on details is when you define an interface that inherits from IDisposable. Take a look at the following abstraction:

public interface ICustomerRepository : IDisposable
{
    Customer GetById(Guid id);
    Customer[] GetAll();
}

Note: IDisposable is an interface specific for .NET, but you can easily imagine your interface containing a Dispose method itself instead of inheriting from such interface.

It might look convenient for the ICustomerRepository to implement IDisposable. This way any caller can dispose the repository and this way the implementation can dispose the connection or unit of work that it uses internally.

The interface however is now written with a certain implementation in mind, since it s not obvious at all that all ICustomerRepository implementations would need to clean up any resources. The interface therefore leaks implementation details and therefore violates the Dependency Inversion Principle.

Example of the abstraction and the details: a stream provides an interface to read a token. That s an abstraction.

A stream implementation of the stream is bound to implement the interface defined by the abstraction: that s why it depends on it. If it provides a different interface (one to read 100 characters at a time) it cannot claim to implement the same abstraction.

Think of the work you need to invoke, and how far away that is from where you are currently coding. There is a spectrum there; your position on it represents the amount of work you need to do to invoke that functionality.

Abstractions move that position closer to the code you are writing. For example, if you have to call a web service, you can either 1) write the calling code directly where you need to use it, or 2) put those details behind an abstraction (such as an interface).

In this case, #1 puts you closer to the web service on the spectrum, while #2 keeps you closer to your work. Abstraction can be said to be a measure of how far you have to stretch your mind to comprehend the work you need done.

What this means is that every piece of work can be abstracted so that it is "closer" to the code using it. By having both sides of an operation depend upon abstractions, they both become easier to understand, and neither side has to harbor knowledge of the gap between them - that is the job of the abstraction.

Wow, that was abstract.





相关问题
How to Inject Open Connections with an IoC

First, my scenario. I have a service, BillingService, has a constructor like this: BillingService(IInstallmentService, IBillingRepository) The InstallmentService has a constructor that looks like ...

Using the Ninject kernel as a Unit of Work object factory

So I m starting to use Ninject for dependency injection and I m wondering what people think of using a kernel as an object factory for Unit of Work type objects like Linq2Sql Datacontexts. I would ...

array dependency injection in spring?

is there a way to use dependency injection to inject all available implementations of a specific interface in spring? This is kind of the same thing as asked here for .NET. Though my aim is to use @...

Unity constructors

I have setup unity in my project and it is working for objects that don t have constructor injection implemented on them. The issue is now I do have an object which requires a custom object as a ...

Grails Packaging and Naming Conventions

Packaging Controllers, Services,etc. i.e. - com.company.controllers - com.company.services Is this a good practice or should be avoided by all means?? Another worth mentioning problem I encountered ...

ASP.NET MVP Injecting Service Dependency

I have an ASP.NET page that implements my view and creates the presenter in the page constuctor. Phil Haack s post providing was used as the starting point, and I ll just the examples from the post ...

Authorization and Windsor

I m trying to implement my custom authorize attribute like: public class MyCustomAuth : AuthorizeAttribute { private readonly IUserService _userService; public MyCustomAuth(IUserService ...

热门标签