Our ChatClient machinery to connect to a server is rather more complex than necessary. The ChatClient.get_connection and ChatClient.connection property setters are there mostly to allow us to easily replace with mocks the connections that our client sets up.
This is because ChatClient has a dependency, a dependency on the Connection object, and it tries to satisfy that dependency all by itself. It's like when you are hungry... You depend on food to solve your need, so you go to the fridge, take some ingredients, turn on the oven, and cook a meal yourself. Then you can eat. Or... you can call a restaurant and order a meal.
Dependency injection gives you a way to take the restaurant path. If your ChatClient needs a connection, instead of trying to get a connection itself, it can ask for a connection and someone else will take care of providing it.
In most dependency injection systems, there is an injector that will take care of getting...