Go Back   SitePoint Forums > Forum Index > Program Your Site > PHP > PHP Application Design
Newsletter FAQ Members List Calendar Mark Forums Read

New to SitePoint Forums? Register here for free!

SitePoint Sponsor
 
Reply
 
Thread Tools Display Modes
Old Jul 20, 2003, 10:38   #1
seanf
Mlle. Ledoyen
silver trophy
 
seanf's Avatar
 
Join Date: Jan 2001
Location: UK
Posts: 7,312
Interfaces

Bear with me, rambling helps me think!

Would I be right in thinking that interfaces allow you to specify the methods that should exist in a class, allowing you to, for example, create an API?

My thinking and research suggests you would go about it something like this with PHP4:

Interface, which defines the API:
PHP Code:

<?php


    
class Dao {


        function
connect ( $params ) {

            die (
'Method connect must be implemented' );

        }


        function
disconnect ( ) {

            die (
'Method disconnect must be implemented' );

        }


    }

?>
Then we have classes which actually do the work, but use the interface to give errors on missing methods:

PHP Code:

<?php


    
class MysqlDao extends Dao {


        function
connect ( $params ) {

            
// Now we can connect to MySQL, but will get error if method is left out

        
}


        function
disconnect ( ) {

            
// Now we can disconnect from MySQL, but will get error if method is left out

        
}


    }

?>
How does that look?

Sean
seanf is offline   Reply With Quote
Old Jul 20, 2003, 10:45   #2
richard_h
SitePoint Addict
 
richard_h's Avatar
 
Join Date: May 2002
Location: London
Posts: 302
Quote:
How does that look?
Looks good to me
richard_h is offline   Reply With Quote
Old Jul 20, 2003, 10:51   #3
seanf
Mlle. Ledoyen
silver trophy
 
seanf's Avatar
 
Join Date: Jan 2001
Location: UK
Posts: 7,312
Yippee!

Next question, again using a data access object. If you were splitting the methods of your DAO into a number of classes, so that you are grouping related methods, would you create an interface for each related group or use one large interface which each class of related methods uses? If you get what I mean by that very long sentence

Sean
seanf is offline   Reply With Quote
Old Jul 20, 2003, 11:09   #4
seanf
Mlle. Ledoyen
silver trophy
 
seanf's Avatar
 
Join Date: Jan 2001
Location: UK
Posts: 7,312
Perhaps an example would help clarify my question

You're creating an application that will have a number of different parts that need to access stored data, such as session data, user data and monkey data (we all like a bit of monkey data ). Would you create one interface that covers all these things or would you create one interface for session data, one for user data and one for the monkeys?

Sean
seanf is offline   Reply With Quote
Old Jul 20, 2003, 11:32   #5
been
SitePoint Addict
 
been's Avatar
 
Join Date: May 2002
Location: Gent, Belgium
Posts: 283
On the interface design in PHP4, I am doubting between 'correctness' and performance...

Since, the interface does not contain any real programming purpose (this is not very well put, but I hope you'll understand what I'm trying to say ), it imposes a 'useless' overhead since every class extending on the interface class must include it, resulting in disk access and parse time overhead...

I write interfaces too, just for having a base api reference really, but in my code I don't include them and I write
PHP Code:

class SomeClass /* implements SomeInterface */ 

The problem with this is of course, if I 'forget' to put in an overriding method in the class that implements the interface, I don't get an error, whereas if it would be extended, the die() in the interface would warn me about that...

So I'm still doubting about it really

Quote:
Would you create one interface that covers all these things or would you create one interface for session data, one for user data and one for the monkeys?
Maybe I'm not seeing it clear, but is this not a bit like the data abstraction thing?
If so, I'd go for one interface, makes it simpler for the code that uses the objects, it doesn't have to check the exact type of objects it uses, it can just call some methods on it, which are always the same. (Which I guess is a little what polymorphism is all about?)

Argh man, this OOP/Design patterns thing sometimes has my brain soooo running around in circles...
But I like it
been is offline   Reply With Quote
Old Jul 20, 2003, 12:01   #6
seanf
Mlle. Ledoyen
silver trophy
 
seanf's Avatar
 
Join Date: Jan 2001
Location: UK
Posts: 7,312
Quote:
Originally Posted by been
Argh man, this OOP/Design patterns thing sometimes has my brain soooo running around in circles...
But I like it
Same here! Thanks for giving me more to think about

Sean
seanf is offline   Reply With Quote
Old Jul 20, 2003, 13:01   #7
Gybbyl
public static void brain
 
Gybbyl's Avatar
 
