Click here to Skip to main content
15,880,651 members
Articles / Web Development / XHTML

Angular2 & WebApi (SPA) for Enterprise App - Part 5 - DI & IoC - Why and Why not?

Rate me:
Please Sign up or sign in to vote.
2.81/5 (22 votes)
15 Jun 2017CPOL4 min read 59.5K   29   19
In this article, we will why and why not using DI & IoC from my real situation.I did not tell you that DI is not good. From my view, each tech has it own pros and cons. So It is better if we know when we can use which techs for our business.

Other Articles in the Series

  1. Overview
  2. Add new Permission
  3. Project structure
  4. Multi-Languages (i18n)
  5. DI & IoC - Why and Why not?
  6. RESTful & WebApi
  7. Manage Application Lifecycle
  8. Build & Deploy Application
  9. New version of TinyERP with Angular 2 (typescript)
  10. CQRS: Avoiding performance issues in enterprise app (basic)
  11. Multiple data-stores: Scale your repository (Part 1)
  12. Multiple data-stores: Scale your repository (Part 2)
  13. Basic authentication (user name/ password) with OWIN

Introduction

I have looked at IoC and DI in my code.

Hope this can help us use IoC and DI in a good manner.

I did not tell you that DI is not good or IoC is better than DI. From my view, each tech has it own pros and cons. So It is better if we know when we can use which techs for our business.

How to Get the Code

Please check out the code at https://github.com/techcoaching/TinyERP.

DI - Dependency Injection

DI is a good patternt that help us inejcting required references:

class UserService : IUserService{
    private IUserRepository userRepository;
    public UserService(IUserRepository userRepository)
    {
        this.userRepository = userRepository;
    }
    public void UserRepositoryForSomeActio(){
        this.userRepository.<callSomeMethod>();
    }
}

As code above, we see that the userRepository instance will be inejcted automaticly, it was also ready for us in UserRepositoryForSomeActio method.

This is cool, as we can focus on business of function.

And this is good in the context of small application. Let look how is it in more complext application type (I mean in enterprise application now a day).

In Enterprise Application, we have many core object/ major object where it has many dependency on other objects.

For example: Order object, we can have dependency on those smaller object:

  • User (who created order)
  • Orderline
  • Category
  • Product
  • Promotion
  • Unit of Measurement (UOM)
  • Branch
  • ...

So OrderService may require injecting appropriated repository for all of dependency objects as code below:

class OrderService : IOrderService{
    private IUserRepository userRepository;
    private IBranchRepository branchRepository;
    private IOrderLineRepository orderlineRepository;
    private IOrderCategoryRepository orderCategoryRepository;
    private IProductRepository productRepository;
    private IUOMRepository uomRepository;
    public UserService(
        IUserRepository userRepository,
        IBranchRepository branchRepository,
        IOrderLineRepository orderlineRepository,
        IOrderCategoryRepository orderCategoryRepository,
        IProductRepository productRepository,
        IUOMRepository uomRepository,
    )
    {
        this.userRepository = userRepository;
        this.branchRepository = branchRepository;
        this.orderlineRepository = orderlineRepository;
        this.orderCategoryRepository = orderCategoryRepository;
        this.productRepository = productRepository;
        this.uomRepository = uomRepository;
        
    }
    public void UserRepositoryForSomeActio(){
        this.userRepository.<callSomeMethod>();
    }
}

There are some points, I want to raise here:

  • We need to define the list of private varaibles for holding the instance of appropriated repositories (such as: private IUOMRepository uomRepository;)
  • The constructor has many parameters.
  • The body of constructor mostly assigns the injected instances to private parameters (such as:  this.userRepository = userRepository;)

This is the real code for my application using Dependency Injection for one of the core entities of system:

