Posted on 2005-11-16 20:00:51-08 by jdhedden
Conventions - Object::InsideOut vs. Class::Std
When reasonable, Object::InsideOut tries to do things the same as way as Class::Std (e.g., :Private, :Restricted, :Cumulative and all the ":X-ify" method attributes). However, as much as I admire the work that Damian Conway put into developing Class::Std, I still found it to be only half-baked: Its conventions were ad hoc, inconsistent and inflexible. Here are just a few examples:

1. Class::Std lumps together accessor designation and ->new() argument specification as part of the :Field designation in an ad hoc manner. Object::InsideOUt logically separates the two because not all ->new() arguments necessarily tie directly to a field.

2. Class::Std uses a mixture of attributes and specially-named methods. Object::InsideOut is more consistent in using attributes throughout.

3. Class::Std does not allow control over the object ID. Object::InsideOut is more flexible in allowing the developer to specify the object ID if needed.

Basically, I had to break a few eggs to make my omelet. However, I don't feel that there is such a great diversity between the two. Consider the following comparison (sorry, but I can't get it to format very well):

Class::Std Object::InsideOut Class declaration use Class::Std use Object::InsideOut 'My::Class' use base 'My::Class' Object creation ->new({args}) ->new(args) or ->new({args}) Object initialization BUILD() :INIT Object ID specification (N/A) :ID Object ID ident($self) $$self Object cloning (N/A) ->clone() Object replicator (N/A) :REPLICATE Object destruction DEMOLISH() :DESTROY AUTOLOAD support AUTOMETHOD() :AUTOMETHOD Field designation :ATTR :FIELD Get accessor :ATTR(:get<name>) :FIELD('GET' => 'name') Set accessor :ATTR(:set<name>) :FIELD('SET' => 'name') Combined accessor (N/A) :FIELD('ACCESSOR' => 'name') Restricted methods :RESTRICTED :RESTRICTED Private methods :PRIVATE :PRIVATE Cumulative methods :CUMULATIVE :CUMULATIVE(BOTTOM UP) :CUMULATIVE(BASE FIRST) :CUMULATIVE Chained methods (N/A) :CHAINED / :CHAINED(BOTTOM UP) Overload methods :STRINGIFY :STRINGIFY :NUMERIFY :NUMERIFY :BOOLIFY :BOOLIFY :ARRAYIFY :ARRAYIFY :HASHIFY :HASHIFY :GLOBIFY :GLOBIFY :CODIFY :CODIFY :SCALARIFY (N/A) Object serialization ->_DUMP() ->dump() Object loading (N/A) ->pump() 'require' not supported automatically supported 'threads' not supported supported 'threads::shared' not supported supported Internal error handling Carp Exception::Class

The only significant difference between the two classes is in specifying the args for ->new():
Field initializer key :ATTR(:init_arg<key>) my %init :InitArgs = ( 'key' => { 'FIELD' => \@field } ); Field default :ATTR(:default<value>) my %init :InitArgs = ( 'key' => { 'DEFAULT' => value } ); Mandatory arguments N/A my %init :InitArgs = ( 'key' => { 'MANDATORY' => 1 } ); Key pattern matching N/A my %init :InitArgs = ( 'key' => { 'REGEX' => qr/.../ } );

So, yes, there are differences, but they are either superficial, or favor Object::InsideOut for one reason or another.
Direct Responses: 1532 | Write a response
Posted on 2005-12-29 16:04:13-08 by melo in response to 1326
Re: Conventions - Object::InsideOut vs. Class::Std

Hi Jerry,

I'm a newcommer to Object::InsideOut and so far I like it very much.

Regarding your three bullet points at the top of the previous message, I only have an issue with the first one.

1. Class::Std lumps together accessor designation and ->new() argument specification as part of the :Field designation in an ad hoc manner. Object::InsideOUt logically separates the two because not all ->new() arguments necessarily tie directly to a field.

I agree that the separation makes sense when you want to have parameters to the :Init method that aren't fields, but I would say that this is something not that comon. I would bet that most :Init parameters are fields, and in that case, we are splitting field information in two places.

Do you think it's useful to add Mandatory and RegExp to the :Field declaration? For me it woul make all the field meta-data in a single place.

Comments?

Thanks,

Direct Responses: 1533 | 1546 | Write a response
Posted on 2005-12-29 18:22:40-08 by jdhedden in response to 1532
Re: Conventions - Object::InsideOut vs. Class::Std
This could not be done in a clean manner. It would require the :Field declaration handling code to actually manipulate the :InitArgs hash (which is external to the Object::InsideOut code) to place the required information in it.
Direct Responses: 1534 | Write a response
Posted on 2005-12-29 18:28:36-08 by melo in response to 1533
Re: Conventions - Object::InsideOut vs. Class::Std

Hi,

Ok, no big problem. I do like Object::InsideOut anyway :).

BTW, for other Object::InsideOut users that happen to use TextMate editor, see this screencast. It's my first screencast, a bit rough, but you should get the idea. I plan to make a better one late on after work :).

I'll make the snippets I use available later on, and I'll post directions on my blog.

Bye,

Direct Responses: Write a response
Posted on 2006-01-01 15:39:35-08 by earl in response to 1532
Re: Conventions - Object::InsideOut vs. Class::Std

HAPPY NEW YEAR!

I just wanted to say that I have exploited the separation between the arg separation and the :Field designation.

In early version of a class, the arg specification mapped directly to fields. Then, the methods used the fields to build SQL statements. In a later version, I used the argument specification to build SQL statement fields eagerly. In still later versions, I used the argument specifications to prepare statement handler fields eagerly.

So, while it is more common to map the arg specs to fields, I wouldn't say that breaking that convention is uncommon.

One of the strength of Object-InsideOut is that it is flexible. It doesn't enforce too many rigid coding convention that prevent you from doing what you want to do. If a class builder enforces too many coding conventions, it becomes difficult to integrate the module with existing legacy code. For example, prefacing getter methods with "get_" is an OK convention. However, I didn't use that convention in my current code base. If I want to replace an old conventional hash-base class with an inside out class, I may not want to have to change the names of the getter methods. When trying to attain market share, you want to support current conventions and keep inward migration cost low. Once you have market share, then you introduce your own specific conventions to make outward migration cost high.

Direct Responses: Write a response
Perl Weekly newsletter
A free weekly newsletter for people who are busy to read all the blogs. click here to check it out.