Books about dependency injection and inversion principle

Just a question for the PHP developers.

Are there any good books on Dependency Inversion / Dependency injection (php-di), which deal with some more difficult scenarios.

Injecting other classes on runetime, within other classes when certain conditions are met.
I have read Sergey zhuk’s book “PHP OOP WAY” hoping it will delve deeper into this topic. Are there any other books that cover this piece?

I wouldn’t say there is a dedicated book to the topic(s) because they are really not that complicated to understand. They usually warrant a decent sized chapter of most books. You might be better off finding one off articles on the Internet that talk about the practice… blogs are usually good for such topics.

If you understand that classes should depend on abstractions (rather than concrete implementations of classes) when injecting classes, you have 85% of the topic understood.

For instance, we might define something like an interface for a vehicle called IVehicle. It might force thinks like drive(), getNumberOfWheels() and honkHorn(). Now a car can implement this interface, a motorcycle could implement this interface or even ORV could implement this interface. Doesn’t matter.

Now we might have another class that relies on a vehicle(s) to do something. We inject the classes through the constructor but not as an implementation like Car but as IVehicle.

public function __construct(IVehicle $vehicle) {
   // Honk its horn (but we don't care what type of vehicle it is.
  $vehicle->honkHorn();
}

Of course with this implementation now, you can do whatever conditional logic we want and inject a Car, a MotorCycle, an ORV or whatever. The class is tied to the interface (an abstraction) and not to independent concrete classes. This affords us abilities like introducing a new vehicle type later and as long as it implements IVehicle everything will just work.

This is a short version of the ideas, but did that take a whole book to explain 85% of the idea? Nope. :slight_smile:

1 Like

Could you give an example of this? Can be a toy example, but I just want to make sure I understand the question correctly.

Hi @rpkamp (always nice to see you :cowboy_hat_face:)

@Martyr2 The concept of dependency injection is not that difficult no, and so is its use.

I’m more interested in being able to switch classes. Let’s sketch a real-live scenario:

I drew it out a bit to make it a bit clearer :slight_smile:

Let’s say we have a heavy application that is used by a lot of users (20000x) so there are a lot of queries made on the database. For that reason, we have a master/slave setup (the one that replicates the data to the slave database and this one is read-only). When somebody goes to the /getInfo route the Info controller is called.

This will load data from the read-only database based on the method that is called in the controller.

Now in the data provider/service, I would like to disconnect a so that we can give a database object with it depending on the route. Which gives you the possibility to read out the read-only database and also the possibility to easily revert this. And Which gives you a loosely coupled dependency.

The read-only is an instance of Database, but with other credentials/database server.

You would not be “switching classes” in this case. Using your sketch, the “Data service” should be able to decide if the “master database” or one of the “read slaves” should be used. In most cases, it would also be tied to the cache server like Redis, where it would cache queries again depending on logic for X period of time.

When it receives a request, it will parse the query, decide if it should go to write or read, if read, it will check if it has a valid cache result if it will use it, if not it will pull from the read slave, etc.

Now, at 200k users you do not really need the cache part, unless you have some expensive queries. Though utilizing cache of the queries with varying degrees of TTL, can really save on database server cost (i.e. you won’t need as many slave servers).

If you are talking about having the ability to easily change between if the system should use MySQL, Cassandra, or even a text file for storage solution depending on the connection/user. In this case, I would recommend looking into hexagonal architecture.

Yes, exactly this. It’s up to the service to know which database to use. So the service gets injected both databases and then runtime decides which to use when, based on what the request is (read/write).

Do take care that during transactions all reads should go the write database too, otherwise any reads during the transaction will not take into account anything that changed inside the transaction.

If you use Doctrine DBAL for you database connection, you could look into using their PrimaryReadReplicaConnection.