test.ical.ly | getting PHP by the balls

May/10

12

Why are interfaces widely ignored in the PHP world and what use do they have when working with symfony?

interfaceEvery once in a while I stumble upon interfaces or somebody mentions them to me. Whenever this happens I realise that the use of Interfaces as an OOP key feature in PHP is next to none at all. But why is that?

Try to google for “php interfaces” and you will get mostly three different kind of results.

  1. Links to the OO/interface section of the  PHP manual
  2. Links to website explaining how to use interfaces for dummies
  3. Links to discussions about the difference between interfaces and abstract classes

What you will rarely see is a link to an interface used in some project. Also if you grep the core of symfony you will find 9 Interfaces for Doctrine, 14 for phing, 11 for Propel and 44 for swiftmailer. symfony itself defines 4 interfaces only.

And symfony is no exception. While interfaces a very common in languages like Java they are almost not present throughout many PHP projects. But why?

What are interfaces?

The best description I could find so far is: An interface is a contract.

  • An interface defines public methods that a class needs to implement
  • An interface does not contain any code
  • A class can implement multiple interfaces
  • Interfaces can be used for type hinting

Basically if you see a class implementing an interface you know how to use it no matter how the implementation within the class is achieved.

What are abstract classes?

  • An abstract class can implement methods (code)
  • An abstract class can define abstract methods (no code)
  • An abstract class can not be instantiated
  • Classes can only inherit from one abstract class

And the difference is now what?

Abstract classes and interfaces are in some ways similar but they do each have their unique use cases.

The simplest rule is:

  • If you write an abstract class containing only abstract methods you use an abstract class as an interface.

On many sites discussion the differences you will find that the fact that many interfaces can be implemented but only one abstract class can be inherited from is the main distinction.

In my humble opinion that is not the case. I even think that classes implementing many interfaces are likely (not always) to be badly designed as many interfaces probably means many concerns within one class.

The main difference is that abstract classes already provide implementations of methods and interfaces do not.

This implies that there is a different concept behind both constructs.

Methods inherited from abstract classes imply that the shared implementation is common to all descending classes.

Methods defined in an interface imply that their implementation needs to be dedicated to the implementing class.

A simple example for an interface is sfLoggerInterface.

interface sfLoggerInterface
{
  /**
   * Logs a message.
   *
   * @param string $message   Message
   * @param string $priority  Message priority
   */
  public function log($message, $priority = null);
}

It defines only a single method log() and if you think about it you will realise that though the job if this method is the same no matter what the implementation is the details will be very different whether you log to a file, a database, syslog or somewhere else.

A simple example for an abstract class does not exist as abstract classes should always contain code. But a simple enough example is sfCache.

In sfCache you will find implementations of methods that are thought to be common throughout all cache classes. The effect of this is of course to avoid duplicate code.

It also defines a few abstract methods where the implementation will be uncommon.

Now you could argue to strip sfCache from all abstract methods and move them to an interface. But other than to server your academic motivation what benefit would it have? It would only create a new file that does not make sense on its own and so would increase the overall complexity.

See what the Java tutorials say about this.

Unlike interfaces, abstract classes can contain fields that are not static and final, and they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead.

Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable, for example.

By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the abstract class), but also have some differences (the abstract methods).

(taken from java.sun.com)

As a rule of thumb you could define the following:

  • Use abstract classes to share function
  • Use interfaces to share usage

I guess one of the reasons why interfaces are not used very often by PHP developers is that in PHP you often start to code right away and you would start thinking sharing code later on when you have something to share. This way around you rarely consider contracts as the usage is already developed and negotiated. This can be considered bad practice of course and probably should be but it is my only explanation for the lack of interfaces out there.

How to handle interfaces if working with a framework?

Of course the use of interfaces and abstract classes when working within a framework are no different to the above. There are however things you should consider about when to use them.

Many developers especially in the Java world are used to design interfaces before the implementation. They build the contracts first and determine how the interaction of classes works before starting to code.

However in frameworks such as symfony a good deal of the coding is done via scaffolding and code generation. There is no point to define interfaces for generated code!

Take models for example no matter if generated by Propel or Doctrine, there is no need to write an interface defining all the getters and setters and such because the classes are not implemented against this interface. They are generated against their schema. The schema defines the interface.

