An Architect's View

CFML, Clojure, Software Design, Frameworks and more...

An Architect's View

Interfaces in ColdFusion

January 8, 2006 ·

I've changed my mind. I no longer think ColdFusion needs interfaces. I've been advocating this feature addition for a few years but no more. Why the change of heart? Well, with all the OO ColdFusion I've written, I must admit that I haven't really missed interfaces. At first I did, but then I started to use type="any" or type="WEB-INF.cftags.component" and that is actually more powerful. How can a "weaker" type be more powerful? Simply because you can pass any object that is able to respond to the necessary methods - those objects don't need to be part of a rigid single-inheritance tree! I'm not the only person who thinks this way... Michael Smith just interviewed Hal Helms about his talk at CFUNITED 2006 and here's a little clip from that:
Michael Smith: So, you're going to argue that Adobe should add interfaces to ColdFusion? Hal Helms: No! What good would that do us developers in the trenches who face these problems right now? Besides, that's exactly the wrong solution. The reason that C# and Java need interfaces is that they are statically typed -- that is, data types get determined prior to run time. But ColdFusion doesn't suffer from this restriction: it's dynamically typed. What we need is to embrace the fact that ColdFusion *is* dynamically typed. And we haven't even started to talk about mixins! There are all kinds of new possibilities!
Hal's talk is about "duck typing" which is only really possible in languages that have dynamic type systems (where a variable's type is determined at runtime based on its contents). Smalltalk programmers are used to this, as are Ruby programmers and others. With all the enthusiasm around Ruby these days, ColdFusion programmers might do well to embrace some of Ruby's strengths which are also ColdFusion's strengths - including dynamic typing.

Tags: coldfusion · programming

