Sunday, January 29, 2012

Type hinting is bad!

Type hinting is bad..if it's done wrong.

Type hinting was introduced in PHP 5 allowing you to force parameters to be specific types of objects or an array. At first glance this is great because of the built-in support for type validation. In the example below there's a type hint on the function transport forcing $car to be of type Car.
class Car {
 public function load(array $cargo) { ... }

 public function go() { ... }
}

function transport(Car $car) {
 $cargo = array('groceries', 'children', 'misc items');
 $car->load($cargo);
 $car->go();
}

$car = new Car();
transport($car);
We can use $car without having to write code to check it's type. A fatal error is thrown if $car is not an instance of type Car.

The problem with this style of programming is you're sacrificing one of the biggest strengths of PHP: the ability to duck type. After all this time of programming with a dynamic language why have we become so concerned with types? Had we not put a type hint on the transport function the code would have still worked. Let's remove the Car type hint.
function transport($car) {
 $cargo = array('groceries', 'children', 'misc items');
 $car->load($cargo);
 $car->go();
}

$car = new Car();
transport($car);
This is better because it is more flexible. $car can be anything as long as it can load() and go(). You can change $car to be a Van and you'll still get your cargo safely loaded and transported assuming Van can load() and go().
$car = new Van();
transport($car);

Can't you use inheritance in this case and still utilize type hinting?
Inheritance could be used and the function would take advantage of subtype polymorphism.
abstract class Vehicle {
  abstract public function load(array $cargo);
  abstract public function go();
}

class Car extends Vehicle { ... }

class Van extends Vehicle { ...}

function transport(Vehicle $vehicle) {
 $cargo = array('groceries', 'children', 'misc items');
 $vehicle->load($cargo);
 $vehicle->go();
}

$vehicle = new Van();
transport($vehicle);
This is still not ideal. What if you wanted to use something other than a Vehicle to do your transportation (e.g. Boat, Train, or Horse and Wagon)? To make this code more reusable we should follow an object-oriented design principle: "Program to an interface, not an implementation". Fundamentally we don't care what an object is; instead we care about what an object can do.
interface ITransporter {
  public function load(array $cargo);
  public function go();
}

class Car implements ITransporter { ... }

class Van implements ITransporter { ... }

class Horse implements ITransporter { ... }

function transport(ITransporter $transporter) {
  $cargo = array('groceries', 'children', 'misc items');
  $transporter->load($cargo);
  $transporter->go();
}

$transporter = new Horse();
transport($transporter);
If you wanted maximum flexibility why even put an object or interface type hint? As long as the parameter can load() and go() the transport function should work. The type hint validation is only enforced at runtime. If an object was passed into the transport function that didn't have a load or go method you would still get a fatal runtime error. It seems like the type hint isn't useful.
That's almost completely true. There is a subtlety. Using a type hint would error sooner. This may or may not be important to you.
function transport(ITransporter $transporter) {
  $cargo = getCargo();
  $transporter->load($cargo);
  $transporter->go();
}
In this example, what if getCargo() uses an external service like a database connection or a web service. It's nice to know $transporter can load() and go() before using resources to getCargo(). If $transporter didn't support the necessary interface then an error would be thrown immediately and no resources would be wasted. It's up to you to decide which is more important: the ability to error early or the flexibility of using duck typing.
I use type hinting because my IDE uses it to provide code completion.
You can use annotations and/or interface type hinting and your IDE will provide code completion. You don't have to sacrifice good object oriented design for the sake of your IDE.

7 comments:

  1. So, it's very good for you to know something about interfaces :)
    You are on the right way :)

    ReplyDelete
  2. Wow amazing i saw the article with execution models you had posted. It was such informative. Really its a wonderful article. Thank you for sharing and please keep update like this type of article because i want to learn more relevant to this topic.


    Salesforce Training

    ReplyDelete



  3. This content creates a new hope and inspiration with in me. Thanks for sharing article like this. The way you have stated everything above is quite awesome. Keep blogging like this. Thanks.


    SAP training in Chennai

    ReplyDelete
  4. Excellent and very cool idea and the subject at the top of magnificence and I am happy to this post..Interesting post! Thanks for writing it. What's wrong with this kind of post exactly? It follows your previous guideline for post length as well as clarity..

    Digital marketing company in Chennai

    ReplyDelete
  5. Wonderful blog.. Thanks for sharing informative blog.. its very useful to me..

    iOS Training in Chennai

    ReplyDelete