Join Date: Jun 2002
Location: Montana, USA
Posts: 650
Quote:
Originally Posted by been
Since, the interface does not contain any real programming purpose, it imposes a 'useless' overhead since every class extending on the interface class must include it, resulting in disk access and parse time overhead...
Everything you do in a programming environment introduces overhead. Including one interface file in php is *not* going to slow your code down at all. Actually, it would be no different than putting your interface in the same file as your class and then running it.

Interfaces allow you to set down solid guidelines for your class hierarchy, and they *force* you to conform to those guidelines. Good example (along with the DAO), would be i/o access. No matter what your source and destination are, you should always use the same methods to get there... So say you are coding to the following interface:
PHP Code:

interface Read

{
    
public function open( $filename );
    
public function readc();
    
public function readLine( $len );
    
public function flush();
    
public function close();
    
public function isEof();
    
protected function isEol();
}
Whenever you make a new child of this interface, say 'stdIn reader', you are going to be FORCED to implement this interface. If you are still complaining about overhead (which still sounds shallow to me, given that basically every person on the face of the planet, and most certainly every production server has more than 1 ghz and loads of RAM at their disposal) -- including 12 lines of an interface is not going to do jack to performance. If you are still skeptical, then maybe you should just include your entire class hierarchy in one file (or go to perl and have your whole class hierarchy on one line). Now, with an interface like this, no matter what data you are reading, you will always know how to read it -- stdIn, file, socket, gzip, whatever.
Quote:
Originally Posted by been
The problem with this is of course, if I 'forget' to put in an overriding method in the class that implements the interface, I don't get an error, whereas if it would be extended, the die() in the interface would warn me about that...
'Forgetting' something like this completely negates the whole idea of APIs and interfaces, which is to maintain a standard way to access/mutate related data. You have *ONE* interface at the top of even one of the branches of your hierarchy, and it saves you AND everyone who is going to code to your API tons of heartache and bugs. Imagine if *aren't* using an interface (or worse yet, not *enforcing* your interface), and 10 seperate people decide that they like your code and they want to extend on it. Say 5 of these people need to use more than one data source throughout the lifetime of their program. Say you don't have a solid api for them to code to. What then? That means they have to duplicate their classes in order to do the same thing of two related sources. This doesn't make sense for them, and it especially doesn't make sense to the author, because it would have been so easy to add one interface. Even, if by some remote possibility there were the slightest bit of data access overhead, is not all the time saved by creating a sound api/interface more than a good trade-off for that overhead?
Gybbyl is offline   Reply With Quote
Old Jul 20, 2003, 14:42   #8
been
SitePoint Addict
 
been's Avatar
 
Join Date: May 2002
Location: Gent, Belgium
Posts: 283
Gybbyl, I can totally understand your points of view...
And I have to say I'm likely too paranoid about performance.
Still my desktop is a PIII450/384Mb and my 'production server' is a K6II350/128Mb so I'm nowhere near the 'Gigahertzes and loads of memory', but all in all that's more my problem I reckon

Quote:
'Forgetting' something like this completely negates the whole idea of APIs and interfaces, which is to maintain a standard way to access/mutate related data.
Well, writing those interface classes prevents me from 'forgetting' really, I just made that point to indicate an important difference in extending and not extending the class. When I subclass an interface class, I copypaste it's api in my editor, so in reality I hardly 'forget' a method...
Quote:
Imagine if *aren't* using an interface (or worse yet, not *enforcing* your interface), and 10 seperate people decide that they like your code and they want to extend on it. Say 5 of these people need to use more than one data source throughout the lifetime of their program. Say you don't have a solid api for them to code to. What then? That means they have to duplicate their classes in order to do the same thing of two related sources.
When more people should like my software (as if ) and start extending on it, they'd still have the interface classes to base the api on. It's true that the interface is not enforced, but isn't that in fact their problem, I mean *if* I should release such code, I would document it properly and the documentation should make the 'interface-thing' more then clear.
Btw, if they write subclasses that do the same thing on related sources, shouldn't then a base class be defined (that /* implements */ the interface) where other classes can inherit from?

