Helper Class

May 13th, 2008

Sometime you need a little class to act as a Utility but still allow for for instance specific configuration. In one class your util may need to do X and in another Y but the functions and methods need to be the same for both classes. In the past I use to develop Singleton or Static utility classes but this situation breaks my design pattern. How do I handle these one off customizable utilities? I create helpers.

For me a helper class is a class instance similar to a utility with options to customize its internal values. Here is one example of a helper class I am now using in my Settings Utility.

package
{
        /** (c) Copyright 2008 Heavy, Inc.  All Rights Reserved.
          *
          * Original Author:  Jesse Freeman
          *
          * Revisions
          *     0.1  Initial version 05-08-2008
          *
          **/

        import flash.utils.Dictionary;
       
        public class XMLTypeHelper
        {
               
                public static const STRING:String = “string”;
                public static const NUMBER:String = “number”;
                public static const ARRAY:String = “array”;
                public static const BOOLEAN:String = “boolean”;
                public static const ASSOCIATE_ARRAY:String = “associate_array”;
                public static const DICTIONARY:String = “dictionary”;
                public static const COLOR:String = “color”;
               
                public var unknown_type_handler:Function = null;
               
                public function XMLTypeHelper(){
                        trace(“Alert: New XMLTypeHelper has been created.”);
                }
               
                public function get_type(data:String, type:String):*{
                        switch(type)
                        {
                            case STRING:
                                return data.toString();
                                break;
                            case NUMBER:
                                return Number(data);
                                break;
                            case ARRAY:
                                var temp_array:Array = data.toString().split(“,”);
                                return temp_array;
                                break;
                            case BOOLEAN:
                                return string_to_boolean(data);
                                break;
                            case ASSOCIATE_ARRAY:
                                return parse_complex_array(data,ASSOCIATE_ARRAY);
                                break;
                            case DICTIONARY:
                                return parse_complex_array(data,DICTIONARY);
                                break;
                            case COLOR:
                                return Number(data);
                                break;
                            default:
                                if(unknown_type_handler != null)
                                        return unknown_type_handler(data);
                                else
                                        return data;
                                break;
                        }
                }
               
                public function parse_complex_array(data:String, return_type:String,data_delimiter:String = “,” ,prop_delimiter:String = “:”):*{
                       
                        var data_container:*;
                       
                        // Switch Statement
                        switch (return_type){
                               
                                case ASSOCIATE_ARRAY:
                                        data_container = new Array();
                                break;
                                case DICTIONARY:
                                        data_container = new Dictionary();
                                break;
                        }
                       
                        var list:Array = data.split(data_delimiter);
                        var total:Number = list.length

                        for (var i : Number = 0; i < total; i++) {
                                var prop:Array = list[i].split(prop_delimiter);
                                data_container[prop[0]] = prop[1];
                        }
                       
                        return data_container;
                       
                }
               
                /**
                 *
                 */

                public function string_to_boolean(value:String):Boolean{
                        return (value == “true”) ? true : false;
                }

        }
}

So this is a really simple class. It basically converts values read in from an XML file and converts them into typed valued base on the attribute type. Nothing really special here, in fact I was using something similar to this set of functions in my AS 3 Setting Utility. So why break this out into is own class?

Part of writing truly OOP code is being able to break out reusable functions into other classes. Also now with all this code taken out of the setting utility I can keep adding to it and have the logic in one self contained place outside of the class that needs it. I can also configure this class’s instance based on the situation it is needed in.

Now there is a special property called public var unknown_type_handler:Function = null;. This allows you to map a custom function to be called when the util doesn’t know what the data’s type should be. Here is an example of how to use it.

var typer = new XMLTypeHelper();
        typer.unknown_type_handler = special_type_converter;

. . .

internal function special_type_converter(data:*):*{
                        switch(data.@type.toString()){
                        case “Option A”:
                        return null // Handle Option A Here;
                        break;
                    case “Option B”:
                        return null // Handle Option B Here;
                        break;
                        }
                }

One last thing I am proud of in this class is the converter to Associated Array and Dictionary. When you supply xml that is comma delimited with colons dividing prop name and value, this class will give you back a parsed Array or Dictionary. Here is an example of what the data node would look like:

<item type=“dictionary”>hello:world,this_is:great</item>

This class is still under the microscope at Heavy so in it’s final state I expect it to be a little cleaner, and less buggy (if any exist let me know). I’ll be posting more of my Helper Classes as soon as I get stable. So far I have several that range from creating 9 slices from bitmaps to class finders and a few others. Hope you enjoy!

Oh, and make sure you visit Heavy.com to see more of my work and click on a few ads to keep the lights on in my office.

3 Responses to “Helper Class”

  1. Kris Says:

    I like the idea of making var methods which can be utilized to alter pieces of the mainlasse’s functionality. Mostly, I’d probably lean toward inheritance to create a class which overwrite the parent, or as you demonstrated a separate function. Otherwise, I’d be afraid that internal changes of the main class would require me to hunt down every place I’d written external methods.

    I’m looking forward to seeing why you’re going with such specific data XMLs instead of for instance

    seems like it may have been less work, then inventing your own standard.

  2. Kris Says:

    woops your comment box killed my XML.

  3. FlashBum Says:

    These classes are meant to be small collections of static code. I only create them after the I know they are production ready. I think the switch statement I created for converting xml data to native flash types has been the same thing I have used since AS 1. Not to mention classes that use this are expecting specific data back from the help so there is a small assumption that these are going to be tightly coupled.

    Probably next week sometime I am going to do a high level overview of Heavy’s new framework and hopefully it will become a little clearer why I am converting xml and relying on type conversions like this.

Leave a Reply