namespace App.Services.Impl
{
    public class DistributionListService : IDistributionListService
    {
        private IDistributionListRepository _distributionListRepository;
        private IDistributionPeriodRepository _distributionPeriodRepository;
        private IGeoRouteNorpostRepository _geoRouteNorpostRepository;
        private IUnaddressedOrderRepository _unaddressedOrderRepository;
        private IAddressedOrderSummaryPerRouteRepository _addressedOrderSummaryPerRouteRepository;
        private IOrderUnaddressedGeoRouteRepository _orderUnaddressedGeoRouteRepository;
        private IUserRepository _userRepository;
        private IVehicleRepository _vehicleRepository;
        private IGeoRoutePackageRepository _routePackageRepository;
        private IGeoRoutePackageRouteRepository _geoRoutePackageRouteRepository;
        private IDepartmentRepository _departmentRepository;
        private IAddressedOrderItemsDeliveryTimeRepository _addressedOrderItemsDeliveryTimeRepository;
        private ISortingTimeRepository _sortingTimeRepository;
        private IOrderRepository _orderRepository;
        private IDepartmentDistributionPeriodExecutionStatusRepository _distributionPeriodExecutionStatusRepository;
        private IDistributionPeriodService _distributionPeriodService;
        private IGeoRouteHouseholdService _geoRouteHouseholdService;

        public DistributionListService(
            IDistributionPeriodService distributionPeriodService,
            IGeoRoutePackageRouteRepository geoRoutePackageRouteRepository,
            IGeoRouteHouseholdService geoRouteHouseholdService,
            IDistributionListRepository distributionListRepository,
            IDistributionPeriodRepository distributionPeriodRepository,
            IGeoRouteNorpostRepository geoRouteNorpostRepository,
            IUnaddressedOrderRepository unaddressedOrderRepository,
            IAddressedOrderSummaryPerRouteRepository addressedOrderSummaryPerRouteRepository,
            IOrderUnaddressedGeoRouteRepository orderUnaddressedGeoRouteRepository,
            IUserRepository userRepository,
            IVehicleRepository vehicleRepository,
            IGeoRoutePackageRepository geoRoutePackageRepository,
            IDepartmentRepository departmentRepository,
            IAddressedOrderItemsDeliveryTimeRepository addressedOrderItemsDeliveryTimeRepository,
            ISortingTimeRepository sortingTimeRepository,
            IDepartmentDistributionPeriodExecutionStatusRepository departmentDistributionPeriodExecutionStatusRepository
            )
        {
            //assign those injected to private variables
        }
        public void SomeMethod(){
            // Use 3 of above repositories
        }
    }
}

 

In specified method of those service class, we use just some of them (mostly around 3).

Let imaging the execution flow of the calling to "SomeMethod" of "DistributionListService"  above at the fist time.

  • The system looks for instance of IDistributionListService
  • System recognises that this implementation has dependency on 15 other repositories.
  • Those repositories will be created and passed as parameter of  DistributionListService cosntructor.
  • System invokes "SomeMethod" and consumes 3 of them for its business logic.

Review again, We create instance of 15 repositories. This process may require attention to create other dependency objects to those repositories.

Consequence, the long list of objects need to be create before doing the business logic.

In DI, we can manage the life time of the instance (search "IoC" or "Inversion Of Control" on internet ), for example: Single, Transient, ...

  1. With Singleton:
  • All registered types will be create once.
  • The next time, We can get it back from memory.

In the context of enterprise application, we will have many classes always existed in memory of server and only part of them frequenly used. It means, we did not use memory of server well enough.

  1. With Transient:
  • All registered types will be create once.

In the context of enterprise application, we will have core objects/ major objects that have many dependency object (as sample above). So creating instance of this type requires a lot of other dependency types created in subsequency and use some of them. It means, we did not use the power of server good enough.

IoC - Inversion Of Control

For improving above issue, I decide to use IoC in method. I mean, we will resolve and use appropriated repositories if need.

The code above can be changed to:

namespace App.Services.Impl
{
    public class DistributionListService : IDistributionListService
    {
        public DistributionListService()
        {
            //oh yeah, I'm free and can be removed from the class now
        }
        public void SomeMethod(){
            IResitory1 repo1 = IoC.Resolve<IResitory1>();
            IResitory2 repo2 = IoC.Resolve<IResitory2>();
            IResitory3 repo3 = IoC.Resolve<IResitory3>();
            // and use above repositories for logic business
        }
    }
}