70 responses

  • 1 barry.b // Jan 8, 2006 at 5:52 PM

    not disagreeing with you but I gotta ask:

    it doesn't worry you that you won't know you've picked the wrong CFC (or even the wrong method to call in that CFC) until runtime?

    I take your (previous) point that CF doesn't really have a "compile-time" to check types and signatures but I'm knee-deep in a .NET app at the moment where interfaces are proving to be a real help (I know, comparing apples to oranges...)

    just curious that's all...
  • 2 Bruce // Jan 8, 2006 at 5:53 PM

    Using type="any" may be convenient and an easy work-around to the lack of interfaces in ColdFusion, but doesn't this convenience increase the possibility that your program may fail?

    What guarantee do you have that the object passed in to your method implements the behaviors you're executing on that object inside your method?

    Also, if I want to use your CFC, I'd have to thoroughly read through your method's code to understand exactly what type of object I could pass to your method.

    One of the great advantages of OO languages like Java is classes a have an easily understood public "interface (understanding)" that is enforced at compile time. This enforcement is partly based on static typing.

    Interfaces enable programmers to lessen coupling between classes, while also ensuring runtime success. If my class implements interface Foo then my class can be used anywhere type Foo is required. Interfaces are the agreement between my class and your class that guarantee we can work together without either of our classes really knowing what's going on inside the other.

    I personally think static typing and interfaces lead to better written code, improved integration among classes, easier code re-use, and simpler application expansion.

    If we are going use object oriented patterns in our ColdFusion application designs, then interfaces are just one of several improvements to the ColdFusion language that will help us.

    For example, if ColdFusion had interfaces my Service CFCs could include an instance of a a CFC that implements the DAO interface instead of coding my Service CFC to contain a concrete DAO object.

    Most patterns recommend coding to an interface rather than a concrete type. Interfaces make expansion and modification much simpler.
  • 3 Cliff Meyers // Jan 8, 2006 at 6:08 PM

    One of the reasons I like interfaces is that they're a very standardized way to document the functionality that one class needs to implement or that another class expects. Without that construct you're left to saying something like, "your class must implement the crawl(), walk() and run() methods in order to be work with MyClass.doSomething()". Now that's really all an interface is doing anyhow. However, think about what happens when your class needs to implement a handful of these "interfaces"; there is no easy way to look at your class and know that it has any relationship to the methods of these other classes that you're coding against. Instead of clearly seeing that your class implements (for example) List, Serializable and MyInterface1, you'll just see a mishmash of methods that might have some comments that say "these four methods are required by SomeOtherClass.run()" and then "these two methods are required by YetAnotherClass.jump()". Instead of abstracting the relationship between two classes into a well-defined construct known as an Interface, the only way to illustrate that relationship is to add comments to your code referring to that specific class's methods when in fact it might actually work with a bunch of other class's methods as well. That seems like it could get very confusing in the long run.

    I do agree 100% that in a dynamically-typed language like CF that you can't be very specific with interfaces and they're not as powerful, though I do think they serve an important organizational purpose that can help clear up the murkiness of a large/complex class hierarchy.
  • 4 Keith Gaughan // Jan 8, 2006 at 6:22 PM

    Bruce, that's a small 'i' interface, not a big 'i' one. With dynamically-typed languages, the interface that you adhere to enforced by custom rather than by a compiler. I've a feeling that CF just isn't the right language for you.
  • 5 Seth Petry-Johnson // Jan 8, 2006 at 9:08 PM

    Bruce: I think you might have missed the point. Sean isn't promoting "coding to a concrete type", (I think) he's saying that we should "code to the contract" of a particular type. In other words, if I have a method foo() that accepts an object and then calls object.bar(), then dynamic typing allows me to pass ANY object to foo as long as it implements bar(). This is the same thing as an interface in Java but is checked at runtime.

    > What guarantee do you have that the object
    > passed in to your method implements the
    > behaviors you're executing on that object
    > inside your method?

    What guarantee do you have about ANY CFC method parameter? Without a compilation phase and static typing the only thing that is guaranteed is that CF will throw an exception if you pass in an invalid parameter. Either you specify a type and provice an instance of that type, or you specify type "any" and provide an object that implements the required methods. Either way, runtime exceptions are your only way to catch bad data.

    Cliff: I agree with your points on interfaces serving an important organizational purpose. I really do enjoy dynamicaly typed languages like CF and Ruby but I always worry about losing track of which objects depend on which methods of other objects. Still, if I had to choose I'd choose the additional flexibility.
  • 6 Sean Corfield // Jan 8, 2006 at 10:04 PM

    Barry, you won't know you've picked the wrong CFC until runtime regardless - ColdFusion only checks types at runtime!! Interfaces would not change that. The *only* difference would be in the text of the error message: today it says something like "no such method - foo()" whereas with interfaces it might say "argument x does not implement interface y" (and might not tell you that x is missing foo() anyway!).

    Bruce, ColdFusion is not Java. There is no compile-time type-checking. At runtime, ColdFusion throws exceptions when things don't match. Interfaces would not change that. Not all OO languages have interfaces as a language construct and yet they are still good OO languages that support those design patterns.

    Cliff, I agree that without an interface you still have to document the requirements. However, an interface means you have to read the source code anyway unless there is good documentation to say not only what methods you must implement but also what pre-conditions, invariants and post-conditions are assumed - an interface never provides that information so documentation is necessary anyway!

    Keith, agree. Seth, agree too.
  • 7 Joe Rinehart // Jan 9, 2006 at 6:11 AM

    Welcome to the dark side :)!

    I converted from pro-interface to "only-on-paper" interface last spring, and I'm still feeling pretty much the same. After talking with some others, I *do* think it could be handy to "mark" CFCs as being of a particular interface, but that the checking should be very little if existant at all. It seems like nice compromise between strong, compile time type checking and the "You mean I have to read all the code of the DuckProcessor to figure out how a 'Duck' should work?" trap that I think pure, "Ask for forgiveness later" Duck-typing could lead to, especially in cases where documentation is slim.
  • 8 Johnathan Gifford // Jan 9, 2006 at 9:32 AM

    Hmm... now I understand why the 'hint' attribute exists for cfargument. By using 'any' allows you to do interfaces without forcing type. Yeah, it sucks that you can't strong type it, but you know what, tell me if it allows any or just a CFC. With the hint attribute , tell me what methods are needed. Then wow, I can accomplish interfaces.

    We can still notate the Interfaces in the domain model with our class diagrams. But in development, we know we just need provide those methods. Even in .NET and Java, you still have code the method in the class. The Interface only acts a traffic cop and a template for required methods. ColdFusion doesn't need a traffic cop, because strong typing is NOT required. Besides, don't we 'all' test out code in the run-time before deploying it production?

    I've taken Hal's class. We banged our heads for most of one day thinking of ways around it. In the end, I totally missed the point of interfaces because I was so blinded by trying to solve the problem that I forgot what the problem was. Afterwards, I asked myself, what's the point of the Interface and started looking at Java and .NET for why they exist and what you still have to do to accomplish it. It was a no brainer, the strong typing of the language has the need for Interfaces. Interfaces provide sub types for an object strongly typed languages. Dynamically typed languages can let sub types slide as long as the method to be called exists.

    What might be a useful function from the ColdFusion team, is the ability to test an object for the existance of method before executing the method.
  • 9 Jared Rypka-Hauer // Jan 9, 2006 at 11:34 AM

    Since interfaces provide no functionality but they do expect some functionality to be coded into the class, they're basically a way to enforce a particular set of methods within a class. That said, the word "rigid" doesn't really fit in the CF, Ruby, SmallTalk or PHP vocabulary.

    All this talk of strong typing in CF is getting silly... because no matter how hard you work to implement it in CF you're not going to get the error until runtime. End of Story. In other words, whether you get a runtime error about an invalid type or unimplemented interface or you get a runtime error about a missing method (which is really more helpful anyway) or an argument type mismatch, you're still going to get runtime messages.

    Johnathan, you can already use cfif structKeyExists(Object,"myMethod") to determine if a method exists, and can therefore check for the correct "interface" before calling it. In fact this is being used extensively in MG and ARF to call setters for event variables only if the setter exists:

    <cfset eventData = arguments.event.getAllValues()>
    <cfloop collection="eventData" item="item">
    <cfif structKeyExists(myBean,"set" & item)>
    <cfinvoke component="#myBean#" method="set#item#">
    <cfinvokeargument name="#item#" value="#eventData[item]#" />
    </cfinvoke>
    </cfif>
    </cfloop>

    So you can already handle interface checking and you can throw custom errors if the interface is missing methods. You can rely on CF's more descriptive missing method exception instead of "doesn't implement x" ala Java, you can dumb your types down, but you can still use inheritance to make sure that an object is derived from a particular inheritance tree... without recreating any of the platform.

    Let's not keep trying to reinvent the wheel... while CF's underpinnings are in J2EE, CF itself is NOT J2EE. Accepting that is the first step toward understanding just how powerful CF can be when you use it as CF instead of trying to wrap it in Java/C++/.NET concepts.

    Aside from that, all the arguments I've seen for strong typing and interfaces in CF have been based on things that are entirely under the developer's control. How do you know your object is the right object if it can't implement interfaces? Well, you write the application so that it sends the right objects... sometimes it strikes me as shortsightedness or even laziness that drives the call for this.

    Anyway... just my $.02.

    Laterz!
  • 10 mikey // Jan 9, 2006 at 11:36 AM

    ColdFusion is not Java? The what the hell-eck is Ben Forta talking about?

    Defending ColdFusion Against Java:
    "Great, so, ColdFusion simplifies Java development, and ColdFusion applications are no less Java than applications written in low-level Java directly. But simplicity and abstractions require sacrificing power, right? Wrong! ColdFusion applications can (and should) leverage Java; Java APIs, Java classes, Java beans, JSP tags, you name it, ColdFusion can leverage it because ColdFusion itself is Java. It's that simple."
  • 11 Jared Rypka-Hauer // Jan 9, 2006 at 11:42 AM

    ColdFusion compiles to Java. ColdFusion is written as a J2EE application. When you sit down to write a program in ColdFusion, you're not typing Java into the IDE... you're typing ColdFusion.

    ColdFusion converts CF code into Java bytecode, and it runs on the server as Java... but the rules of the language, the way the objects work, and how it does what you tell it to do is not Java. Java is the end result, but the path to getting there isn't the same. It's a lot closer to JSP, but even JSP requires a String to send data to the output buffer...

    Mostly, JSP/Java is a waste of time when creating web applications because HTTP is stateless and typeless. CF is a bridge between the stateful and strongly typed world of Java and the stateless/typeless world of HTTP (at least as far as developing browser-based websites is concerned). Add to that the fact that it works with FTP, SMTP, POP, webservices, LDAP, RDBMSs of many kinds, text, numbers, Java, ad infinitum... and you have one very powerful platform that can get a great deal of work done very, very fast.
  • 12 Sean Corfield // Jan 9, 2006 at 11:43 AM

    Mikey, ColdFusion is a great way to write apps that are essentially Java apps - but has the benefits that the language itself has expressive power (through things like dynamic typing).

    It's like Jython - that's the Python language (which is not Java) but you're using it to build Java apps in effect.

    If folks keep trying to add Java-like features to ColdFusion, they'll end up with Java.

    Make sense?
  • 13 barry.b // Jan 9, 2006 at 2:52 PM

    >> Mostly, JSP/Java is a waste of time when creating web applications because HTTP is stateless and typeless.

    but on simplistic level, CF isn't fully typeless either - we still have dates, numbers, cfc references....(semi-typed?)

    with all this talk about "Mystic" + the next release of CF, at what point does CF start to run out of steam/get left behind?

    back in 1999, Microsoft went far beyond their vbscript classes (similar to CFC's - continers for functions with public + private structs) and an interpreted language (ASP classic) which eventually gave birth to ASP.NET. Sure they had other reasons to do so (like giving their old VB programmers a new life)...but they saw a need to do so.

    So what's left for improvements for CFC's since there'll never be strong typing of the language and no interfaces? Where to from here?

    or is that it? we've got all we'll ever have?



  • 14 Sean Corfield // Jan 9, 2006 at 3:06 PM

    Barry, you are so totally missing the point dude! Strong typing is not always a good thing. Many languages - especially newer languages that are on the rise such as Ruby - do not rely on strong typing and are more powerful because of it.

    What "improvements" to CFCs do you actually need in order to get your job done?

    ColdFusion's power comes from its ability to quickly and easily bridge a wide variety of technologies and problems and new features have almost always focused on solving problems that developers face - at a conceptual level rather than at a language syntax level: easy-to-use database code, protocol support (LDAP, FTP, SMTP/POP etc), web services, PDF generation, report building, complex form management, asynchronous data/process integration etc etc. I expect ColdFusion to continue evolving, providing more high-level solutions to problems, allowing developers to build better systems faster.
  • 15 Jared Rypka-Hauer // Jan 9, 2006 at 3:07 PM

    Bogus, barry... CF treats all those as strings and analyzes their contents for patterns. That's analyzing the contents of the variable, not the nature of the variable itself. Even CFCs, when you get right down to it, are all part of the inheritance tree of web-inf.cftags.component, so there's not really any TYPE involved, it's all dependent on the content of the variable.

    Your final point, however, is where you prove you've actually MISSED the point entirely. Strong typing in CFCs, and interfaces, are NOT IMPROVEMENTS. They're inhibitors... they're why I don't like writing in Java, because they shackle my creativity and create excess work. You say "why can't I have strong types??" and I say "Why should I have to cast anything manually??" Seriously, other than to satisfy the minds of those who can't handle a relaxed language, there's absolutely no reason to provide them that I can see.
  • 16 barry.b // Jan 9, 2006 at 3:20 PM

    Jared, I don't disagree with you. I'm actually working on an asp.net app ATM (with all it's type conversion headaches and overblown constructs) and it's shitting me to tears (and making me miss CF).

    I *do* see the point: it's either have an OTT language where you can nit-pick to the n'th degree or have a RAD language that bypasses all that for the sake of simplicity and effectiveness: "if you want all that stuff, use Java", etc.

    but what you're also saying is that CFC's are at the end of their development cycle**, not the start. There's no room for anything else and there never will be.

    yes?


    ** with the exception of a few "tweeks" like serialisation, perhaps?

  • 17 Sean Corfield // Jan 9, 2006 at 3:38 PM

    Barry, again, what improvements to CFCs do you actually need to get your job done?

    Over the last few releases and updates, we've seen the addition of all sorts of web services control added to CFCs, Application.cfc, event gateways (based on CFCs). All sorts of things keep getting added.

    To me, it's as if you're complaining that arrays and structs are at the end of their development cycle without offering suggestions of improvements - and justification for those improvements.

    CFCs do a great job. I don't find there are any major pieces of functionality missing - in real world situations - although there are a number of small "tweaks" I'd like to see that might just make my life as a developer more convenient. I used to think interfaces were the big, missing piece but I no longer think that. If CFCs are stable and do their job, then the end of their development cycle should be exactly where they are, yes?
  • 18 Jared Rypka-Hauer // Jan 9, 2006 at 3:38 PM

    Barry... I'm glad we don't disagree! :D

    But, I don't think I understand where you're going with the whole concept of CFCs being at the end of their development cycle. Is there a problem with them being "finished"? If the intention was to create an OO construct, why does that have to change, and why do they need to fall in line with the Java view of OOP? That's where we're having a disconnect. I know you want NULL, interfaces and strong typing, but they're all contrary to the nature of the platform.

    It's time for people to drop the expectation that CF will conform to the C-based languages, or Java, and start looking at CF as something new, something unique, and something empowering. ColdFusion gives the common man cheap access to incredible amounts of power... ooh! I like that! But it's never going to have null because it can't. It's never going to be strongly typed because it deals with value, not nature, anyway. And it's never going to interfaces because the amount of benefit is so small relative to the amount of work it would take to make it work that it's not worthwhile.

    Then again, watch the CF team prove me wrong. What interfaces would give is a smile, and a degree of comfort, to Java developers. That's about it. Nobody else really cares about Java-style interfaces, especially in the context of a late-binding language with no real concept of types.

    So... you seem to be lamenting the fact that CFCs are "at the end of their development cycle", so could you clarify why? I don't really see the problem, because if the construct has been fitted to the platform, they SHOULD be done and adding a lot of extra stuff would be wasteful. I'd rather see the CF team focus on enhancements to UI generation tools like XHTML compliance in htmlParagraphFormat() than see them spend a lot of extra time on these other issues.

    Can you clarify?
  • 19 Aaron Foote // Jan 9, 2006 at 4:58 PM

    The debate continues. Interfaces, Method Overloading, NULL values - What next?

    We keep hearing that ColdFusion doesnt need these features and benefits by not having them - Also this "weakness" is in fact a strength, either now or in future releases

    The easiest way to settle this debate is by coming up with new features ColdFusion *could* have that are enabled by this lack of traditional OO functionality

    I'll start the ball rolling

    Runtime generated CFC's - I currently have build tools that spit out CFC files, would be cool if this generation of CFC's could be done dynamically at Runtime.

    Dynamic modification of Objects/CFC's - Add/Remove methods and attributes dynamically at Runtime, a slight extention of this would be the ability to merge two object together to form one object

    I have no idea how I would use these but they would be powerful features.

    I'd be curious to see a ColdFusion version of Aspect Oriented Programming - I know little about AOP except that it's a buzz word like "Ruby-on-rail" and often you need a modified Java Runtime or have to endure the powerful yet frighting nightmare that is JBoss

    These are some of my ideas, I'm sure the readers out there can come up with more

  • 20 Jared Rypka-Hauer // Jan 9, 2006 at 5:06 PM

    I'd like to see the ability to go from code to instance programmatically, but it's of such limited use (unless you need it) that I'm not sure it'd ever make it into a release. :) I should clarify that... I'd like to generate the code (say from metadata about a table), then be able to execute the code that I just generated to create a running instance, without ever having to write the code to disk.

    That could be very handy.

    But... as far as dynamically modifying the methods and properties of a CFC, that's already there. CF treats methods as struct keys, so you can create a UDF in a page, create an instance of web-inf.cftags.component, then do cfset Object.myMethod = myUdf and it works just fine. Using that technique you can create an adapter method that gets you access to the variables scope of a CFC. Handy but dangerous.

    It's what we've been calling "Behavior Injection" or "Method Injection" and it's the foundation for things like ARF.

    And while I haven't used it, ColdSpring allows AOP already using CF so you can do things like trap calls to CFCs, modify their behaviour, then let the call finish executing.

    While I haven't needed it, I'm sure many, many people would be happy to see CFCs able to be replicated across members of a cluster. I think that async calls from within CF would also be handy (i.e. cfthread or something...) but I'm drawing a blank when it comes to other advanced features that would be nice.

    Anyway... it's a good question.

    Barry... what WOULD you like to see done that isn't there yet?
  • 21 Nando // Jan 9, 2006 at 6:25 PM

    Improvements? Since it hasn't been mentioned here, i think a new type, type="component" would be a useful improvement.

    I also appreciate this discussion very much. There's seems to be a general perception out there that if ColdFusion doesn't fully implement all OO constructs, it's not the real thing. I'm glad to see that questioned in an intelligent, down to earth way.
  • 22 Bruce // Jan 9, 2006 at 6:47 PM

    What about adding a dedicated constructor method to CFCs so that we don't have to have an init method or other work arounds to simulate a constructor.
  • 23 Seth Petry-Johnson // Jan 9, 2006 at 7:00 PM

    Nando: what do you mean by a new "component" type? How would this be different than using "WEB-INF.cftags.components" as the type?

    Also, we seem to have veered off-topic a bit but since there's such a good discussion going I thought I'd toss in my thoughts for improving CFCs sans interfaces:

    1) I second Bruce's thoughts on a dedicated constructor method. The init() convention works well but I would prefer an official language feature if possible.

    2) Automatic var scoping of local function variables. Despite tons of blog posts and documentation entries about this issue people are STILL not doing this and being bitten by it. I'd much the default behaviour be local variables and have to manually specify when I want a global rather than the reverse.

  • 24 Chris Scott // Jan 9, 2006 at 7:36 PM

    Bingo! Constructors. Good call there Bruce. This has been a really great discussion, I haven't had to much to add because it's all being said already. I'm still for interfaces and abstract classes for object composition, but I agree with many points being said here. But as far as improvements to cfcs, constructors would be nice. Also I'm going to tweak the edit that automatic var scoping entry. How about just not having to var at the top of a method? Every put a cfdump above some var declarations and get pissed? I have!
  • 25 Nando // Jan 9, 2006 at 7:45 PM

    Seth,

    It would be functional the same as specifying "WEB-INF.cftags.components" - just formalized.

    I was also going to suggest your #2, automatic var scoping of local function variables. But i chickened out at the last minute. ;) I don't know the language inside and out so thoroughly that i can think thru all the consequences properly.

    Nevertheless, from my little corner I think it makes MUCH more sense to have to manually specify variables-scoped variables. This way, it's immediately obvious if you forget (whoops, that variable isn't defined ... why not?), instead of the consequences being hidden. In my mind, it seems to be a mistake that it was done that way and should be fixed.

    In addition to developers not being aware of this hidden issue, it's also hard to remember each and every time.

    If backwards compatibility is a big concern of the CF product team, and maybe it should be, then i can envision a setting that would allow a developer to switch the default behavior from "auto var scoping" back to "manual var scoping", if they want to, rather than clean up their code.

    Small thing, but it would make a big difference on the ground.
  • 26 Cliff Meyers // Jan 9, 2006 at 8:59 PM

    ""
    Strong typing in CFCs, and interfaces, are NOT IMPROVEMENTS. They're inhibitors... they're why I don't like writing in Java, because they shackle my creativity and create excess work.
    ""

    Strong typing and interfaces need not necessarily go together. You can still have interfaces in a dynamic, weakly-typed language such as CF to provide a blueprint or contract for implementing functionality. Think of it this way... interfaces allow one class to "inherit" from multiple "abstract classes" in a language that doesn't allow traditional multiple inheritance... although you only get methods, not properties or constants.

    The arguments against strong typing just don't apply to interfaces. Asking for strong typing in CF is silly because it'd break backwards compatibility with everyone's CF code base. On the other hand, it looks as though interfaces could easily be added to the language without impacting anyone previously written code. Interfaces wouldn't inhibit you in any way... if you don't like them or don't see their value, just don't use them. Simple problem, simple solution!
  • 27 Jason Daiger // Jan 10, 2006 at 4:29 AM

    Aside from this being one of the best discussions I've read I'm just baffled about the some of the black and white nature of many of the comments as (to me) it seems silly. One of the great things about CF is its flexibility. If you want implement 'interfaces' in CF and code to that contract go for it. If you want to use Duck Typing go for it. If you want to specify your type parameters and returntypes go for it. If you don't want to, ok have at it. If the case warrants typeless parameters don't type them. If you feel the case warrants them, like a particular web service, use them. In the end those decisions are for the organization creating the project, the skill set of the developers and what makes the most sense for that organization. Using CF you know its not statically typed, you know interfaces are mearly a contract and you know type checking and interface 'verifying' are done at runtime so plan you must accordingly. But all this has to be ok w/ you or you wouldn't be using CF in the 1st place since that's the nature of CF.

    With that said, the portions of discussion about CFC future features are spot on. I 2nd, 3rd, 4th, whatever the call for a true constructor and cleaning up the variable scoping. The 'crossing of variable scope' or searching various scopes as CF does has always bothered me as it tends to inject more errors than fix them. Personally, I would like to see method overloading allowed as well.
  • 28 Seth Petry-Johnson // Jan 10, 2006 at 5:10 AM

    Jason: I've found myself wanting method overloading as well, but I don't even know if this is possible (or at least feasible) given CF's dynamic typing.

    Think about it this way: lets say I want two versions of foo(), one that accepts an integer and a string and one that accepts two strings. What happens if I do this:

    foo("3", "test")

    Which version is called? If CF decides a variable's type according to its value it would consider the first argument numeric, but what if I actually *wanted* to pass the string representation of 3?

    Without strong typing I don't see how method overloading could be implemented properly.
  • 29 Dave Ross // Jan 10, 2006 at 6:19 AM

    I think that whether or not you want interfaces has a lot to do with the size and complexity of the applications you build (and this applies to Java too Jared... trust me, interfaces are not inhibiting in a 10+ million LOC Java project).

    If the consensus is "use duck-typing", then CF needs to provide another way for me to specify the contract inferred by that argument or returntype. It needs to be part of the language, not on some sheet of paper. Those that work in a distributed enviroment with team members that come and go know exactly why interfaces/contract programming are generally a good thing. Those that work on small projects in a silo probably do not. I do both, and for the small projects, there's no need for anything like an interface (consider the concrete class the contract and you're done). For large projects, being able to implement an interface and KNOW that I didn't break any of the thousand or so dependencies is quite nice.
  • 30 Jason Daiger // Jan 10, 2006 at 6:27 AM

    I've thought about the same problem and believe Sean actually commented on this issue recently in a CFCDev thread. However, there is already a level of type checking going on is various tags and CF gives the appearance of type checking so why not actually do it. If all complex objects inherited from a single object (in reality they do I just do not think its explicitly obvious at this time) then you could use any, complex object type and primitive types and evaluate type signatures accordingly. To me the language should be able to determine the difference b/w primitive types, component types and don't care buckets and still retain backward compatibility. Use 'any' for the don't cares, component for complex objects or structs and primitives.

    Method overloading is great for maintenance b/c you can overload a method by adding a parameter, thus changing the type signature, and just have to test the new method. This ensures backward compatibility and prevents the need for regression testing since the original method hasn't been touched.

    I just feels like there should be some middle ground out there b/w strongly typed and no type and since CF appears to be in this world today why not actually finish the job.
  • 31 Daniel Greenfeld // Jan 10, 2006 at 8:12 AM

    Seth Petry-Johnson's automatic var scoping of function variables would make me happy beyond words.

    There are times also when I want method-overloading. You can do clumsy work arounds by having a parent method to a number of child methods that handle the individual function handling, but this is clumsy at best. This is the method I am using for my ColdFusion Humane Interface Package (inspired by Python & Ruby), but the more I play with it the less I am not so sure about it. But I don't know of any other way to do what I am trying to do.
  • 32 Sean Corfield // Jan 10, 2006 at 11:02 AM

    As pointed out by one or two folks, we already have the ability to dynamically add / remove methods on objects. It's powerful and used by several modern frameworks.

    We don't have the ability to create code on the fly unless we write to disk (something ColdSpring AOP does, as well as several of the new ORM frameworks). Perhaps that could be more convenient but the write-to-file-then-invoke method works pretty well (assuming you're creating new objects once per application, not once per request).

    Overloading is not really feasible in a dynamic language - overload resolution would have to happen at runtime and it's effectively an O(n*m) algorithm (for n arguments and m candidate methods). Besides, since you can manually test at runtime what type an argument is, you can always have a method that takes type="any" and dispatch internally based on the actual runtime type of that argument.

    NULL. If you use duck typing, you don't really need NULL since you can call isObject(obj) which will return false if obj is 0 or "" or whatever you want to use for NULL. With a real NULL you'd still have to test (obj is not NULL). The only benefit of NULL would be the ability to still specify returntype="component" rather than returntype="any". Given the rest of this discussion, I'd categorize that as syntactic sugar.

    Constructors. Huh? If you work with Java objects in CF, you have to explicitly call init() to invoke constructors that take arguments. Why not just continue to use init() in CFCs? What would "real constructors" get you that init() does not? Pure syntactic sugar!

    Auto-var-scope. OK, this is a good one. I agree that it would be nice to somehow be able to tell the compiler that unscoped variables should automatically be declared 'var' instead of defaulting to 'variables' scope. It would need to be a "compile-time" flag and probably on a per-file basis so you could mix'n'match old and new code without breakage. Perhaps a cfprocessingdirective flag?
  • 33 Sean Corfield // Jan 10, 2006 at 11:12 AM

    I submitted ER 61862 for the auto-var-scope / flag undeclared variables enhancement.
  • 34 Bruce // Jan 10, 2006 at 2:34 PM

    Sean - "syntactic sugar" have to disagree.

    For a while I was using a setup function and then a configure function to "construct" my CFC objects. Then I stumbled across a blog post about using init() and discovered that's what many other developers are doing.

    If constructors become a standard part of CF then we can avoid confusion among developers and also ease the transition for the hoards of Java and .net programmers migrating to CFMX development.
  • 35 Sean Corfield // Jan 10, 2006 at 5:45 PM

    Bruce, if the documentation specifically told people to use init() would that be sufficient? (Given that the docs would have to tell people to use *something* for the constructor).
  • 36 Nando // Jan 10, 2006 at 5:49 PM

    Wouldn't a constructor method be automatically called when the object is created? If it's present?
  • 37 Bruce // Jan 10, 2006 at 5:58 PM

    Sean - what's negative about CF adding real constructors?

    If the constructor method has the same name as the Component, then the existing code base that uses init() would still work.

    Also, for all those CFC's that currently don't have a constructor CF would just add a default empty constructor. Those all the existing CFCs should work.
  • 38 Jared Rypka-Hauer // Jan 10, 2006 at 7:18 PM

    Negative? Nothing... however because you can't pass anything into a createObject() call or a cfobject tag, you'd still have to append the method name to it to pass in any values. The only alternative is to create a new argument to createObject() that takes a struct as input parameters or something, which very much feels like a hack.

    WIth Java, you can call new Object(param1,param2), so you're STILL calling a method. CF has no such technique... createObject() is it... and since Java requires you to import any class you're going to instantiate anyway, it conflicts with the whole concept of runtime binding. You're free to name the method the same as the object instead of init, but there's no practical non-hack way to make this work.

    So runtime binding and createObject/cfobject make it impossible for CF to have "genuine" constructors (although an argument could be made for init() BEING a genuine constructor, at least by convention). The limited concept of type make overloading nearly impossible. The fact that CFCs are loosely bundled structs-on-steroids make abstract classes worthless unless you're going to parse a lot of text.

    Where does that leave us?

    Or a better, more relevant question: How do you propose implementing "genuine constructors" in CF? Under the current circumstances, it's impossible... so how do you make them work?
  • 39 Brian Kotek // Jan 10, 2006 at 8:27 PM

    The other issue is consistency. In order to create a Java object using createObject(), you must call init() in order to actually call (and pass arguments to) the constructor. The current setup of using init() for CFCs keeps things the same. If we start changing the way we call CFC constructors, there will be different ways to use createObject() depending on whether you'r instantiating a CFC or a Java class.
  • 40 Sean Corfield // Jan 10, 2006 at 9:06 PM

    I certainly don't see the point of saying that method foo() is now a constructor for object foo() when, for compatibility with Java handling, you'd still call it via init(). Just call the method init() in the first place!

    Bruce / Nando, feel free to respond to Jared, Brian and myself on this one - I just can't see any benefit to changing how "construction" is handled since today CF and Java objects are treated so similarly.

    Also bear in mind that New Atlanta introduced a cfconstructor tag but then later dropped it because there wasn't any worthwhile benefit.
  • 41 Bruce // Jan 11, 2006 at 11:36 AM

    Jared asked "How to do you propose implementing genuine constructors in CF?"

    My CFC named Foo has a constructor method named foo () with arguments firstName and lastName

    Using <cfinvoke> method attribute is given the value of foo, the returnvariable is the name for my CFC object since foo() returns a reference to a Foo object. I can use method arguments, the argumentCollection, or the <cfinvokeargument> to pass the values to my constructor arguments.

    Using <cfobject> tag all CF would need to add would be an optional argumentCollection attribute, the constructor would be called by default and be passed the argumentCollection.

    Using createObject again CF would need to add an optional argumentCollection attribute. The constructor method is called automatically and passed the argumentCollection.

    I don't see any of the above as a hack.

    My key reason for proposing constructors be added to CF is to standardize in the language how CFC objects are created and how their properties are provided initial or default values.

    Most developers have realized the need for a constructor method so why not make it a documented feature of the language?

    The number one CFMX book (Ben Forta's CMFX 7 Web App Construction Kit) doesn't even mention using init() in its chapter on CFCs (chap 23) since it's not a documented feature of CFCs. Thus most developers learning CFMX and CFCs don't start out using init(). Maybe they discover this "practice" or maybe (like me) they come up with their own work around.

    Having a standard, documented constructor feature for CFCs helps all developers learn the same techniques and leads to better code reuse.

    Of course Im not a CFMX expert, but I did stay at a Holiday Inn Express last night :).
  • 42 Bruce // Jan 11, 2006 at 11:47 AM

    Sean:

    See my post above on how I'd implement constructors in CF.

    As for your argument that CF should not add constructors because we have to call init() when creating a Java object and we want object create (either CFC or Java) to be similar -

    CF adds an optional argumentColletction to createObject. The argumentCollection is passed to an appropriate constructor defined in the Java class. If no argument Collection is provided, createObject automatically calls the class's default constructor.

    Thus, how I create a Java object or how I create a CFC object remains similar.

  • 43 Mike Cohen // Jan 11, 2006 at 12:42 PM

    It's funny that many ColdFusion experts strongly advocated interfaces for quite some time, and as CFCs were introduced into the language, so too was a notion of typing introduced with them. This of course was arguably at the height of Java's popularity. (Interesting too that at the same time ActionScript began to look more and more like Java and move towards static typing.) And now as loosely typed languages are experiencing a good bit of hype we see strong typing, interfaces, and the like poopoo-ed. What a fickle bunch we are, so beholden to fashion.
  • 44 Sean Corfield // Jan 11, 2006 at 1:49 PM

    Bruce, you're asking for a specific enhancement: providing a nice clean way for object creation to also call "init()". You didn't answer my question about documentation / guidance: would you be satisfied that "init()" was the standard constructor if the docs said it was?

    BTW, since "init()" is expected to return "this", you can do all in one object creation *and* initialization (aka construction) by simply calling "init()" instead of using createObject() / cfobject:

    [cfinvoke component="Thing" method="init" argumentCollection="#myConstructorArgs#" returnvariable="myObj"]

    That's the same as setting myObj to createObject("component","Thing") and calling init(argumentCollection=myConstructorArgs)

  • 45 Keith Gaughan // Jan 11, 2006 at 2:01 PM

    Nope Mike, it's that few have realised what they really want: type inference.

    BTW, what AS has are type <em>hints</em>, not types.
  • 46 Bruce // Jan 11, 2006 at 2:39 PM

    Sean - I'd prefer the standard constructor be named the same as the CFC.

    More importantly, I'd like the constructor to be called automatically when an object (CFC or Java) is created and also allow argument values to be passed into the constructor.

  • 47 Jared Rypka-Hauer // Jan 11, 2006 at 3:02 PM

    I wish I could explain why this just feels wrong... giving CF constructors isn't... feh. Sorry, it's an instinct thing, not a specific technical thing.

    I can think of one reason, I suppose... createObject(), cfinvoke, and cfobject don't involve themselves with the specific workings of the objects, they're just tools to access code other than CFM files... so involving them in the details of instantiation is outside the scope of their current responsibilities. Once you give CF the priviledge of dictating the content and structure of your objects, though, you start to restrict the usability of your platform. That creative expression is what I love about CF and the lack of it is what I hate most about Java... and I balk dreadfully at the thought of making CF more Java-like.

    Incidentally, I already use init(argumentCollection=someStruct) to pass a whole collection of arguments in... so adding it to createObject() saves you 7 characters and gives CF the privilege of controlling things it doesn't need to, dictating programming style and enforcing the way my objects work for me. It causes CF to do things behind the scenes that obfuscates how things work (which makes it even harder for noobs). And it breaks with how the whole process works from the very foundation of the CFC concept.

    Plus it's been tried and failed to be useful in the case of BlueDragon.

    I just remain unconvinced. It might be handy for you, but for the platform, the language, and in the overall scheme of things, I can't see it being a terribly good thing... but feel free to keep trying to convince people, maybe you'll hit on something.

    Laterz!
  • 48 Sean Corfield // Jan 11, 2006 at 3:05 PM

    Bruce, well, I still don't see why it matters whether the constructor is called "foo()" or "init()" but I do see some minor value in the enhancement you are requesting (to allow arguments to be passed into createObject() / cfobject that are in turn passed to the 'constructor'). ER 61875.

    Note however that the way Java objects are handled is subtle: createObject("java","SomeClass") does *not* call the default constructor; createObject("java","SomeClass").init() *does* call the default constructor. This is to allow Java classes to be loaded and manipulated (e.g., accessing static methods) without forcing construction. In particular, you do not want to call *both* the default constructor and a specific constructor:

    createObject("java","SomeClass").init("foo")

    that should be equivalent to new SomeClass("foo"). It's hard to reconcile createObject("java","SomeClass") automatically calling the default constructor (e.g., new SomeClass()) which is what you are asking for with the backward compatibility of calling a specific constructor.

    Note also that if you do not explicitly call init() on a Java object, the default constructor is called automatically by CFMX the first time you try to access an instance method. In other words, CFMX defers construction to either (1) a call to init(), optionally with arguments or (2) the first instance-based use of the object.

    I don't think constructors as you envisage them can be implemented without breaking that backward compatible guarantee (so I don't think 61875 will ever be implemented).
  • 49 Chris Scott // Jan 11, 2006 at 3:19 PM

    Hey Sean, what you just wrote pretty much sealed the deal on constructors as far as I'm concerned. Sacrificing the ability to call static methods to implement a basically short hand version of the functionality we already have would be terrible. If people would like to have init methods called the class name, go for it, just call CreateObject('component','foo').foo(). But that seems awfully silly and a bit redundant, and awfully silly.
  • 50 Seth Petry-Johnson // Jan 11, 2006 at 3:21 PM

    > But that seems awfully silly and a bit
    > redundant, and awfully silly.

    And a bit redundant :)
  • 51 Jared Rypka-Hauer // Jan 11, 2006 at 4:06 PM

    Dude... you're repeating yourself over and over again!
  • 52 Jared Rypka-Hauer // Jan 11, 2006 at 5:30 PM

    Chris,

    Ditto... there's all sorts of reasons this is a bad idea, and the reasons are starting to troop into my head. :) I like when that happens.

    CF doesn't work like Java. In CF you can create an object without instantiating it, which is incredibly powerful for doing method injection, introspecition and stateless objects. It's how CF gets around the lack of static vs instance methods... createObject() doesn't do anything but read the CFC and prepare for calling methods on it... whether it becomes an instance of that class or is just used as having static methods is up to the developer.

    People rant and rave about not using frameworks because of "the overhead" (which is pretty silly anyway) but when it comes to introducing "features" which absolutely add extra processing to CFCs, it's all good. Bruce, it may be good for how YOU use CFCs... but CFCs are so far beyond anything Java can do and restricting them to simple instantiation/method calls is selling them way short.

    Think of this: createObject() creates a usable object in memory, and some methods require instance data while others do not. If I want to createObject("component","addition").add(2,2) and have it work, then having createObject() first call a constructor is a total waste of clock cycles. I'll grant you that's an extremely simplified example, but there are many out there that are more complex and yet just as true.

    Just a few more thoughts... :)
  • 53 Mike Cohen // Jan 11, 2006 at 6:05 PM

    Semantically, what's the difference between static vs instance methods of a java class and a cfc with or without calling an "init" constructor? What do CFCs do that a java class doesn't?

  • 54 Bruce // Jan 11, 2006 at 7:07 PM

    Jared:

    Since I do both CF and Java development (and love both languages) please explain..

    "but CFCs are so far beyond anything Java can do and restricting them to simple instantiation/method calls is selling them way short"



  • 55 Bruce // Jan 11, 2006 at 7:13 PM

    Sean -

    Hadn't considered the static method angle. However, I don't thinkt that the CFC methods are really static methods (otherwise they could not access instance fields [ variables or this scope ] ).

    What if the <cfinvoke> tag just created the CFC object using a default constructor and then called the method - similar to how it works now. I could still call any method I wanted without concern about object instantiation.

    I think CF is really creating a an object and calling the method, then dumping the object when you use <cfinvoke>.

    Since a static Java method can be called using an object reference, having createObject call the default constructor and then call the static Java method doesn't break anything.

    Bruce
  • 56 Sean Corfield // Jan 11, 2006 at 7:41 PM

    Bruce, if you call cfinvoke on a component and specify a method it does the following:

    tmp = createObject("component","TheComponent");

    tmp.someMethod();

    Now, one thing nobody has pointed out in this thread is that createObject() (and cfobject) both actually do execute the "default constructor" - what is more usually called the pseudo-constructor.

    Any code inside the cfcomponent tags but outside any cffunction tags gets executed automatically when a CFC is created.

    In other words you can already do exactly what you want:

    [cfcomponent]

    ... write your default constructor code here ...

    [cffunction ...] ... [/cffunction]

    ...

    [/cfcomponent]

    Then when you call createObject() (or cfobject) that inline default constructor code will be executed automatically.

    As for static methods, I'm talking about Java, not CFCs. But the point is that you do not want the behavior to be gratuitously different between how CFMX handles Java objects (deferred calls to the default constructor, or explicit init() calls) and how it handles CFC objects.

    I can't help thinking that some of the requests being made for "Java-like" features to be added to CFMX stem from a lack of understanding of some of the power of a dynamic language (CFMX)...

    (be warned, ithe pseudo-constructor code is also executed if you use the CFC Explorer since that has to create an instance in order to get the metadata to display)
  • 57 Jared Rypka-Hauer // Jan 11, 2006 at 7:51 PM

    Bruce,

    I guess it's just a matter of them being distinctly different animals, CFCs and Java classes. CFCs allow you to do all sorts of creative things, like adding attributes to the cfcomponent tag and then accessing them thru getMetaData(myInstance) (which I've been working on as a way to create "interface definitions" in CFCs, btw) and treating methods as struct keys (which enables Behavior Injection where you actually inject the method into the CFC), accessing the default local scope from within a running function (via the PageContext object)... in other words, if you can come up with a viable reason to use any given technique there's almost nothing you can't do with CFCs.

    A CFC is a base class composed with separate classes for each "method" which are basically UDFs. Based on observation, it looks like an instantiated CFC is basically a page context that hosts 3 other page contexts... super, this and variables. "THIS" is actually available from within variables by a default struct called THIS (so variables.this.something works the same as this.something) and, since there are no rules about typing other than content-type checking you can literally do ANYTHING (including cfreturning cfcatch as a struct from an error, or setting a method as a property on another method, or...)

    So a CFC bears almost no relationship to a Java class other than the fact that they're both OO constructs that handle polymorphism, encapsulation, and inheritance.

    That's what I meant. :)

    HTH...
  • 58 Jared Rypka-Hauer // Jan 11, 2006 at 7:54 PM

    Thinking about it, in many ways CFMX is almost the opposite of Java. CF works WITH Java, but I think it's fair to say that CF is almost the anti-Java. ;)
  • 59 Ramchandra Kulkarni // Jan 11, 2006 at 9:22 PM

    I think interfaces in ColdFusion can be very useful to developers. It is a contract that you want the user of your program to follow.
    Using any type as a replacement for interfaces would certainly work, but you will have to do a lot more validations in your program to make sure you are getting proper data type- in most cases you can do meaningful things with the value only when you know its data type.
    Even in ColdFusion functions, you do not always use 'any' data type for arguments. You do specify type as int, struct, query etc. because the logic in your function depends on argument being of certain type. Interfaces will ensure the same thing for your framework or reusable program.
    Let's consider examples with and without use of interfaces. You are writing a framework and one of the functions in your framework expects a component with certain methods. Without interfaces you will have to make sure that the component passed has required methods, each required method has required arguments, each required arguments are of certain data type. With interfaces, you simply define an interface and make it a required argument in your function.

    Without interface -
    cffunction name="SomeFunc"
       cfargument name="arg1" type="WEB-INF.cftags.component" required=true
       Do all validations about methods in arg1, their arguments and data types
    /cffunction

    With interface -
    cffunction name="SomeFunc"
       cfargument name="arg1" type="SomeInterface" required=true
       No need to perform validations on methods in arg1, arguments and types
    /cffunction

    So you can either choose to do all validations about methods of the component yourself or leave it to the language to do that.

    Of course, there are other advantages of the interface. By requiring interface data type of an argument, you, as a framework developer are sure that your method is not called unless component passed to your method implements all the methods you expect. Without interfaces also you will get error about non-implemented functions, but you come to know that within your function, may be after performing some operations on the component.
    With interface, object creation will fail if it does not follow the contract - which means that you will find about missing method much earlier, not later in your function.

    Interfaces will let you associate multiple and different behaviors with the component by allowing multiple inheritance. Good example is Serializable in Java. By implementing this interface you all the object to be serialized.

    Interfaces also communicate required contract to the developer very concisely. You don't need verbose document about what the user of your program should do.
  • 60 Sean Corfield // Jan 11, 2006 at 9:35 PM

    Ramchandra, the reason that interfaces aren't as useful in ColdFusion as many people seem to think is that the type checking is only done at runtime.

    In your example, interfaces would give you a runtime error that "argument 2 does not implement interface foo" at the calling site, for example. Without interfaces, any attempt to use the argument in a way that the argument didn't support would give you a runtime error that "method bar not found in arguments.obj" at the use site. Either way, you get a runtime error.

    I'm also not convinced the interface error is likely to be able to give better debugging info than the use error...

    Interfaces make a lot of sense in a statically typed, compile everything first language (like Java, C#, C++) but they make a lot less sense in a dynamically typed, compile at runtime language (like ColdFusion).
  • 61 Ramchandra Kulkarni // Jan 11, 2006 at 9:46 PM

    Hi Sean, my point was that by using interfaces, the function that accepts interface as an argument won't event get called if the component does not follow the contract e.g. CFC1 -> implements -> CFI1. CF function 'foo' takes arg1 of type CFI1. If you have a code like

    aCfc = CreateObject("component", "CFC1");
    foo(aCfc);

    if CFC1 does not implements all the methods in CFI1 properly, CreateObject will fail. So 'foo' will not get called with invalid component.

    Also, as I mentioned earlier, you don't have to perform validations like if CFC contains a method, that takes perticular arguments of perticular type etc.

  • 62 Mike Cohen // Jan 12, 2006 at 5:12 AM

    Can I do anything special with those attributes I added to the cfcomponent tag, other than just read them back again? Methods as struct keys, hmm, sounds like the decorator pattern, or an aop introduction. Accessing pageContext from a cfc method? Easily done in Java. Accessing this from the variables scope? Easily done through introspection if the SecurityManager is not used, but most people prefer to have their class invariants guaranteed. Setting a method as a property on another method? In Java it's called the Command pattern (i.e. Runnable). Returning cfcatch? I suppose I could specify Object as the return type and return the Exception. This begs the question, why in the world would I ever want to do such a thing? And for me is related to the discussion of interfaces. Often overlooked in this debate is the inherent function of documentation that interfaces and strongly typed languages provide. It's about code readability. Some of the more exotic things that can be done with CFCs probably should not be done. At least not in code that other people are going to have to come along and read, understand, and modify later on.
  • 63 Jason Daiger // Jan 12, 2006 at 6:23 AM

    CF does not truely implement interfaces unless you consider subtyping implementing an interface. CF can't inherit from A and implement B & C like a Java or C# class can. Interfaces by definition are implemented by a class that may or may not inherit properties and methods from a different source and CF (as I know it) definitely can't implement in that fashion. In my opinion, it's not a true interface by any means. So should CF have true interfaces, not unless CF changes to being a compiled language instead of a runtime one. Compiled languages need interfaces for many things one of which is the runtime flexibility CF has by design.

    Should we as developers in practice use the concept of an interface? I my opinion yes. Using the concept of an interface provides a clear contract between a class and its subclasses which is a good thing. It's really no different than implementing a design pattern. Maybe just call it an architect pattern that you can choose to (or not to) use.
  • 64 Seth Petry-Johnson // Jan 12, 2006 at 6:45 AM

    Mike said: "Often overlooked in this debate is the inherent function of documentation that interfaces and strongly typed languages provide. It's about code readability. Some of the more exotic things that can be done with CFCs probably should not be done. At least not in code that other people are going to have to come along and read, understand, and modify later on."

    But CF **isn't** a strongly typed language, which means we can't evaluate it using the same metrics as we do Java or C++ or others.

    This discussion IS NOT about which is better: dynamic typing or strong typing. Its about whether or not interfaces should be added to CF *even though* dynamic typing and late binding means they will be a documentation tool more than anything else.

    I don't see a lot of ADDED value between saying method foo implements bar versus adding a hint to foo that says "Passed object must implement a bar1() and bar2() method".

    If the feature were there I would use it but I don't think its critical by any means.
  • 65 Brian Kotek // Jan 12, 2006 at 7:33 AM

    Am I the only person who thinks this debate is going in circles? The bottom line is that adding interfaces will ONLY (and CAN only) change the text of a runtime error message! The ONLY difference would be that instead of a runtime error with the text string "method foo() cannot be found in component Bar", the text would say "component Bar does not implement interface Foo". THAT'S IT. All the effort to add interfaces just to change the text of an error message seems rather crazy.
  • 66 Johnathan Gifford // Jan 12, 2006 at 8:33 AM

    Definately agreed, this discussion is going in circles and has strayed from the REAL topic.

    The strong type fanatics simply want interfaces. If ColdFusion had interfaces, then the init() constructor could be forced by requiring that method in the WEB-INF.cftags.component. I say, give them interfaces, maybe the disscussion can then turn to more about how to accomplish dynamic typing in ColdFusion.

    Take a look at the BIG names in the ColdFusion community. For a few years (or least since CF MX 6) both Sean and Hal have been big proponents of interfaces and the biggest voices for it for a long time. Now they see a different possibility. So now all us strong typers should take a minute, get into the zen of it, and see what the possiblities are of dynamic type and how to do it in ColdFusion.

    The more techniques you learn, the more rounded and better programmer you are. Even if you prefer strong typing over dynamic typing. After you would want a surgeon operating on you with tools and techniques of the 1970's would you?
  • 67 Sean Corfield // Jan 12, 2006 at 3:05 PM

    Ramchandra, good point on where the error would actually appear (at creation, not at the call site). It's still runtime but, you're right that it could prevent creation of objects that do not implement an interface correctly.

    I think this has been a very interesting discussion. It's clear that a significant number of people feel strongly that interfaces would add value to ColdFusion and if interfaces were added those folks would then be able to evaluate whether or not the added value is real. There are also a significant number of people who are happy with the status quo and are comfortable pursuing a more dynamic approach to typing.

    ColdFusion is already a general purpose, multi-paradigm language, allowing all sorts of applications to be built in either a procedural style or an OO style or some middle ground. Adding interfaces would increase the paradigm range without negatively impacting those folks who aren't ready to use them (or who wouldn't want to use them).

    Thanx for all your input and I would strongly encourage the "strong-typing / pro-interface" camp to explore the broader possibilities of dynamic programming if they haven't already...
  • 68 Mike Steele // Dec 12, 2006 at 12:03 PM

    I just used the getMetaData() function and wrote a component to enforce interfaces during the componentutil's cfdocument run. Since we document our code that way, I let the documentation provide me with a check for making sure I've implemented the right component, function AND arguments.
  • 69 LT // May 30, 2007 at 12:14 AM

    well, it looks like we now have interfaces in CF! hurrah!
  • 70 Sean Corfield // May 30, 2007 at 12:45 AM

    @LT, no "hurrah!" from me... I think it's a terrible idea.