Now of course you will add custom methods to the generated classes but will you really implement an interface on more than one class? If not what’s the point? And if isn’t the implementation of it the same for all classes?

In most cases I assume that you want to define a common behaviour for you models. You want them to share some methods and attributes. Now in Doctrine you should probably create a behaviour for this and specify it in the schema of your models. The code in the case would not be implemented (duplicated) nor would it be inherited instead it would be delegated. I’m not sure but there is probably a similar feature in Propel.

And always ask yourself if you really do share the usage across all classes that should implement your interface. Will you ever pass objects to a method that have a common interface but no common implementation (parent class) ?

There will be situations where all this is appropriate no doubt about it. But for the best part of your work you will deal with models, controllers and templates and the interaction is defined already by the framework..

RSS Feed

21 Comments for Why are interfaces widely ignored in the PHP world and what use do they have when working with symfony?

Tweets that mention • Why are interfaces widely ignored in the PHP world and what use do they have when working with symfony? | test.ical.ly -- Topsy.com | 12. May 2010 at 06:02

[...] This post was mentioned on Twitter by Jakub Zalas. Jakub Zalas said: Why are interfaces widely ignored in the PHP world and what use do they have when working with symfony? http://bit.ly/aSYIAL #php #symfony [...]

Gnarf | 12. May 2010 at 06:59

PHP Interfaces are quite useless to define contracts because PHP is a loosely typed language. How dumb would be a contract where you cannot ensure what you’ll obtain contracting with the API.

And don’t get me started on using phpdoc for that. Already saw things like @return null|boolean|int…

PHP is not Java.

Christof | 12. May 2010 at 07:31

A lot of the current frameworks are also very tightly coupled. Sometimes all of the classes inherit from the same root class. This happens when you use abstract classes as interfaces.

As we are moving to the second generation of frameworks (Symfony 2, Doctrine 2, ZF something) we will see a lot more interfaces being used to decouple the classes and make it possible to use and test the components independently.

But @Gnarf is right too, without the use of type hinting and tightening of what your methods are expecting, interfaces and abstract classes are useless.

Giorgio Sironi | 12. May 2010 at 08:09

We’re not so in a bad situation:

@Gnarf: with the current implementation we have type hinting on parameters but not on return types. But in dynamic languages tests are the mean to assert these things, not compile-time checks. Due to the nature of the language, a check on the return value could only be done at runtime, so if you have a test that runs it you’re fine.

Giorgio Sironi | 12. May 2010 at 08:10

Zend Framework 1.x trunk:
[08:51:05][giorgio@Marty:~/svn/trunk]$ grep -r ‘^interface’ . | grep -v \.svn | wc
187 408 20282
187 interfaces…

skoop | 12. May 2010 at 14:12

The thing is: in PHP there are very little standards. In Java (and some other languages) there are API standards that are upheld even throughout different projects offering the same functionality. The idea of this is that you could easily exchange one for the other. PHP frameworks, both full-stack and component frameworks, seem to be aiming to just be usable by itself. They don’t work on interoperability too much.

This is changing. The new Framework Interoperability Group that is working on standards will hopefully work on things like this more and more. Their first focus is naming/autoloading, but hopefully after that they will also work on API standards, especially for the easy things like logging, caching etc, because those implementations are pretty common throughout every framework.

Having said that, I think that if you look in codebases of bigger companies using PHP, you will (or at least should) encounter more interfaces, for the simple reason that they will guide developers new to certain APIs.

I do agree, interfaces should be used more in the PHP world.

I disagree with Gnarf that using contracts in PHP code is useless because of it’s loose typing: For *good* developers this should not matter. PHPDoc will help for sure, and also typehinting using interfacenames instead of classnames will help with ensuring a common API set is implemented for passed parameters.

Ulf | 12. May 2010 at 15:12

I strongly believe that interface do make sense even in a loosely typed language like php. They define not only contracts between classes within one application they can also define contracts between two applications. Or they define what a class should be able to do. The ZF does make a heavy use of interfaces and they do make sense most of the time. I either use the concrete implementation of their interface or I wrote my own Adapter /WhatEver.

