Type hint and Decoupling

While type hinting is important to help improve your codebase usage and testing. For all the fun and joy it brings it can also lead to some of the worst maintenance hell if it is not done correctly. As one famous Uncle Ben used to say with great power comes great responsibility so here’s a quick reminder on how to properly type-hint.

To illustrate this, I will use the Carbon package. This is in no way shape or form a criticism of the package but I think it’s usage makes it a great use case:

Let’s say we want to change a date. I’m pretty sure that this piece of code was recently added to a codebase near you.

Carbon\Carbon is a mutable child of PHP’s DateTime class. In 2022, we should stop using DateTime. The class is mutable which means that the number of unpredictable things, this piece of code can do in your codebase is frightening.

Thanksfully for us, the code can be improved by just doing this.

This way side effect are prevented as Carbon\CarbonImmutable is an immutable child of PHP’s DateTimeImmutable class. Last but not least, if this method is part of an interface or of the public API, I would instead suggest doing this:

This way the public API no longer rely on a specific PHP package (it’s decoupled), only this specific implementation does which is OK.

But what about when you do not need to mutate your object ?

There again by using Carbon we largely limit who or what can potentially quickly interact with our API. Instead a way forward would be to do the following:

The code has not changed but by using the CarbonInterface interface, a child interface of DateTimeInterface we allow any Carbon instance mutable or not to use the method.

But wait, since the code is not even changing or doing any funny stuff with date what we should really do is the following:

The following code will work everywhere regardless of the presence of the Carbon package.

TL;DR:

  • is Type-hinting fun: ✅
  • should we still use Carbon (the instance) and DateTime: ❌
  • should we use CarbonImmutable and DateTimeImmutable : ✅
  • Rely on contracts and avoid specific implementations or hard coupling when possible