I just want to make clear that I'm not trying to argue here in a yes no debate, I want to learn, don't we all .
My reasoning is a result from reading this thread a while back (starting around post #14).
And I also want to state, that It's not my MO to just sacrifice something for a little performance gain.
been is offline   Reply With Quote
Old Jul 20, 2003, 14:49   #9
Gybbyl
public static void brain
 
Gybbyl's Avatar
 
Join Date: Jun 2002
Location: Montana, USA
Posts: 650
Good points all around -- It must be a matter of personal preference, coupled with thought process and peer pressure. Boils down to this: at least we are all using structure in our code.

Gybbyl is offline   Reply With Quote
Old Jul 20, 2003, 16:20   #10
lastcraft
SitePoint Victim
 
lastcraft's Avatar
 
Join Date: Apr 2003
Location: London
Posts: 2,273
Hi...

I am glad someone raised this. I have noticed this argument rear it's head as part of other debates on the forum without it really being tackled head on.

Myself I lean on the side of get the library right and well designed, then find out what the bottleneck is. If you then need to improve performance, look at the big things first, e.g. caching, lazy loading or switching to a compiled module. All of these are easier with a clearly designed system, rather than micro-smithing the source code. It can be a very poor return for invested time and the extra code tangling will hurt development time for ever more.

If you do all of this and you find that the source code really is the source of your problems then firstly isolate with a class the bits that need optimising. Then branch the code. Leave the unoptimised version as your main development branch and perform the tuning on the other. When you want to do a release you just merge the development branch into your releases branch to get the fast version. A fixed release where nobody ever reads the source is a safe environment for optimisations.

I say "just", but of course all of this is extra management. Luckily I have never had to do this for any length of time because the problems that cause performance bottlenecks actually change quite often and the bottleneck disappears of it's own accord.

I know that 'Selkirk' holds a more performance oriented view and I would be interested to hear about the experiences that have pushed him or others in that direction.

Slightly off topic, but I find that OO is best as a long term investment. This falls into my manager's bad news (which I have shamelessly stolen from others at various times) when changing to OO...
1) Will OO make writing my program easier? No.
2) Will OO make my program run faster? No.
3) Will OO make my program shorter? No.
4) Will OO make my program cheaper? No.
The good news is that the answers are yes when you come to rewrite it!

yours, Marcus.
lastcraft is offline   Reply With Quote
Old Jul 20, 2003, 18:30   #11
KillAllDash9
killall -9 lusers
 
Join Date: Oct 2002
Location: Cincinnati, Ohio, USA
Posts: 395
Quote:
Originally Posted by been
I write interfaces too, just for having a base api reference really, but in my code I don't include them and I write
PHP Code:

class SomeClass /* implements SomeInterface */ 

The problem with this is of course, if I 'forget' to put in an overriding method in the class that implements the interface, I don't get an error, whereas if it would be extended, the die() in the interface would warn me about that...
Sure you'll get an error. PHP will complain if you try to access an undefined method.
KillAllDash9 is offline   Reply With Quote
Old Jul 20, 2003, 21:11   #12
Gybbyl
public static void brain
 
Gybbyl's Avatar
 
Join Date: Jun 2002
Location: Montana, USA
Posts: 650
Quote:
Originally Posted by lastcraft
Slightly off topic, but I find that OO is best as a long term investment. This falls into my manager's bad news (which I have shamelessly stolen from others at various times) when changing to OO...
1) Will OO make writing my program easier? No.
2) Will OO make my program run faster? No.
3) Will OO make my program shorter? No.
4) Will OO make my program cheaper? No.
The good news is that the answers are yes when you come to rewrite it!
Good point. Maybe it's like the stock market in some ways -- If you try to invest $10 and get $1,000,000 out in 10 days, you might as well kiss your *** good-bye. But, if you leave that money in there over a long period of time, you will most certainly see at least some kind of gain. Actually, I find that I can usually write my classes faster than many other people I know can write their spaghetti -- They are busy finding bugs in their 1,000 function definitions. I see the problem coming, slow down, change one line of code and watch the error disappear like a puff of idle smoke (Tao). But really -- I always try to keep my functions ~10 lines max, so I can always debug them easier.
Gybbyl is offline   Reply With Quote
Old Jul 21, 2003, 02:46   #13
HarryF
SitePoint Wizard
gold trophysilver trophy
 
Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
Just on the original point, the way I think of interfaces (vs. inheritance) is like this;

Inheritance is a vertical hierarchy

Interfaces are horizontal, (possibly) cutting across multiple inheritance hierarchies.

A theoretical example might be if I have two inheritance hierarchies like;

PHP Code:

abstract class Bird {


}

class
Pidgeon extends Bird {

}

class
Sparrow extends Bird {

}

PHP Code:

abstract class FlyingMachine {


}

class
747 extends FlyingMachine {

}

class
Apache extends FlyingMachine {

}
These two heirarchies are seperate but an interface could be applied to both;

PHP Code:

interface Flight {

    function
fly();
}
All of the subclasses of Bird and FlyingMachine could implement the Flight interface.