@Gnarf
Surely a method can return a boolean, int, double, Object and so one at the same time but it should not. I can also programm in PHP and note use objects at all or just write spaghetti-code. It is possible to do so, does not mean to do it that way – especially within PHP.

puch | 17. May 2010 at 07:43

I don’t agree with the opinion that an Interface is useless in a loosy-typed language.
It’s a good practice anyway to define contracts, because contracts are not always “language restrictions” but “conceptual agreements” to garantee the compatibility between pieces of sw.

And I’m pretty sure that in the future is going to be useful: For instance, there will be tools to check type integrity before running applications. And you can always use Interfaces for “typed arguments” in methods. And you can already use interfaces and check them in your unit and functional tests.

And, by the way, Symfony use interfaces, in fact, multiple interfacing (that, for me, it’s a good practice):

“sfDoctrineManager” implements Iterator and Countable

Author comment by Christian | 17. May 2010 at 11:16

@puch Let me clarify. I am not at all arguing against the use of interfaces. I was merely stating that they are not widely used in PHP. And I also pointed out that in my opinion interfaces for generated code are a waste of time.
For everything that you are going to implement on your own and that you are going to need multiple implementations of interfaces make a lot sense.

Munim | 18. May 2010 at 09:48

I just don’t need the point of using interfaces anywhere.. as do most php developers. That is why they are so rarely used.

Les | 18. May 2010 at 10:33

Interfaces are ignored because they are misunderstood in regards to PHP.

Professionals use interfaces – they always take advantage of a language – so my opinion is that it is only those non professionals who fail to see the advantages.

PHP is an easy language to pick up and learn and because of this so many non professionals – amateurs in other words (”would be developers”) – have no understanding and/or education regarding computer science – even on the most basic levels.

The problem isn’t the language – but the people who are to ignorant – or stupid – to fully understand a technology.

Artem Nezvigin | 18. May 2010 at 16:19

@Munim

Here’s an example of when to use an interface. Let’s say you need to build a File Store. The sole purpose of the file store is… to store files :) When a user uploads an avatar, you want to store that. When a user attaches files to some record, you want to store files there.

How would you create this? Here’s how you should (namespaces not included).

Create an interface called FileStore_Service_Interface that forces implementation of the following method: get(), put(), pull(), delete()

get($filePath) – Should return a URL to the file.
put($filePath, $fileContents) – Should save the file into the filestore.
pull($filePath) – Should return the file contents for the file.
delete($filePath) – Deletes the file from the file store.

As long as the a class implements the above interface, you can add CDN support to your application by simply flipping a switch.

FileStore_Service_Local is the local file store class, it implements FileStore_Service_interface. You implement get(), put(), pull() and delete() to work the local file system and to create/read/delete files from a directory you set in configuration (ie: /path/to/your/app/public/files)

FileStore_Service_Amazon is something you could implement later. It implements the same interface so none of your business logic will change. All that will change is files are now stored in the Amazon CDN instead of the local file store.

So why not just create an abstract class? Because you may actually need an abstract class to implement some base functionality. For example, FileStore_Service_Amazon may use REST+HTTP to communicate with Amazon. You may implement another CDN that also uses REST+HTTP, so that’s where the abstract class comes in.

FileStore_Service_Amazon extends FileStore_Service_HttpAbstract implements FileStore_Service_Interface

And there you have it. They key is understanding that when you use an abstract class instead of an interface you are *defining implementation*, which is dangerous.

The reason why PHP developers don’t use interfaces is that the projects they work on are small enough that it doesn’t matter. Going back 1 year later and modifying existing code is easier that building for flexibility on day 1. This does not hold true for larger web applications, however.

This is why you typically see interfaces in large frameworks (like Zend Framework) and large web applications. Both of these heavily benefit from the flexibility up front.

Author comment by Christian | 18. May 2010 at 17:29

@Artem Thank you, I’ve got nothing to add! :)

Max’ Lesestoff zum Wochenende | PHP hates me - Der PHP Blog | 22. May 2010 at 06:23

[...] von Zend_Translate das im nächsten Minor-Release zur Verfügung steht: Translation Routing. • Why are interfaces widely ignored in the PHP world and what use do they have when working with s… Christian schreibt über Interfaces in PHP und warum sie in der PHP Welt gerne ignoriert werden [...]

