Interfaces - Why bother?
I've been watching people talk back and forth about including interfaces into the ColdFusion language or not and I've been wondering why bother. From what I know, interfaces (the Java keyword rather than the general term) are used to define what is basically a "rules class". This rules class contains the names of methods and any arguments that they may need. Any class that uses this rules class (implements it), must have a method within it of the same name (and arguments) or else an error will be thrown.
Basically an interface is a contract between a class and a rules class that says that the class has to have all of the rules' methods to be legal.
In ColdFusion terms, this means that there is a 'rules' component (an interface component) that only contains cffunction tags. The cffunction tags can have cfargument tags, but these are not required. Nothing else can be in this component other than these functions.
Some other component will include this interface component and basically have to create a function for each of the functions in the interface component. How this will be done is all theory to the community at the moment, but the theory will follow the steps above.
Now if my definition is correct, then this sounds more like something that would be useful at development time to make sure that a component being written follows certain rules. If it's going to be used at runtime, then it 'feels' like it would just be more overhead and unneeded validation. Am I wrong? Is there something I'm missing here? What are the issues and why should I (or anyone else) care?


Because CF isn't compiled, you don't get the kinds of benefits from interfaces that you do in Java in your IDE. I don't think it would do any harm to support interfaces and I'm sure people writing larger projects with more developers would appreciate them, but I could take or leave them. I don't think they are an essential language feature but they would help larger developments.
Basically the interface is a specification that says "you HAVE to have AT MINIMUM method x with arguments y and z and it MUST have a returntype of a" so you're right on except for the terminology. It's a specification, which is the same thing as a rule but it's more in line with the way these things are talked about in general.
As far as runtime vs compile-time issues... yeah, I can see eventually having a cf administrator switch that says "turn off interface, type and returntype validation" in the same way you can turn trusted cache on and off. THAT would be a killer cool way to make sure we get the use of the tools as we develop (which is where they are really very useful) without the costs and performance penalties in production.
The page never refreshed, the browser never updated... it looked like the page was hanging but the comment posted every time I clicked Post...
*sigh*
OK, so we can blame Ray... I'm off to port BlogCFC to AJAX. hehehehehe
Because Java is compiled, you will find out immediately if you try to create a class that implements an interface and you fail to live up to the contract that the interface lays out. This is thanks to Java's strong typing: the compiler knows the types of all method arguments and return types and will complain loudly if you violate the interface's specification.
Unfortunately, it seems like many CF'ers have a dream that this power can be ours if we bring interfaces to CF. I am sad to report that this is not the case because CF is not strongly typed and not compiled until runtime.
Let me paint two scenarios:
A) You don't have interfaces. You create a CFC called Car. Since car is a drivable thing, you might expect and demand that all of your drivable things have a method called drive(). If you pass one of your drivable things (like Car or Boat) to some other object, you'd better have a drive() method implemented. Because if you don't, and your using object tries to call drive(), you'll get a method not found exception at runtime.
B) You have interfaces. You create a CFC called Car that implements an interface called Drivable. Your Drivable interface demands that all implementing classes have a method called drive(). The problem is that if you create a Car that implements Drivable, and you don't supply a drive() method and you save the CFC, nothing happens. You won't find out anything is wrong until you pass one of your drivable things to some other object, and it tries to call drive() on it. In that case, you'll get a "cfc does not implement interface Drivable" exception at runtime.
Let that sink in for a moment. Notice that, aside from the extra work and overhead that CF will have to do to verify the interface contract, the only difference between the two scenarios is the text of the error message you get at runtime. One says "method not found", the other says "does not implement interface".
In my opinion, a different runtime error message is not a very compelling benefit in exchange for many hours of development time on the part of the CF engineering team. Which is why I think the CF team would be much better served working on numerous other enhancements. The cost seems quite high and the benefit seems very small. My opinion of course, and I will hedge by saying *if* interfaces were added despite my reservations, I would probably use them. I just don't think it's a very beneficial use of the CF team's development time and budget.
1) Here is a link to a post my partner wrote a while back on the definition of an interface that you might appreciate.
2) CF *IS* compiled; It turns into Java (or .Net) and then Java bytecode (or .Net binary) and at the same time we have a nice layer above that providing many dynamic functionalities. I see the future of ColdFusion being able to benefit very much from this scenario. For one (in response to Brian's scenario), who's to say that we can't compile a file when you save it in your IDE of choice? The ability to compile CF from the command line is already there just waiting to be used.
I don't know if you guys have played with Actionscript 3 yet, but I am consistently amazed at how well it supports both static and dynamic typing / classes. It is so cool to be able to choose what you want validated at compile time and what you don't. The beauty of this is Actionscript 3 has catered to all needs and done it seamlessly. True support for the OO constructs many developers expect as well as the ability to "lighten up" when necessary. I think ColdFusion could do this very same thing.
Sorry if my thoughts are a little shattered right now, its getting a little late hehe :-)
Mike.
Sorry,
Mike.
http://www.newatlanta.com/c/products/bluedragon-be...
- Java or ActionScript2/3 have Interfaces for multiple Inheritance.
- Because Interfaces don“t include their own implementation Java additionally supports Inner Classes for real multiple implementation inheritance. In C++ you can inherit from multiple classes with different implementations which can be awkward.
- Interfaces brings polymorphism to its full power because it allows to use multiple different types in one level of the inheritance hierarchy.
Because ColdFusion like JavaScript or ActionScript 1/2 is far less strict than Java there is no real need for interfaces in CF which the author of this blog wants to say.
As for BlueDragon, I actually think the way that they are implimenting interfaces and abstract methods/classes is very clean. And I love the concept of abstract methods and classes. I have an example of the whole thing in the article. I'll have to get the article up online as the first example from the issue.
In your case (B), at least in the BlueDragon 7.0 implementation, you'll get an error as soon as you create an instance--via CFOBJECT or CreateObject--of a class that implements Drivable but doesn't implement to drive() method. This is much better than case (A), here's why:
In case (A), if you don't have any code that actually tries to invoke the drive() method, then you'll never get an error. That is, your code may run fine for a while, but as soon as you add code to invoke the drive() method it'll break (or maybe your testcases weren't thorough enough and you missed testing the path that invokes the drive() method, so everything works for a while, then--poof!--suddenly it's broken when you execute a path in your code that your testcases missed).
In case (B), again in the BD 7.0 implementation, you're guaranteed that all CFCs that implement Drivable will have a drive() method as soon as you create an instance of a Drivable CFC, regardless of whether you actually run any code that invokes the drive() method. This is why Interfaces are better than Duck Typing--you don't have to rely on perfect testcase coverage to make sure your code is going to work properly. I'm not arguing against thorough testing, but pointing out that there's a class of errors that Interfaces can catch before you even start testing.
We're doing performance testing on BD 7.0 now and will answer that question before the final release. Our goal is that any performance hit should be small enough to not be relevant (not something most developers will have to worry about).
As to the argument raised that CF *is* compiled, yes, yes, we all know that. But there's no static typing and that's what we'd be looking for for interfaces to be valuable. But it seems that the decision has been made, so there's not a lot of point in debating whether they should be included.
I know at CFObjective they said Interfaces were being considered. This was not covered in the CFUNITED keynote (that I know of).
Did I miss an announcement saying that they would (or would not) be included?
( Michael I'm also seeing the same problem that Sean and others have mentioned when submitting comments )