oopcoldfusioncfcfilesizecfinvoke

How to handle "Invalid method Code length" in Coldfusion?


I have a bunch of cfc files (running coldfusion8), which consist of a cfswitch bundling similar functions (user, search, ...).

Some of the cfc files are becoming too large, so I'm receiving a Invalid method Code length 72645 which I assume says, "your file is too big to be parsed"..

I'm usually reaching this at about 2000 lines and think this is ... not much.

Since I'm bumping this upper limit on a bunch of files, I'm considering adding another functional layer = remove all functions from the switch-statement and call cfinvoke with a separate cfc per function.

Question:
My application is not that big, so I'm wondering, is there a way to circumvent the "you-can't-have-more-than-2000-lines-in-a-cfc" upper-limit and if not, is it a viable approach to have separate CFCs/components for every main method to be called in an application?

Thanks!

EDIT: re: "planned" :-)
Currently my CFCs are structured like this:

<cfcomponent extends="controllers.main" output="false" hint="handle all user interactions">     
    <cfscript>
        VARIABLES.Instance.Validation = {   
            // all user-relate form fields including validation method to call (pass = no validation)
            id="spec_id"
          , corp="pass"
          ...
        };
    </cfscript> 

    <cffunction name="Init" access="public" returntype="any" output="false" hint="Initialize form data">
        <cfreturn true />
    </cffunction>   
    <cffunction name="Defaults" access="public" returntype="struct" output="false" hint="Assign defaults">
       <cfscript>
          // form default values assigned to instance
          var formDefaults = {
              id=""
            , comp=""
            ...
          };
       </cfscript>
       <cfreturn formDefaults />
    </cffunction>

    <cffunction name="Commit" access="remote" returntype="struct" output="false" hint="Main handler">
        <cfscript>
        // all var declarations
        var userID = "";
        var strRememberMe = "";
        var timestamp = now();
        ... 
        var defaultValues = THIS.Defaults();
        var LOCAL = {};

        structAppend(defaultValues, VARIABLES.Instance.FormData);
        LOCAL.User = defaultValues;
        LOCAL.User.timestamp = timestamp ;
        </cfscript> 

        <!--- the switch --->       
        <cfswitch expression = #LOCAL.User.submitted_form#>

            ... lot of stuff ...

        </cfswitch>

        <cfreturn LOCAL.Response />
    </cffunction>

    <!--- UTILITY FUNCTIONS --->
    <cffunction name="Validate" access="public" returntype="array" output="false" hint="validate form inputs">
        <cfscript>
        var LOCAL = {};
        var double = structNew();
        double.criteria = VARIABLES.Instance.Validation;
        double.form = VARIABLES.Instance.FormData;
        </cfscript>

        <!--- Get error name and type --->
        <cfinvoke component="form_validate" method="validate_fields" double="#double#" returnvariable="validation_errors"></cfinvoke>
        <cfset LOCAL.ErrorMessages = validation_errors />
        <cfreturn LOCAL.ErrorMessages />
    </cffunction>                                   
</cfcomponent>

Now I have been writing a lot of unstructured stuff, but splitting up in functional-cfcs and then handling them like this did not seem very "un-planned" to me.

If it is, what would be a better way to set this up, since I'm having to re-do it anyway? The switch will have about 15 cases, which is the average across all the main cfcs I'm using.

Thanks!


Solution

  • I experienced this problem in CF8 some time ago as well. There is no general "2000 lines limit" but a maximum value in the JVM for the address offset in order to jump within a subroutine. The offset must not exceed 2 Bytes (WORD), otherwise you will face this exception. To avoid large address offsets within a subroutine (function), you need to minimize large blocks of conditional jumps (if/else/switch). You can do this by using multiple subroutines instead (these calls may take the full register up to 4/8 Bytes).

    For example: Redesign...

    function A (x, y) {
        if (...) {
            switch (...) {
                case ...:
                    switch (...) {
                        ...
                    }
                ...
            }
        } else {
            switch (...) {
                ...
            }
        }
    }
    

    To something like...

    function A (x, y) {
        if (...) {
            call B(x, y);
        } else {
            call C(x, y);
        }
    }
    
    function B (x, y) {
        switch (...) {
            case ...:
                call B1(x, y);
            ...
        }
    }
    
    function B1 (x, y) {
        switch (...) {
            ....
        }
    }
    
    function C (x, y) {
        switch (...) {
            ....
        }
    }
    

    ...you get the idea. This will usually also improve readability and maintainability.