In this cde, we can see:

  • it looks nicer.
  • We can add or remove unused dependency types without impact to other code.
  • We resolve what we need to use. all of those repos will be disposed as default.

So in this way, I think we can balance between memory and power of server in context of enterprise application.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Vietnam Vietnam
I have more than 8 years in web development for multiple types of applications (ERP, Education System, ...).
I usually organize training/ coaching on specified topic (such as: RESTful/ WebApi, Angular2, BEM, LESS, SASS, EF, NodeJs ....). Please contact me on Skype (tranthanhtu83) or email (contact@tranthanhtu.vn) if need.
For more information about me, Please visit http://www.tranthanhtu.vn/page/about-me

Comments and Discussions

 
QuestionMy vote of 1 - DI is a form of IoC Pin
TheGreatAndPowerfulOz16-Jun-17 10:52
TheGreatAndPowerfulOz16-Jun-17 10:52 
AnswerRe: My vote of 1 - DI is a form of IoC Pin
tranthanhtu.vn16-Jun-17 23:32
professionaltranthanhtu.vn16-Jun-17 23:32 
GeneralMy vote of 4 Pin
catmeo3-Jun-17 20:40
catmeo3-Jun-17 20:40 
AnswerRe: My vote of 4 Pin
tranthanhtu.vn4-Jun-17 3:40
professionaltranthanhtu.vn4-Jun-17 3:40 
SuggestionSimplify Pin
Kirk Wood30-May-17 12:44
Kirk Wood30-May-17 12:44 
GeneralRe: Simplify Pin
tranthanhtu.vn30-May-17 16:35
professionaltranthanhtu.vn30-May-17 16:35 
QuestionNot a good DI example Pin
Member 78232112-May-17 5:50
Member 78232112-May-17 5:50 
AnswerRe: Not a good DI example Pin
tranthanhtu.vn2-May-17 19:32
professionaltranthanhtu.vn2-May-17 19:32 
Question[My vote of 1] this is just wrong. Pin
DavideGuida2-Nov-16 4:28
DavideGuida2-Nov-16 4:28 
AnswerRe: [My vote of 1] this is just wrong. Pin
tranthanhtu.vn2-Nov-16 5:58
professionaltranthanhtu.vn2-Nov-16 5:58 
GeneralRe: [My vote of 1] this is just wrong. Pin
DavideGuida2-Nov-16 6:07
DavideGuida2-Nov-16 6:07 
GeneralRe: [My vote of 1] this is just wrong. Pin
tranthanhtu.vn2-Nov-16 6:28
professionaltranthanhtu.vn2-Nov-16 6:28 
AnswerRe: [My vote of 1] this is just wrong. Pin
tranthanhtu.vn2-Nov-16 7:49
professionaltranthanhtu.vn2-Nov-16 7:49 
General[My vote of 1] It looks nicer, but it's wrong Pin
Stefan.Balan1-Nov-16 22:59
Stefan.Balan1-Nov-16 22:59 
GeneralRe: [My vote of 1] It looks nicer, but it's wrong Pin
tranthanhtu.vn1-Nov-16 23:17
professionaltranthanhtu.vn1-Nov-16 23:17 
GeneralRe: [My vote of 1] It looks nicer, but it's wrong Pin
Paolo Vigori15-Nov-16 0:46
Paolo Vigori15-Nov-16 0:46 
AnswerRe: [My vote of 1] It looks nicer, but it's wrong Pin
tranthanhtu.vn15-Nov-16 1:12
professionaltranthanhtu.vn15-Nov-16 1:12 
GeneralRe: [My vote of 1] It looks nicer, but it's wrong Pin
DaveMertens5-Jan-17 5:15
DaveMertens5-Jan-17 5:15 
AnswerRe: [My vote of 1] It looks nicer, but it's wrong Pin
tranthanhtu.vn5-Jan-17 14:43
professionaltranthanhtu.vn5-Jan-17 14:43 
GeneralRe: [My vote of 1] It looks nicer, but it's wrong Pin
tranthanhtu.vn1-Nov-16 23:19
professionaltranthanhtu.vn1-Nov-16 23:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.