Using a PHP related example - Vincents Eclipse library, one way it could be modifed to use interfaces for PHP5 could be where the Iterators are concerned. The interface could be;

PHP Code:

interface Iterator

{
    function
reset();
    function
next();
    function
isValid();
    function
getCurrent();
}
With this, instead of the subclasses of Iterator being seperate from the collections they iterate over, they might be implemented directly into the collections, for example;

PHP Code:

class MyQueryResult implements Interator {


}
or

PHP Code:

class DataFileReader implements Iterator {


}
Edit:


Note that the actual implementation of the Iterator in MyQueryResult and DataFileReader would be the current QueryIterator and DataFileIterator classes respectively


Think Iterators make the about the best example of how interfaces can be used as Iterators are about unify many different types of "collection". More about Iterators here.

As to whether methods should be placed in a parent subclass or in an interface, a very rough rule of thumb might be if you require all subclasses to provide a method and in the parent the definition of that method has an empty body (ie doesn't do anything) then consider an interface.

Last edited by HarryF; Jul 21, 2003 at 05:43.
HarryF is offline   Reply With Quote
Old Jul 22, 2003, 05:25   #14
been
SitePoint Addict
 
been's Avatar
 
Join Date: May 2002
Location: Gent, Belgium
Posts: 283
Quote:
Originally Posted by been
The problem with this is of course, if I 'forget' to put in an overriding method in the class that implements the interface, I don't get an error, whereas if it would be extended, the die() in the interface would warn me about that...
Quote:
Originally Posted by KillAllDash9
Sure you'll get an error. PHP will complain if you try to access an undefined method.
You're absolutely right of course, I didn't communicate that one properly, thanks for pointing it out.
Still, using die(), you could put out a more explaining (explicative? explanatory?) error than 'call to undefined function', what, in the end, was what I was trying to say.

I hope I cleared that one up a bit, not only is my brain spinning on the OOD part, also my english seems to be causing me more trouble than I'd like to admit sometimes

lastcraft, reading over your post, I'm realizing I'm putting too much effort and time in performance at the wrong time in the development process, I should optimize later (if ever?)...
I think it's also a psychological thing: when I know I've got code that could be made faster, however small the gain (without sacrificing things like layering etc...), I have to optimize it, I can't seem to help it... This is probably just stupid pride on my behalf

HarryF, in the example code you posted, suppose you also have an interface Drive, can a 747 be implemented something like this:
PHP Code:

abstract class FlyingMachine implements Flight


class 747 extends FlyingMachine implements Drive
//or something???
?
So the 747 can taxi to the runway?

About the iterator-discussion, I'm terribly puzzled, isn't decoupling the iterator from the collections it iterates over a more preferable way?
Implementing an iterator interface in every class that could need iterating at some point seems very 'dangerous' for possible bloatness. If you need iteration, instantiate an iterator for the specific collection, if not, you don't, less dead code, no?

Just questions, my brain ain't spinning enough, and these discussions are way cheaper than the drugs I usually have to take to achieve the same result. lol.
been is offline   Reply With Quote
Old Jul 22, 2003, 06:40   #15
HarryF
SitePoint Wizard
gold trophysilver trophy
 
Join Date: Nov 2000
Location: Switzerland
Posts: 2,906
Quote:
So the 747 can taxi to the runway?
I would guess so but not 100% sure - banned myself from any more playing with PHP5 today so I can get back to real work with PHP4 and examining whether implemented interfaces are inherited is something I forgot to try.

Quote:
About the iterator-discussion, I'm terribly puzzled, isn't decoupling the iterator from the collections it iterates over a more preferable way?
That's an interesting discussion which came up (to some extent) before in this thread (read down past the QuickForm discussion).

In theory I guess the answer is yes but in practice, when you consider performance (premature - yes I know but PHP is not compiled), how you usually need to build your own numeric index to keep track of the sequence and the question "Has this now become more complicated to use than native PHP functions?" it generally ends up being better to implement the iterator API into the collection.

Probably someone can give you a better answer than that but as to bloat, the iterator I usually prefer for most things I'm doing is lightweight (it has weaknesses but in most cases it's all I need);

PHP Code:

    function fetch() {

        
$element = each($this->collection);
        if (
$element ) {
            return
$element['value'];
        } else {
            
reset($this->collection);
            return
false;
        }
    }
That allows me to use while{} to loop. It "breaks" on false values but I'm mainly using it for arrays or arrays or arrays of objects.

