Sunday, May 1, 2011

One file per function...really?

I am relatively new to Flex/ActionScript, but I have been using a pattern of creating one file per function in my util package - with the name of the file being the same as the name of the function. Like if the file was convertTime.as:

package util{
    public function convertTime(s:String):Date{
        ...
    }
}

This way I can import the function readily by doing:

import util.convertTime;
...
convertTime(...);

I like this way better than importing a class object and then calling the static methods hanging off of it, like this:

import util.Util;
...
Util.convertTime(...);

But, the more I do this, the more files I'll end up with, and it also seems a bit wasteful/silly to put only one function into a file, especially when the function is small. Is there another alternative to this? Or are these two options the only ones I have?

Update: after some research, I've also posted my own answer below.

From stackoverflow
  • Is there another alternative to this? Or are these two options the only ones I have?

    There aren't two options. Those are two bad conventions. Only using static methods and treating AS as a procedural language on one hand, and your quirky one-file-per-function convention on the other.

    None of the two is really option in the long term.

    To take advantage of an OO environment you have to build classes which represent objects from your problem domain.

    Consider investing in a book on Object Oriented methodology and class design.

    toby : The last part was somewhat of a personal attack and I don't appreciate it. The reason I like ActionScript more than Java(I am no stranger to OO) is because it gives you more flexibility to choose what programming style to use. OO is by no means the only way things get done.
    ryeguy : Judging from your profile, you're a haskell programmer. It's great to expand to functional programming (I'm an erlanger myself), but make sure you switch your brain back to OO mode when you come over to an OO language. You're right, OO is not the only way to get things done, even in an OO language. But if you really are cluttering up your directory by making THAT many functions, then you must have a lot of static methods. In that case, you're doing it wrong.
    toby : Dude, that's why I am asking the question here: to see if there are alternatives than to clutter up my directory. Don't be hatin'.
    Scotty Allen : Wow, kind of an inflammatory answer, no? While what you say is technically correct, the bashing seems unnecessary...
    foljs : Sorry if I am getting across as ad hominen. I meant the "invest in a book on OO methodology" part simply as pragmatic advice. OO is not the answer to everything --I love functional stuff too--, but it sure is better than 70's style procedural programming...
  • Yes, these are your two main options for utility libraries. We actually use both of these approaches for our generic utility functions. For a very small set of functions that we feel should actually be builtins (such as map()), we put one function per file, so that we can use the function directly.

    For more obscure/specialized utility functions, we don't want to pollute our global namespace so we make them static functions on a utility class. This way, we're sure that when someone references ArrayUtils.intersect(), we know what library intersect() came from, and what roughly it's for (it intersects two arrays).

    I would recommend going with the latter route as much as possible, unless you have a function that a) you use very frequently and b) is really obvious what it does at a glance.

    toby : Thanks Scotty! Not only for a good answer but also for being nice =)
  • I came across some other alternatives after all and thought I'd share them here.

    Alternative 1 - use inheritence

    This is probably an obvious answer, but is limited. You would put your static methods into a parent class, inherit them to get them in the subclasses. This would only work with classes. Also, because ActionScript is single inheritence, you can only inherit once.

    Alternative 2 - Alias the methods

    You still write utility functions as static methods hanging off util classes, but you alias them so you can access them with a shorter name, ex:

    import mx.binding.utils.BindingUtils;
    var bind:Function = BindingUtils.bindProperty;
    

    Now you can just call

    bind(...);
    

    rather than than the lengthy

    BindingUtils.bindProperty(...);
    

    You can do this within the class scope and the function scope, but not the package scope - because apparently you can only have one visible attribute inside a package. If you do this in the class scope, you will want to make sure it doesn't conflict with your other class attribute names.

    Alternative 3 - use include

    As described in this flexonrails blog post you can use include to simulate a mixin in ActionScript. An include is different from an import in that all it's doing is copying the entirety of the file you are including from and paste it into the place you are including it at. So, it has completely no handling of namespace issues, you can not reference its full path name afterwards like you can with imports, if you have conflicting names, you are on your own with this. Also unlike import, it creates different copies of the same code. But what you can do with this is put any number of functions in a file, and include them into class or function scope in another file. Ex:

    // util/time_utils.as
    function convertTime(..){
       ...
    }
    function convertDate(..){
       ...
    }
    

    To include:

    include 'util/time_util.as';  // this is always a relative path
    ...
    convertTime(...);
    
    an0nym0usc0ward : Alternative 4 - Consider investing in a book on Object Oriented methodology and class design.
  • @ an0nym0usc0ward

    OOP is simply the method of consolidating like functions or properties into an object that can be imported and used. It is nothing more that a form of organization for your code, ALL code executes procedurally in the processor in the end, OOP is just organization of sources. What he is doing here may not be OOP as you learn from a book, but it does the exact same thing in the end, and should be treated with the same respect.

    Anyone that truly understands OOP wouldn't be naive enough to think that the approved and documented form of OOP is the only possible way to object orient your code.

    EDIT: This was supposed to be a comment response to an0nym0usc0ward's rude comment telling him to learn OOP. But I guess I typed it in the wrong box :)

    an0nym0usc0ward : If you are programming in Flex, this is completely the wrong approach. The advice may be rude, but it is correct.
    Bryan Grezeszak : See, the thing is, I do completely OOP, have for years, java c# AS3, etc. So I know where you're coming from. BUT to truly understand OOP then you must realize what it is: a method of organization and modular code. What he is doing IS just as effective at organization, and it is just as modular. In essence it is his own form of OOP. To say that it is not standards compliant would be true. To say it s not the accepted method would be true. Even to say it isn't sharable between programmers would be true. But to say it is wrong or ineffective is not.

0 comments:

Post a Comment