Hi all. Whilst investigating Tangram, a thought occurred to me: wouldn't it be great to be able to specify the exact attributes that an object is allowed to have in the class definition, and have "standard" constructors, access and update methods use those as a master source for their actions?

You have to tell Tangram what attributes an object has, so that it knows how to store it in the database. So why not combine the two? Tao::Object facilitates just that. For instance, say you have a "Person" class that has attributes "name", "age" and "father". That would be represented in a Tangram schema as:

package Person; $schema = { fields => { string => [ qw(name profession) ], int => [ qw(age) ], ref => [ qw(father) ], } };

It's a simple data type, so what do you want to check, other than the name is a string short enough to go in the database, the age is an integer and "father"->isa "Person"?

Adding Tao::Object to @Person::ISA, you would be able to do the following without writing any class functions whatsoever.

my $father = new Person(name => "Charlie Vilain", age => 49, profession => "DMS II Guru"); my $self = new Person(name => "Sam Vilain", age => 22, profession => "Perl weenie", father => $father); print "My name is... " . $self->name() . "\n"; $self->name("Samuel"); # ok, sets name to "Samuel" $self->age("old"); # croaks, age is an int $self->father("Darth"); # croaks, "Darth" is not a blessed object print $self->mother(); # croaks, "mother" not recorded in schema

Now, I don't know about you lot, but I am finding this shortcut bloody useful, and it doesn't feel like a strict type straightjacket.

The meditiation is this: do you think that this is a useful shortcut, or will promote sloppy programming? Note: you can supply a custom function to check each attribute, and the destructor will automatically delete $obj->{father}, because it's a reference and that's generally a good idea to break potential circular references. See the POD for more.

In the Perl 6 PDF by Damian Conway, it mentions "More Declarative class specifications". Does anyone know offhand whether that will cover this sort of thing, or any other modules that I've missed that cover this sort of area?

I would also appreciate any peer review of the code, etc. If I get enough positive feedback from this, I may have to polish it up and CPAN it.

I can see other really useful uses for this, such as automatically generating a dia XML file from a set of module files that is a UML diagram representing your project. That would be ultra-cool, but would need some development to work.

srand 3.14159; print join("", sort{rand 1<0.5}map{$_^"\037"}split m{ }x,"qmptk|z~wOzm??l]pUqx^k?j"),",\n";

Replies are listed 'Best First'.
Re: Too lazy for constructors
by bikeNomad (Priest) on Jul 18, 2001 at 19:01 UTC
    Adding more of a declarative nature to Perl's object model is an interesting thing to do. What problem does this solve? To me, one of the appeals of dynamic languages like Perl, Ruby, and Smalltalk is that they don't have rigid type systems. That is: if my object supports the desired operations, it has the right type, regardless of what its superclasses are. Although your solution at least doesn't require specific inheritance, it does differentiate between blessed objects and regular scalars. But what if I had a blessed object that overloads '+' and other numeric operations and I want to use it instead of an integer for age above? Your scheme doesn't check dynamic type, only static type. That is, why do we want age to be an integer? Because we have some preconditions? Because we're doing math with it? Why can't I substitute an object of my choice that supports the required behavior?

    It does seem to me that you're trying to work around the major discrepancy in the Perl type system — not everything is an object. Maybe this solves real-world problems, I don't know. I guess it solves some problem you were having or you wouldn't have written it.

    My own experience with Perl is that type errors are a rare source of bugs. Of course, I mostly use objects, but I rarely run into problems because of number/string distinctions. (Perhaps those dealing with relational databases would care more, but this hasn't been a problem for me, since I don't).

      That is, why do we want age to be an integer? Because we have some preconditions? Because we're doing math with it?

      No. Because I want to be able to store it in a finite amount of space.

      Type errors may be a rare source of bugs, but they're one of the nastiest to track down... especially if they've been allowed to propagate beyond their original source, corrupting other data structures and otherwise wreaking havoc.

      I can't help but say that I think strict type checking is good, if sometimes a pain in the ass. Adding "soft" type checking like this gives you the good points without the "pain in the ass" aspect of not being able to, say, quickly tag an object with an attribute in a debugger. ie, you can still get around it with $object->{attribute}, but $object->attribute will always be checked.

      srand 3.14159; print join("", sort{rand 1<0.5}map{$_^"\037"}split m{ }x,"qmptk|z~wOzm??l]pUqx^k?j"),",\n";
Re: Too lazy for constructors
by frag (Hermit) on Jul 18, 2001 at 18:33 UTC

    Have you seen Class::Contract? I'd say that this does no more for sloppiness than that does. And actually, I'm unsure of why I should use this over that. (I'm not being snooty here, I'm honestly working my way through the Class:: heirarchy and trying to see the advantages of the different approaches.) You've got finer-grained types (int, string, real, etc.) and Tangram schema importation. Class::Contract doesn't have those features, but has a lot of other ones; could it be extended, using it as a base class (i.e. Class::Contract::Tangram?)

    I guess I'm wondering if this is something one would only use if they're using Tangram (which I don't know about), and whether it would suffice to extend an existing approach/module from Class:: (e.g. Accessor, Struct, etc.) rather than create a new one.

    Also, if you CPAN this, I'd suggest a different name than Tao::Object; something like Tangram::Schema or Class::Tangram would seem to be a better fit.

    -- Frag.

      You're a star, this is pretty close to what I'm after.

      There are reasons why I am using Tangram over, say, Class::DBI:

      • Support for Polymorphism in data types
      • Support for non-trivial relationships between classes (sets, arrays, etc)
      • Objects that contain/refer to other objects are automatically loaded as needed via a tied variable
      • Queries are in Perl, not SQL. This is achieved with a very clever trick - having a variable type that represents a "remote" (that is, not local) object, and overloading functions on that so you can do, eg $db->select($remote_orange, $remote_orange->{field} eq "value");. This returns a data structure that can be converted by the object data persistence engine to a SQL query.

      What I think is the direction from here is to refine Class::Contract to the point where it is suitable for generating storage schemas; be they Tangram or Class::DBI or Alzabo or whatever. "Scalar" is, by definition, of boundless length, which isn't too useful if you want to store it in a column of a relational database.

      Thanks for the pointer, I guess I'll take up this conversation with the Class::* maintainers. The POOP list, which seemed the natural place for this, seemed worryingly quiet.

      srand 3.14159; print join("", sort{rand 1<0.5}map{$_^"\037"}split m{ }x,"qmptk|z~wOzm??l]pUqx^k?j"),",\n";
Re: Too lazy for constructors
by Malkavian (Friar) on Jul 18, 2001 at 17:18 UTC
    A useful shortcut that works is a joy.
    I don't think that this promotes 'sloppy programming' at all.. Anymore than Perl promotes sloppy program because you don't deal with malloc et. al.
    From a quick read, and from how you describe it, it looks like a very useful too. :) I'll know more when I try and use it tho.. :) I'll give you feedback when I get round to doing that.
    Looks promising tho.

    Malk
Re: Too lazy for constructors
by Sinister (Friar) on Jul 18, 2001 at 15:32 UTC
    So far...
    this is way over my head. But that doesn't matter! It's sounds ultimatly cool.

    If the module comes out, you'll give us a holler right?

    Sinister greetings.
    perldoc -q $_