If you need a more robust iterator, which won't choke on false values in the collection but still relies on PHP's sequencing rather than having to track your own index, the trick is using PHP's reset() function for which you need to read the docs carefully;

Quote:
reset() rewinds array's internal pointer to the first element.

reset() returns the value of the first array element.
Of course the question of iterators becomes alot simpler with PHP5 which provides the SPL extension - have a look at the PHP example script.
HarryF is offline   Reply With Quote
Old Aug 2, 2003, 22:56   #16
Selkirk
SitePoint Guru
 
Join Date: Nov 2002
Posts: 848
Ok, I've been harping alot lately about PHP being a dynamicly typed language. A recap:

Static Typing: Check for type compatability as soon as you can (compile time).
Dynamic Typing: Check for type compatability as late as you can (runtime).

Staticly typed languages such as C# and Java REQUIRE interface declarations.

Dynamically typed languages do not.

So I will refer to this style as an informal interface:
PHP Code:

class SomeClass /* implements SomeInterface */ 

And this style as a formal interface:
PHP Code:

interface SomeInterface

{
   function
SomeFunction();
}
Which is better? Formal or Informal. Until recently, I would have said formal everytime. Lately, I lean the other way.

Lets look at how interfaces are used in those Statically typed languages that require that they be declared.

Take a look at this article Are delegates the moniker of .NET? (if you have time, use google to track down some of the discussion on this article, its better than the article.)

Notice that delegates are like interfaces except that they do not require the callee to declare an explicit interface. The caller must have access to the interface declaration in the form, but it is not necessary for the target to explicitly declare the implementation of an interface.

Anonymous classes in Java are used for the same purpose.

If interface declarations are so good, why do these staticly typed languages keep using such cumbersome methods of avoiding them?

On a different track, I talk in This post about a productivity study I did where team A was twice as productive as team B. What has only recently occurred to me was that the productive team A used a dynamicly typed language and less productive team B used a statically typed language. This study has formed the basis of many of my views of programming and this realization rocks my world.

Gyybyl talks about 'forgetting' and 'enforcing' in his post. In my experience, forgetting is not an issue and enforcing is time consuming. To use a recent popular term, 'enforcement' is not agile.

Counter intuitively, I believe that early type checking is less productive because it requires more of that useless non-value added code that I talked about in my productivity comparison.

Less code is better. (period.)

See Strong Typing versus Strong Testing for a more eloquent explaination.

Or lets put it another way. You are programming in a language that lets you do stuff like this:

PHP Code:

$x = "1" . 2; 

and where this is true

PHP Code:

(1 == "1") 

And you want to worry about interface declarations?
Selkirk is offline   Reply With Quote
Old Aug 3, 2003, 14:43   #17
lastcraft
SitePoint Victim
 
lastcraft's Avatar
 
Join Date: Apr 2003
Location: London
Posts: 2,273
Hi.

One very definite timesaver with interfaces is for library writers "enforcing" objects on their victims that their libraries can work with.

If I write a class for an object which I think works with this library it may take a little while to find out that it doesn't work, usually an unexepected error saying that a method does not exist that was expected. I look more deeply at the code and find that I have misunderstood things completely. The advantage of an interface check is that I would have found out as soon as I passed the object in. I could also have looked up the interface to see what was expected and so seen that I was on the right track or not. I use this example because I've got a real habit of doing this.

Ok, had I read the documentation or code more carefully I should have known anyway, but that little interface block works so much more decisively.

Now the rambling part...

There is an interesting point here about testing in that you only test single infinitessimal points along a (near) continuium of possibilities. This is similar to scientific non-proof. You cannot prove a theory with experiments anymore than you can prove something works with testing. Declarations, such as "interface", act as genuine laws, however. I think the weakness of declarations (I haven't used Eiffel) is that you are already thinking declaratively when coding, even when translating it into algorithms in your head, and this means that you are writing it twice in a similar way. The testing approach is weaker, but is a such a different viewpoint as to act as a very strong check.

yours, Marcus.
lastcraft is offline   Reply With Quote
Old Aug 13, 2003, 21:05   #18
Selkirk
SitePoint Guru
 
Join Date: Nov 2002
Posts: 848
I ran in to this article recently:
Python & Java: a Side-by-Side Comparison

It does a good job of comparing dynamic typing versus static typing and its effect on productivity.

Many of the points he makes for python are valid points for PHP.
Selkirk is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread | Next Thread »

Thread Tools
Display Modes

 
Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Sponsored Links
 
Forum Jump


All times are GMT -7. The time now is 01:43.


Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Copyright 1998-2009, SitePoint Pty Ltd. All Rights Reserved