Archive

Archive for January 5th, 2003

Camel Poop

January 5th, 2003 No comments

In response to the Camel POOP article on Evolt, Simon Willison complains: I have no
intention of starting a language war, but my God this is ugly. Still, I guess it must work for some people.

As a user and fan of Perl, I have to agree. This is exceptionally ugly. In fact it’s the sort of thing that turns people against Perl. Thankfully OO in Perl doesn’t have to be like that.

Let’s take his Person class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#class Person
package Person;
use strict;
use Address;    #Person class will contain an Address
 
#constructor
sub new {
  my ($class) = @_;
  my $self = {
    _firstName => undef,
    _lastName  => undef,
    _ssn       => undef,
    _address   => undef
  };
  bless $self, $class;
  return $self;
}
 
#accessor method for Person first name
sub firstName {
  my ( $self, $firstName ) = @_;
  $self->{_firstName} = $firstName if defined($firstName);
  return $self->{_firstName};
}
 
#accessor method for Person last name
sub lastName {
  my ( $self, $lastName ) = @_;
  $self->{_lastName} = $lastName if defined($lastName);
  return $self->{_lastName};
}
 
#accessor method for Person address
sub address {
  my ( $self, $address ) = @_;
  $self->{_address} = $address if defined($address);
  return $self->{_address};
}
 
#accessor method for Person social security number
sub ssn {
  my ( $self, $ssn ) = @_;
  $self->{_ssn} = $ssn if defined($ssn);
  return $self->{_ssn};
}
 
sub print {
  my ($self) = @_;
 
  #print Person info
  printf("Name:%s %snn", $self->firstName, $self->lastName );
}
 
1;

There are numerous problems with this. Let’s start from the top.

  1. The ‘use Address’ is completely needless. Misleading comment notwithstanding, nothing in the package actually uses the Address module, so there’s no need to load it.
  2. The constructor is complete overkill. The object is going to be a hash, but in Perl hash keys autovivify the first time you assign to them, so there’s absolutely no need to set up lots of keys that contain undef. As the constructor does nothing, it could simply be sub new { bless {}, shift }.
  3. The data methods all do exactly the same thing. This breaks one of the cardinal rules of programming – Don’t Repeat Yourself. firstName, lastName, address, and ssn are all trivial accessor/mutator methods. They could all be abstracted away in a variety of methods, but as this is Perl, someone else has already done that for us. Class::Accessor lets us set up all these methods simply by doing:
    Person->mk_accessors(qw/firstName lastName address ssn/);
  4. The constructor doesn’t all you to set object data. It’s pretty much a matter of style, but in general it’s nice to be able to instantiate your object with data, rather than having to call all the mutators in turn. As this is a simple hash-based object (as with 90% of all perl objects) Class::Accessor gives us a default new() as well that allows us to pass a hashref of the data members.

So, this entire class could be replaced with:

1
2
3
4
5
6
7
8
9
10
11
12
13
package Person;
 
use strict;
use base 'Class::Accessor';
 
Person->mk_accessors(qw/firstName lastName address ssn/)
 
sub print {
  my ($self) = @_;
  printf "Name:%s %snn", $self->firstName, $self->lastName;
}
 
1;

Similarly, the Employee subclass, which simply adds ‘id’ and ‘title’ data members, and overrides print could become:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package Employee;
 
use strict;
use base 'Person';
 
Employee->mk_accessors(qw/id title/);
 
sub print {
  my ($self) = @_;
  $self->SUPER::print;
  printf("Name:%s %snn", $self->id, $self->title );
}
 
1;

(The example on the site makes no sense as it keeps referring to an Address class that doesn’t seem to exist. I’ve assumed that the overridden print should be outputting the extra data members of this class instead…)

Then, instead of the longwinded test program (with a eval to catch exceptions that’s completely needless as neither class throws them):

1
2
3
4
5
6
7
8
9
10
11
12
13
use Employee;
 
#create Employee class instance
my $khurt =  eval { new Employee(); }  or die ($@);
 
#set object attributes
$khurt->firstName('Khurt');
$khurt->lastName('Williams');
$khurt->id(1001);
$khurt->title('Executive Director');
 
#diplay Employee info
$khurt->print();

We can simply have:

1
2
3
4
5
6
7
8
9
10
use Employee;
 
my $khurt = Employee->new({
  firstName => 'Khurt',
  lastName  => 'Williams',
  id        => 1001,
  title     => 'Executive Director',
});
 
$khurt->print();

It may not be as nice as OO in some other languages, but it’s a lot nicer than the example in the article… and as it’s Perl, there’s plenty of other approaches if you want to dice it another way.

Tags: ,

Importing Radio posts to MT

January 5th, 2003 No comments

A couple of people have asked for more pointers on exactly how I got my Radio posts into MT. So here’s some more detailed information.

Firstly, I ran into lots of problems with Radio seemingly caching macros. When I edit radio macro files and resave them, Radio doesn’t seem to notice the changes for about 5 minutes. Which is far ideal for the programming approach I use (particularly in a language I’m not that familiar with, such as UserTalk), which basically involves keeping the code running at all times (code a line, save it, test it still works). I would never survived as a programmer in the old days of coding ‘offline’.

I originally thought this was to do with my set up (I have my PC’s C: drive mounted via samba onto the linux box on which I do most of my programming, as I find it much easier to code in that environment), but using Notepad didn’t seem to make any difference, and there are a few scattered references to this problem littering the Userland noticeboards.

Anyway, I ended up having to code in the scratchpad instead. The script is below. It was cut-n-pasted from Radio’s outline editor so the formatting is a little strange, but it should do the trick. This can either be used as a macro, or, as I did, or by adding it to the scratchpad and calling <% workspace.showAll ()%> in a page (I just created a new page in my Radio Userland/www/ directory that had that in it.

This outputs all my posts in XML, with the titles and bodies wrapped in CDATA tags. I then wrote a simple Perl script to turn this into the MT input format. You then import this into MT following the instructions in the manual.

I’m sure this could all be tidied up some more, but hopefully it’s of some use to someone as is!

Read more…