2
\$\begingroup\$

I have the following UserServiceProvider and I'm wondering whether so much dependency injection is overkill:

use
Illuminate\Support\ServiceProvider,
App\Repositories\Eloquent\User\EloquentUserRepository,
App\Repositories\Eloquent\Profile\EloquentProfileRepository,
App\Repositories\Eloquent\Seller\EloquentSellerRepository,
App\Repositories\Eloquent\AppResponse\EloquentAppResponseRepository,
App\Repositories\Eloquent\AppRequest\EloquentAppRequestRepository,
App\Repositories\Eloquent\Model\EloquentModelRepository,
App\Repositories\Eloquent\Maker\EloquentMakerRepository,
Cartalyst\Sentry\Sentry,
App\Services\Cache\Decorators\UserCacheDecorator,
App\Services\Cache\Laravel\LaravelCache,
App\Entities\Entities\Profile\ProfileEntity,
App\Entities\Entities\Seller\SellerEntity,
App\Entities\Entities\AppRequest\AppRequestEntity,
App\Entities\Entities\AppResponse\AppResponseEntity,
App\Entities\Entities\Model\ModelEntity,
App\Entities\Entities\Maker\MakerEntity,
Profile,
Seller,
AppResponse,
AppRequest,
Model,
Maker;

class UserServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind('App\Repositories\Interfaces\UserRepositoryInterface', function($app)
        {
            $user = new EloquentUserRepository(
                new Sentry(),
                new ProfileEntity(
                    new EloquentProfileRepository(
                        new Profile()
                        )
                    ),
                new SellerEntity(
                    new EloquentSellerRepository(
                        new Seller()
                        )
                    ),
                new AppRequestEntity(
                    new EloquentAppRequestRepository(
                        new AppRequest()
                        )
                    ),
                new AppResponseEntity(
                    new EloquentAppResponseRepository(
                        new AppResponse()
                        )
                    ),
                new ModelEntity(
                    new EloquentModelRepository(
                        new Model()
                        )
                    ),
                new MakerEntity(
                    new EloquentMakerRepository(
                        new Maker()
                        )
                    )
                );
            return new UserCacheDecorator(
                $user,
                new LaravelCache($app['cache'], 'user')
                );
        });
    }
}

I do need all these entities in my UserEntity. Is this normal or should I start reducing the number of injections?

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

You should reconsider the responsibilities of class UserServiceProvider, too many responsibilities may lead to a lot of dependencies in many cases.
It is quite possible that this class is doing a lot of work that it should not, for example populating User object with sales reports, earnings reports, or activating user, checking activation status etc.

It is not clear in your question but looking at the names of dependencies it looks like it does a lot of checking and population, you should consider moving respective codes to respective repositories and also refactor the service object into separate classes. This will create a spreaded hierarchy like this:

                           DashboardController
                           /                \
            UserProfileService              UserService
                /        \                    /         \
UserProfileRepository  OtherRepository  UserRepository   SomeOtherDependency

Now, instead of injecting UserProfileRepository, OtherRepository, UserRepository, SomeOtherDependency into UserService and then injecting UserService into controller you can inject UserProfileService and UserService into controller with all of their respective dependencies.

A couple of them looks like they can be defined as a relation. You can, for example, define UserProfile as a relation on User which in a typical case should be a one-to-one relationship. This should sort out the dependencies quite a bit.

Main point to take home is that you should re-evaluate the responsibilities of classes and determine which object should be responsible for what action. as a basic rule of thumb, all data fetching and storing should be a responsibility of repository and all data manipulation and logical decisions should be a responsibility of a service object. If a service object requires more than one repository as a dependency then step back and check if the manipulation of data from second repo should really be a responsibility of service object ?

\$\endgroup\$
7
  • \$\begingroup\$ Thanks for this extensive answer, I've already refactored my code to better reflect these design patterns. Just one more question - are "entity", "manager" and "service" basically the same thing? I'm referring to the class which contains application logic and does all the logical decisions. I've noticed that different people call it differently, thus causing confusion for newcomers like me. \$\endgroup\$
    – Onion
    Jun 23, 2014 at 23:32
  • \$\begingroup\$ In my application, I have repositories, which contain database related stuff; entities, which are reponsible for logical decisions; and services, like validation classes. \$\endgroup\$
    – Onion
    Jun 23, 2014 at 23:33
  • 1
    \$\begingroup\$ Entity - think of it as a single row in database, it has details and behavior. Repository - operate on DB with entities, like fetching entity, putting entity, deleting/updating entity. Service - operate on entities and make logical decisions. Manager - manages service objects and keep them in order, ie cache manager will create object of a cache service based on what kind of cache you want e.g. file, array, memory, redis etc. Try reading up about them on blogs or browse some codes on github and try to figure them out. \$\endgroup\$
    – Gufran
    Jun 24, 2014 at 0:18
  • \$\begingroup\$ Hmm. It seems I need to read up on the naming conventions. In my app I have repositories which interact with the DB and entities (which in this case are services), which contain all the logical decisions. Anyhow, I guess I'm still following a certain design pattern so there is no need to refactor my code once more. Once again, thanks for your insights. \$\endgroup\$
    – Onion
    Jun 24, 2014 at 0:22
  • 1
    \$\begingroup\$ Yes, a model is an entity which has details i.e. name, age, location and also has behavior e.g. moveTo($location), growUp() and such. A repository might be a dependency to a service class and an entity might be a dependency to a repository. \$\endgroup\$
    – Gufran
    Jun 24, 2014 at 0:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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