in reply to Thoughts On Object-Oriented Module Design. Input Sought.

Interesting post. Let me hereby attempt to tackle a few of your questions.
  1. Should my module's methods croak, or return error codes when they fail?
    This really depends. Generally It's ok for a module method to die if its life becomes unbearable due to a serious bug etc. To remain consistant, I suggest you stick with Croak.

  2. How much internal error checking is sensible? Some external calls will fail anyway if I pass duff data
    You should always do sanity checks. Check subroutine parameter count and type (scalar/hashref/array/...?) and die on invalid use. However, I remember coming across pieces of code that did too much of this kind of check. So, in the end, you have to keep your sanity checks to a level that is sane ;).

  3. Should I use generic methods that can both get and set, or is a single one each, e.g. $o->debug or $o->set_debug(1); print $o->get_debug?
    No, the way you do it now is great. That's what I'd do anyways ;). In the end, it's always easier to deal with just one method rather than two. Say, why should anyone keep two get_ and set_ methods when a context (lvalue etc.) in which a method is called is clear enough indication what the method should do (either of the two: get or set an object attribute).

  4. If I want to submit it to CPAN, how do I go about it? I know CPAN has instructions, but USENET seems a scary place, and I don't know if the code is worth anything to anyone else?
    I think by posting here you are already one step closer to getting your module on CPAN. Further, you may want to seek some advice on the name space you are using for your package. I believe there are special discussion groups/forums dedicated to just that ;).

  5. What works best, lots of methods to set things, or via the constructor in one go?
    In case of accessor methods, it's good to keep them regardless of whether your constructor is able to accept initial object settings. However, my suggestion would be to allow as much stuff initialized through your constructor method as possible. Otherwise, a user of your module would have to call 100 and 1 methods to properly initialize an instance of your RRS::Tools class before even being able to do any work on it. I suggest you don't make it a necessity by allowing as much (initialization) work to be done through the constructor as possible.

    Whew... well, that was my 3.2 cents there.

    "There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith

Replies are listed 'Best First'.
Re: Re: Thoughts On Object-Oriented Module Design. Input Sought.
by jreades (Friar) on May 05, 2002 at 17:29 UTC

    1. Should my module's methods croak, or return error codes when they fail?

    I generally feel that it is unhelpful for an object to take down an application because it's unhappy about its own state.

    Why? If you view objects and being bits of data able to be acted upon, the absence or presence of that data is not necessarily an event worth 'dieing' over. Particularly in the case of objects (which are liable to be imported and used by others) you should leave the choice of what to do up to the application developer.

    This is what's beautiful about Java's try{} catch{} syntax -- errors can percolate up to whatever level you care to let them, so errors can be trapped at any point of execution or simply cause the application to fail depending on the choices made by the developer.

    If you feel uncomfortable doing this, then a good backup plan is to have a flag available to the developer -- say, isErrorFatal() -- that allows the developer to choose whether or not a failure within the object is fatal to the application.

    This is, of course, a generalization, but I'd go with returning undefined and setting an error flag for all but the most serious cases.

    2.Should I use generic methods that can both get and set, or is a single one each, e.g. $o->debug or $o->set_debug(1); print $o->get_debug?

    Here I have to respectfully disagree with vladb. Beyond the reasons outline by Ovid (what if your method doesn't actually *accept* input), are issues with flexibility and maintainability.

    What if I want to create a wrapper object that only exposes the getter features of the RSS class? This contract is a lot more clear when there are separate methods to perform each action.

    From a maintainability standpoint I also think that the clearer your method names the less likely you are to have problems down the line when you want to re-write the class or update a specific feature. Compare looking for what needs to change when you have a method called getDatabaseConnection() versus one just called connection().

    More clarity is almost always better.