ColdFusion and the need for method overloading.

ColdFusion has never had this and I can never work out why, I do know that over time it has been mentioned a few times and has always been answered with the fact that you can pass the type of any into the function.

That might sound good in the interim, but I wonder how many of these people who say that have really thought about the problems that this might raise?

I raised this as an enhancement with Adobe and it appears that they seem to agree, but I am not 100% sure if it will make it in the update 1 as promised.

So the first thing I would like to do is get people to back this, and explain why this is important the future of ColdFusion.

Lets look at some code that I am writing at the moment, at first glance there is nothing obscure about the function. That is until we are needing to enhance it, more on that latter.

public array function getPosts(required string blog) {
}

As this function stands it will return all posts that are for the passed blog, which is nothing special. But when we wish to filter this, currently we have a few options that we could do. The first would be to leave it like this, and add a new method as follows.

public array function getPostsByYear(required string blog) {
}

Now if we were to then have a good think about this, we would end up with a lot more functions than we would really require. Or we could do the next best thing, and create more arguments than is necessary, or may never be used.

public array function getPosts(required string blog, string year, string month, string, day) {
}

Now the second is maybe the better way of writing this, but it is not without its problems. For example if we look at the year, month and day you will notice that these are not required. Which means that we would have to write more logic to check for the inclusion and validation of these parameters.

This may not be the best example, but what if this was to then be re-factored. To something like this.

public array function getPosts(required string blog, string author, struct date) {
}

So what is the problem here, because I can hear you saying that there is no real problem here. Well technically there isn't. Until you are refactoring code, because when you re-factor some like this you are then forced, and yes you are forced to go and search for every occurrence of this method and modify and re-factor that code as well.

The best solution here would be to allow for method overloading, and not have to worry about having to go back through your entire Application and making sure that it is modified. Instead it would be easy to just do the following

public array function getPosts(required string blog) {
}
public array function getPosts(required string blog, required string author) {
}
public array function getPosts(required string blog, required struct blogDate) {
}
public array function getPosts(required string blog, required string author, required struct blogDate) {
}

This is something that has annoyed me over the years, not because it is hard to get around. But it opens up the fact that when refactoring code, it actually creates more work. It also opens the Application up for developers to get lazy and not have to go through the paces of checking the Application for its changes, and test these changes.

I know Adobe has said that they will introduce this, but I really would like to drum up support to get this introduced sooner than later.



  • Sean Corfield's Gravatar One problem comes when you have methods that do not have guaranteed distinct argument type sets:

    function getPosts( required string blog, string author ) { ... }

    function getPosts( required string blog, numeric maxPosts ) { ... }

    Since CFML treats 123 as "123" (a string), both versions are callable.

    The other big problem is that the resolution of which method to call would have to be done at RUNTIME and that means that every single method call would have to support finding multiple methods to call and then having to inspect the types of every possible method to see if it was callable...

    Overload resolution is a big overhead at runtime.
    # Posted By Sean Corfield | 2/12/10 9:25 PM
  • Andrew Scott's Gravatar Another reason why I have never been a big fan of typless, it might have been good a few years ago. However it is going to be the thing that will hinder ColdFusion from really achieving great things.

    Unless Adobe can pull of some exceptional miracles.
    # Posted By Andrew Scott | 2/12/10 9:35 PM
  • Oscar Arevalo's Gravatar ;I don't see this happening really, since in a way it would go against standard ColdFusion behavior. I mean, in CF your arguments scope is not really constrained to what you explicitly declare with <cfargument /> (or the equivalent), you can call a function and pass a hundred arguments even if you only declared one, and all those extra 99 arguments would be available on the arguments scope. There are tons of code out there that rely on this type of behavior, which coincidentally is the complete opposite for what is required for method overloading.

    Any semblance of method overloading should be taken care programatically in your method body.
    # Posted By Oscar Arevalo | 2/13/10 1:10 AM
  • Andrew Scott's Gravatar And that is what I call bad coding too, and although ColdFusion allows it doesn't make it right either. Give me an example of a situation where you would do this, and I will show how bad of a code design it is.

    The problem is, and this is not Adobe's fault but they don't nip it in the butt. Is that quick fixes are introduced to the language to met the short term problems. This is a problem when you have an Application thats life cycle is 2 years before a new release, it opens the doors to more bad coding and because it is a quick fix at the time. It hinders the Application in years to come.

    Your example is one such thing that will hinder ColdFusion in years to come. The fact that it is typeless, will also make it even harder for Adobe to begin to even introduce java code inline to ColdFusion.

    And the worst thing with your example, I would not like to be the one debugging that style of code either. Nor would I want to be writting extra code to take care of all the unknown arguments passed into the function either.

    ColdFusion allows for spaghetti coding too, but its totally frowned upon these days as well. I really can't imagine maintaining that sort of code.
    # Posted By Andrew Scott | 2/13/10 8:22 AM
  • Matt Woodward's Gravatar You can avoid function explosion by handling overloading type behavior within your function itself. Just make all options that can be optional optional, and throw some conditionals in the function based on the arguments you get to handle the rest of the processing accordingly.

    Not the same as method overloading but I agree with Sean's assessment of the inherent problems with doing this in CFML. If you had asked me a couple of years ago I would have argued for it, but it's not a huge burden to have a single getFoo() function that handles how it gets Foo based on what arguments it receives.
    # Posted By Matt Woodward | 2/13/10 10:11 AM
  • Andrew Scott's Gravatar @Matt - That is the exact reason I raised the ticket, because you are forced to provide your own conditional statements. Write more code, and bloat the function. The function needs to be clear and precise as to its function, and not blind sighted by all this conditional checks that is outside the scope of Rapid Application Development.

    And people are forgetting that Adobe have agreed, and have indictaed that they will be providing this.

    All I am asking for is more support, to get it in quicker.
    # Posted By Andrew Scott | 2/13/10 3:44 PM
  • Josh Knutson's Gravatar I know I always thought it would be really awesome just to add some extra attributes to the cfrargument tag

        <cffunction name="getSomething" returntype="any">
           <cfargument name="source" default="" condition="required:if(len(arguments.name) eq 0)" />
            <cfargument name="name" default="" condition="required:if(len(arguments.source) eq 0)" />


        </cffunction>

    but until then I am stuck with having cfthrow statements in my code instead

    # Posted By Josh Knutson | 2/24/10 5:58 PM