Rewriting CMS - to use singletons or not

Thanks guys, this is really interesting reading for me.

I think I’m understanding interfaces a bit better now however. I was making the mistake of assuming they go at the top of a class file but if I’m understanding correctly we will (most likely) define the interface and then any classes that implement this interface are loaded afterwards and check the interface to ensure that all of the required methods/properties are available. So, for example, I could have a database interface that defines some simple methods like query(), fetchArray() etc, and then have a MySQL class that implements it, and also a PostgreSQL class that implements the same interface, ensuring that all of the methods that I’m going to need are available.

Is that at least in the ball park? :smiley:

you can make an abstract class that does the same, but classes will have to directly extend the abstract to implement the methods. i.e


abstract class MyAbstractClass{
    //cannot provide implementation in abstract method
    abstract method foo();

     // regular methods can also 
     // can be defined here
    public method bar(){
    }
}

class MyClass extends MyAbstractClass(){
    public function foo(){
    // has to be implemented, or else this class will 
    // also be declared abstract
    }
    // no need to implement bar if already defined
}

An interface on the other hand can be used by any class regardless of inheritance


interface MyInterface{
    public function foo();
    public function bar();
}

class MyClass implements MyInterface(){
    // MUST implement all interface methods 
    // i.e. foo and bar or else be declared abstract 
}

So you can see, interfaces are more strategic - they enforce a high level API across class families, abstract classes are more tactical and only work through the inheritance chain.

:smiley: LOL, Ok, I may have misread a little there. Just to be clear we are talking about two distinctly different meanings of the word interface. What I described above is an interface - the language feature which is common in OOP (and some other) languages. It has a specific syntax as shown above to define the contract which a class must implement, (otherwise known as the function and other member names that the class promises to define).

There’s also an interface - the public (or protected) members of a class which define what functions, properties, etc. available when you instantiate an object and start working with it. You can create all manner of private members for a class, and you have relatively free reign with these because only your class has access to them. If you change them later, nobody cares except your own class. The public interface of your class however, can be used by objects throughout the rest of your code, and if you were to say, change the name of your public function, you now have a lot of maintenance to do updating all those references throughout your program. That’s why people talk about “nailing down the interface” of a class as early as possible and not messing with it. Any changes you make afterward, creates a lot of maintenance work for you.

Exactly. The database example you give is an especially high level example, just as you show, the query() and fetchArray() depend on other sub functions and possibly even on other classes to help them do all the work. But the important part is that each class has functions with exactly the same names which perform exactly the same responsibilities So consider a piece of code like this.

public class ComplicatedApplicationLogicWithLotsOfDatabaseQueries
{
MySqlManager myDataManager = new MySqlManager();
.
.
.
Lots and lots of code that retrieves data and then does work on it, for example…
myDataManager.query(parameter102);
NewArray102 = myDataManager.fetchArray();
.
.
.

}

In the case you outlined, MySqlManager implements the database interface. When your boss comes and tell you that you’ve sold your souls to Microsoft and are moving to a MS SQL database, you only have to change one line, the first instantiation of the data manager object which now becomes…

 MSSqlManager myDataManager = new MSSqlManager();

What those query() and other functions do underneath in the MSSqlManager class, you neither know or care. (Unless of course you used some MySQL specific syntax in your SQL in which case you will have to adapt that to work with the new database.) Especially if there are two hundred classes that use the MySqlManager class, you have a lot of work, but you are updating the one line of code two hundred times. Consider if each database manager were NOT written to a specific interface. You would then be tasked with searching through two hundred classes LINE BY LINE and rewriting every reference to the data manager classes so that they performed the same old work in the new system.

That’s so insane that you would never do that. You would write an adapter class over the top of the new MSSqlManager so that you don’t have to change any of those calls. The adapter would hide the details necessary to make the new class do the same job, e.g.

public class MSSqlAdapter
{
query()
{
…Code to tell the new MSSqlManager what it should do when the query function is called by those 200 classes…
}

 fetchArray()
 {
      ...Code to tell the new MSSqlManager what it should do when  the fetchArray function is called by those 200 classes...
 }

}

once you had the adapter in place, you have a good alternative to using the MSSqlManager. You now just update the two hundred references to MySqlManager with…

 MSSqlAdapter myDataManager = new MSSqlAdapter();

In other words, a consistent public interface (ie the group of public functions for your class) is so important, that if you don’t have an interface (the programming language construct that enforces this consistency), you reverse engineer that consistency with an adapter, rather than trying to rewrite your entire program.

I think were talking about different perspectives of the same thing. The principle you’re referring to “Information Hiding” is absolutely kick ass. And your absolutely right when you talk about what an interface “is”.

What I’m talking about is “why”. They’re not fancy or good for impressing a date; they don’t taste sweet, and they don’t do windows. So why? Because you can write more maintainable code. From the perspective of the class which implements the interface, you’re right; every class has to provide the implementation for each function. If you have 15 classes which all implement IPayable, you have 15 classes and each one has it’s own pay() function. That’s unavoidable because each one has it’s own unique implementation to actually make that payment. If they don’t you should encapsulate that code in a new function, which each of the identical pay() functions should call instead of implementing the code themselves.

HOWEVER, the code that USES those classes can be much more DRY with interfaces. Even if your 15 classes all have a pay() function, without an interface (or abstract class), you wind up with this…

public Customer payCustomer(Customer customer1, float amtToPay)…

public Client payClient(Client client1, float amtToPay)…

public Employee payEmployee(Employee employee1, float amtToPay)…

public Walrus payWalrus(Walrus walrus1, float amtToPay)…

etc.

The next time your accounting department switches from Charge.com to paypal, you now have to rewrite 15 different functions. Yuck!

As you stated, the interface allows you to hide implementation, this is key. If I had used an interface instead, IPayable, I can now write ONE function that does the job of all the others…

public IPayable makePayment(IPayable receiverOfPayment, float amtToPay)
{
…whatever necessary code, but most importantly including…
receiverOfPayment.pay();
}

This function can be used by all 15 classes, so instead of 15 functions, we now only have one to maintain. (If you’ve ever studied generics, they’re basically an amped up version of this technique.)

When the pay() function of each class gets called, what happens? Who cares? makePayment() doesn’t even know what happens; it’s delegated that job to the class that gets passed to it.

What if the pay functions do completely different things? Fantastic! So maybe the pay function of the employee class has the payment included in their next paycheck, while clients get a credit to their account, and walruses get paid in fish. Our function neither knows nor cares. That’s how powerful the idea of interfaces are, and also how they allow you to limit redundant (WET) code.

:eek::cool::rofl::smiley:

It’s worth taking a look at attempts to enable classical OOP paradigms in Javascript- take Pro Javascript Design Patterns for example:

The authors attempts to patch in features like interfaces give you some perspective on what those features really are (although PHP isn’t a pure OOP language - but since it walks like a duck…). Doug Crockford has some interesting thoughts on the subject of forcing classical OOP forms into JS.

Back to PHP : while you can enforce the name of a method with an interface (or use it for type hinting), you can’t enforce a return argument type - so it doesn’t take much to stray from the path. Interfaces are great, but IMHO it’s a planning/architecture tool more than anything. They just help keep the API under control. I may be wrong…