PHP: When to use an Interface | 25. May 2010 at 00:38

[...] post: By Artem Nezvigin from Why are interfaces widely ignored in the PHP world and what use do they have when working with symfo… This entry was posted in Uncategorized and tagged Interface, PHP. Bookmark the permalink. Post a [...]

Interfaces Make Testing Easier | BrandonSavage.net | 26. May 2010 at 12:19

[...] If you are new here, you might want to subscribe to the RSS feed for updates on this topic.I, along with others, have written on interfaces many times before but recently I had occasion to find a new thing about [...]

Gnarf | 28. May 2010 at 07:53

So let’s have a look at a basic Doctrine call, say

/**
* @return Doctrine_Collection|null
*/
public function getPosts() {
return $this->createQuery(’p')->where(’p.is_published = 1′)->execute();
}

This will return a Doctrine_Collection or a null. PHP is full of that, because it’s loosely typed. If I had an interface specifying a getPosts() method (yeah that would be dumb), I just can ensure that some instance is able to get posts, but not if I will have a null or a collection of posts. so if I do:

$array = Doctrine::getTable(’Post’)->getPosts()->toArray()

I will have a “fatal error” because I’m calling a ->toArray() method from a null. The good practice would be to use exception for that, but it’s even worse than interface in php: nonetheless people are rarely using them, but they’re using them mostly the very wrong way.

So if even the best and/or most popular libs around are using this “feature” of php, interfaces make no sense. If you want to use interfaces, do Java. If you want to use the php language for what it provides, use it but don’t bother with trying to redo Java with it. Waste of time, and efficiency.

Cheers

David Harkness | 7. June 2010 at 23:11

@Gnarf – I don’t understand your point. Whether Doctrine_Collection is a class or interface matters not. If getPosts() can return null you must check the return value for null before making method calls on it.

I myself find interfaces very useful when building systems that are designed to be extended. For example I recently built a spam detection module for our site using a naive Bayesian filter. The first algorithm I wrote to calculate the spamicity of a word was a mishmash of if checks for configuration parameters (min/max value, weight, default spamicity, whitespace characters, maximum word length, stop words, etc). As I added more features the code became needlessly complicated.

I refactored it into several pieces (word extractor, filter, and calculator), and one was the WordCalculator interface with a single method “float calculate(string $word, int $spamCount, int $hamCount)”. To this I added an abstract class that allowed one WordCalculator to decorate (wrap) another. This allowed me to write one implementation for each feature: weighting, final spamicity allowed range, etc. Not only was it easier to understand the final system, but it was far easier to test it.

When you work with patterns you’ll find that interfaces can be most useful. Obviously, generating code is not writing code to an interface so there’s no point there. If you don’t gain anything I see no reason to pay the cost of writing a separate interface. That your interface would change with the every schema change is a sure sign that there’s no real interface to be had anyway, no pre-designed behavior that you can implement multiple times.

@Les – I hardly see the point of your invective comment. Claiming someone is ignorant or stupid simply because they don’t follow your preferred engineering methods doesn’t further the discussion, nor will it inspire them to seek more knowledge. I claim one can hardly be ignorant if they’ve taught themselves enough to build working software.

Author comment by Christian | 8. June 2010 at 06:00

@David thanks for the example!

Revue de presse Industrialisation PHP de la semaine 23 (2010) | Industrialisation PHP | 14. June 2010 at 11:27

[...] qui ne tirent pas suffisamment parti de la Programmation Orientée Objet. Christian Schaefer prend l'exemple des interfaces qui sont trop souvent ignorées ou mal utilisées alors qu'elles apportent tant de souplesse lors [...]

Chris Henry | 16. June 2010 at 05:56

I think a lot of developers wound up working with PHP to avoid having to satisfy strict requirements. It can be quite liberating to not have write code just to satisfy a set of draconian requirements. Many, if not most, PHP projects wind up staying small enough that there is no need to assert a common set of functions that must exist.

The projects named here that do use interfaces certainly make good use of them. I use Phing, have written extensions for it, and can see the need for it. However, I think the vast majority of PHP developers have no real need to ever write an interface.

Leave a comment!

<< Thoughts about using stream wrappers for everything

Symfony 2 now following the standards rather than setting them >>

Find it!

Theme Design by devolux.org