Qualms over the ‘flexibility’ advantage of using dependency injection

I’m currently studying dependency injection and I’m having some issues with the so called ‘flexibility’ advantage of using dependency injection.

The flexibility advantage is mentioned in post Criticism and disadvantages of dependency injection, where it is mentioned that dependency injection enables
“switching implementations quickly (DbLogger instead of ConsoleLogger for example)”

I’m really having qualms about how this ‘switching’ can occur, and this is probably due to my limited experience. To elaborate on my confusion, I will mainly use constructor injection, which is the one I wish to understand and am working with.

Suppose I have a class User that depends on a class MsSqlConnection. According to the above post (and many other articles), it seems as though User could switch from using MsSqlConnection to MongoDbConnection with much greater ease when using dependency injection. But I fail to see that.

Let’s consider the following example where constructor injection is used.

class User {
    constructor(connection: MsSqlConnection) {}
}

class MsSqlConnection {
    constructor() {}
}

const connection_instance = new MsSqlConnection()
const user = new User(connection_instance ); 

Here, I’m passing connection_instance as the argument of the constructor of User. But if I wanted a different kind of connection, say MongoDbConnection, I will have to declare connection_instance to be a MongoDbConnection. It should look like:

const connection_instance = new MongoDbConnection() // changed to MongoDbConnection; note MongoDbConnection class was not defined
const user = new User(connection_instance); 

However, in addition to creating a connection_instance of type MongoDbConnection, the above code would simply not work. This is because our User class looks like

class User {
    constructor(connection: MsSqlConnection) {}
}

and the constructor of User only takes an argument of type MsSqlConnection, not of type MongoDbConnection. So where is the flexibility? I would have to adapt my constructor and change the code inside of User to adapt to MongoDbConnection.

I feel like I might be missing something rudimentary here… Any answers are very appreciated, and it’d be even greater if they are catered to some beginner (like me).

2

The principle

I’m really having qualms about how this ‘switching’ can occur, and this is probably due to my limited experience. To elaborate on my confusion, I will mainly use constructor injection, which is the one I wish to understand and am working with.

Have you ever walked into a coffee shop, and seen a customer hand the barista their personal coffee cup, so they don’t have to drink from a cardboard cup? In programming terms, the coffee cup is an injected dependency in the coffee making process.

Without dependency injection, that barista would be incapable of making a coffee in anything other than a cardboard cup, or only the types of cup that the barista was explicitly trained in. Just imagine the effort wasted in having to retrain your staff whenever a cup they haven’t seen before is handed to them.
While from a coffee making perspective, there’s nothing inherently wrong with only knowing how to make coffee in a cardboard cup, it’s a pointless hurdle from a customer-oriented perspective.

This also gets at the core benefit of dependency injection. The main purpose is not to the benefit of the class you inject the dependencies in (the barista), the benefit is gained on the higher level, organisationally speaking (the coffee shop and their customers).


The practice

Suppose I have a class User that depends on a class MsSqlConnection. According to the above post (and many other articles), it seems as though User could switch from using MsSqlConnection to MongoDbConnection with much greater ease when using dependency injection. But I fail to see that.

What you’ve missed here is that the swappability of two concrete classes only works when these classes have a shared ancestry (interface or base class), and the injected dependency is of that shared type.

So instead of:

class User {
    constructor(connection: MsSqlConnection) {}
}

You should be doing something along the lines of:

class User {
    constructor(connection: IDatabaseConnection) {}
}

interface IDatabaseConnection {
    // ...
}

class MsSqlConnection implements IDatabaseConnection {
    // ...
}

class MongoDbConnection implements IDatabaseConnection {
    // ...
}

If a concrete example helps better, let’s look back at our barista. The bad barista doesn’t inject their dependency at all. He just uses a cardboard cup, and he is incapable of making coffee in anything else.

class BadBarista {
    makeEspresso() {
        let cup = new CardboardCup();
        let coffee = new Coffee();

        cup.Add(coffee);

        return cup;
    }
}

Note: I’m using method injection instead of constructor injection, but functionally speaking this is the same principle of DI at play.

Your code example, when applied to our barista, would be something like this:

class YourBarista {
    makeEspresso(cup: CardboardCup) {
        let coffee = new Coffee();

        cup.Add(coffee);

        return cup;
    }
}

Technically, the cup is being injected. However, it’s stil forced to be a CardboardCup. That doesn’t really yield a benefit. The goal was to make it so that any cup could be passed.

So a better implementation would be:

class GoodBarista {
    makeEspresso(cup : ICup) {
        let coffee = new Coffee();

        cup.Add(coffee);

        return cup;
    }
}

Now, any class that implements the ICup interface can be passed into this method. You are no longer forced to use cardboard cup, therefore making it easy to swap which cup you use without needing to change/update your barista.


The documentation

In case this is new to you, look up polymorphism (and interfaces) instead of dependency injection. Dependency injection, or at least the swappability of components that you can leverage using dependency injection, relies on the concepts of polymorphism, i.e. the ability to substitute one thing for another, provided that they are defined as being (partially) the same thing.

5

It only lets you switch between different implementations of the same interface. This wouldn’t typically be used for something like switching between Mongo and MsSql, unless you had a common interface between them, like if different customers used different databases. Typically, it’s used to run different implementations in test and production, so you don’t have to spin up an entire database just to run unit tests.

7

This is where you’re doing it wrong:

constructor(connection: MsSqlConnection)

Rather than taking an object of type MsSqlConnection, you should define an interface which includes the functionality you need from any database connection object, make your connection objects implement that interface, and your constructor take an instance of the interface, not of the specific types.

0

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật