Вопрос

I've been investigating a lot about dependency injection theory and it makes great sense except for the fact that it seems to introduce complexity/bloat in certain scenarios.

Firstly, it is assumed that a DI Container instance is never passed into any object. Bad practice and all that...

For example: Consider a "user" class that relates to all other business objects created in the system by/for a specific user.

If a user instance is to be deleted, all related objects (i.e. records, files, images, etc.) also have to be deleted. Does this mean that an instance of each and every dependency is to be injected into the user instance to allow for the lookup and deletion of all related objects? i.e. an instance of ImageMapper (or ImageMapperFactory) must be passed in in order to delete all images created/uploaded by the user instance being deleted?

If not, is such a scenario a good example of where a service locator should be used?

I find it repeated over and over again in the articles & tutorials that a programmer must avoid using "new" within any class like the plague. However, is this really feasible for instances of controllers that may need to create a variety of views or the like?

A concrete example of adherence to the SOLID mantra, at least as far as DI is concerned, would be appreciated... One that makes it clear how one would either stuff instances of ALL required dependencies into a controller class or how best instances of such dependencies would be located or created?

Это было полезно?

Решение

I don't know PHP but I'll try to explain some things so your question doesn't get neglected, so bear with me. ;-)

I find that dependency injection works best by separating your application in layers:

  • Presentation Layer - Some (user) interface that provides interaction with your application.
  • Business Logic/Service Layer - The actual behavior of your application.
  • Persistence/Data Access Layer - The layer that stores/reads data from a back-end (try searching for repository pattern).

These layers all transfer data to each other in a structured way, using domain models. These models can be for example a user and an image.

When your application logic states that a user's images are to be deleted when a user is deleted you'll want this in the middle layer (Business Logic). The business logic layer calls the data access layer in order to delete entities.

Let's demonstrate using Python (I hope you can read that).

# Define a class that manages users.
class UserService:
    # A constructor accepting dependent DAL instances.
    def __init__(self, user_repo, image_repo):
        self.user_repo = user_repo
        self.image_repo = image_repo

    def delete(self, user):
        self.user_repo.delete(user)
        self.image_repo.delete(user.profile_picture)

The repo arguments that go in the constructor are instances of repository classes, this is dependency injection (constructor injection).

The important thing to remember is that an object doesn't instantiate another object, it accepts instances of objects.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top