On Tuesday, January 14, 2003, at 12:55  PM, Dave Rolsky wrote:

   use DateTime;
   my $dt = DateTime->new( 'MySQL' => $mysql_dt );
   print $dt->to_string( 'MySQL' );

   use DateTime;
   use DateTime::Parse::MySQL;
   my $dt = DateTime->from_mysql_datetime( $mysql_dt );
   print $dt->to_mysql_string();
Um, yeah, the second is _much_ clearer.
[...] And if someone wants to build a separate implementation of the DateTime interface, like the TAI64 code, how will they be able to integrate with those parsing/formatting modules, short of blindly making their code a subclass of the primary implementation?
Yes, other implementations will blindly inherit from the base class. That's ok. For example, it'll want to inherit things like strftime and so on.
My suggestion would be that strftime also be placed in an external module.

package DateTime::Format::strtime;

sub string_to_rdsec { ... } # strptime

sub rdsec_to_string { ... } # strftime

This same interface could be used polymorphically for any date parsing/stringification library, and can be used directly by other modules, in addition to via a DateTime object.

Users could be isolated from this behind the current interface:

package DateTime;
require DateTime::Format::strtime;

sub strptime {
(shift)->new( DateTime::Format::strtime->string_to_rdsec( @_ ) )
}

sub strftime {
DateTime::Format::strtime->rdsec_to_string( (shift)->as_rdsec, @_ )
}

Modules like Date::Discordian or Date::Maya, which have no internal storage format and only exist to convert to and from other calendar formats, could easily be refactored to follow this interface.

my $dt = DateTime->new( .... );

print $dt->to_string( strftime => $fmt );
# Calls DateTime::Format::strtime::rdsec_to_string($rd, $sec, $fmt)

print $dt->to_string( 'Discordian' );
# Calls DateTime::Format::Discordian::rdsec_to_string($rd, $sec)

Your first option is not on the table.
Er, why not?
Cause I don't like it.
Ouch.

Some decisions have to be made by fiat, because as we can see there are lots of people with different, conflicting, valid opinions. But in the end, we need one consistent API. Since I'm in charge (FWIW) that means I'm the one who gets to decide what goes in and what doesn't.
I agree that a certain amount of that approach is needed, but taken to extremes this may doom the project to being just another contender in the date/time space, rather than the open framework everyone standardizes on and interoperates with.

The options on the table are: [...]
That's a straw man -- AFAIK, nobody's suggesting this kind of API.
I was, actually.
OK, sorry for the confusion.

Decorators are a dynamic composition of objects, nestable such that you can stick one decorator in front of another, and each one is provided by a different class and so has its own namespace and inheritance tree.
Thanks, I know what a decorator is in GoF-speak ;)

This achieves exactly the same thing as a decorator, without a whole stack of objects needed.
Regardless, the point I've been trying to make is that we don't want Decorators.

We want something more like Strategies (ie, given several similar algorithms, rather than having a bunch of different methods or a big case statement, put each in its own class and call them as needed):

http://c2.com/cgi/wiki?StrategyPattern

On Tuesday, January 14, 2003, at 01:07 PM, Dave Rolsky wrote:
I'm very strongly opposed to something that just passes random strings into new() and then loads the module on demand.
They're not random strings, they're class names; passing classes as arguments is common OO framework practice.

We could turn off on-demand module loading, or default to off unless you explicitly request it, if that part seems undesirable.

-Simon

Reply via email to